queueing/0000775000175000017500000000000014620417652012271 5ustar morenomorenoqueueing/INDEX0000664000175000017500000000133214620404470013054 0ustar morenomorenoqueueing >> Queueing Networks and Markov chains Discrete-time Markov chains dtmcchkP dtmc dtmcbd dtmcexps dtmcisir dtmctaexps dtmcmtta dtmcfpt Continuous-time Markov chains ctmcchkQ ctmc ctmcbd ctmcexps ctmcisir ctmctaexps ctmcmtta ctmcfpt Single Station Queueing Systems qsmm1 qsmmm erlangb erlangc engset qsmminf qsmm1k qsmmmk qsammm qsmg1 qsmh1 Queueing Networks qnclosed qncmmvabs qncmmva qncmnpop qncmpopmix qncmvisits qncscmva qncsconvld qncsconv qncsmvaap qncsmvablo qncsmvald qncsmva qncsvisits qnmarkov qnmix qnmknode qnom qnomvisits qnopen qnos qnosvisits qnsolve Bounds Analysis qnosaba qncsaba qnomaba qncmaba qnosbsb qncsbsb qncmbsb qncmcb qncspb qncsgb queueing/doc/0000775000175000017500000000000014620417652013036 5ustar morenomorenoqueueing/doc/queueing.texi0000664000175000017500000001431014620411412015536 0ustar morenomoreno% Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2018, 2020, 2024 Moreno Marzolla % % This file is part of the queueing package. % % The queueing package is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by the % Free Software Foundation; either version 3 of the License, or (at % your option) any later version. % % The queueing package is distributed in the hope that it will be useful, but % WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or % FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License % for more details. % % You should have received a copy of the GNU General Public License % along with the queueing package; see the file COPYING. If not, see % . % This info file is taken from the GNU Octave info file \input texinfo @setfilename queueing.info @c The following macro is used for the on-line help system, but we don't @c want lots of `See also: foo, bar, and baz' strings cluttering the @c printed manual (that information should be in the supporting text for @c each group of functions and variables). @macro xseealso {args} @iftex @vskip 2pt @end iftex @ifnottex @sp 1 @end ifnottex @noindent @strong{See also:} \args\. @end macro @c @macro examplefile{file} @c @example @c @group @c @verbatiminclude @value{top_srcdir}/examples/\file\ @c @end group @c @end example @c @end macro @c @macro GETHELP{file} @c @end macro @c @macro GETDEMO{file,n} @c @end macro @c FIXME: The following macros are workaround to fix erratic behavior of texinfo @iftex @macro lambdack @lambda_{c,k} @end macro @end iftex @ifnottex @macro lambda lambda @end macro @macro lambdack lambda_@{c, k@} @end macro @end ifnottex @ifinfo @format START-INFO-DIR-ENTRY * queueing: (octave). Queueing Networks and Markov chains analysis package. END-INFO-DIR-ENTRY @end format @end ifinfo @c Settings for printing on 8-1/2 by 11 inch paper: @c ----------------------------------------------- @setchapternewpage odd @c Settings for small book format: @c ------------------------------ @ignore @smallbook @setchapternewpage odd @finalout @iftex @cropmarks @end iftex @end ignore @defindex op @c Things like the Octave version number are defined in conf.texi. @c This file doesn't include a chapter, so it must not be included @c if you want to run the Emacs function texinfo-multiple-files-update. @include conf.texi @settitle queueing @documentdescription User manual for queueing, a GNU Octave package for queueing networks and Markov chains analysis. This package supports single-station queueing systems, queueing networks and Markov chains. The queueing package implements, among others, the Mean Value Analysis (MVA) and convolution algorithms for steady-state analysis of product-form queueing networks. Transient and steady-state analysis of Markov chains is also implemented. @end documentdescription @ifnottex Copyright @copyright{} 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2018, 2020, 2024 Moreno Marzolla. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. @ignore Permission is granted to process this file through TeX and print the results, provided the printed document carries copying permission notice identical to this one except for the removal of this paragraph (this paragraph not being relevant to the printed manual). @end ignore Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. @end ifnottex @titlepage @title The Octave Queueing Package @subtitle User's Guide, Edition 1 for release @value{VERSION} @subtitle @value{VERSIONDATE} @author Moreno Marzolla @page @vskip 0pt plus 1filll Copyright @copyright{} 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2018, 2020, 2024 Moreno Marzolla (@email{moreno.marzolla@@unibo.it}). This is the first edition of the Queueing package documentation, and is consistent with version @value{VERSION} of the package. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the same conditions as for modified versions. Portions of this document have been adapted from the @code{octave} manual, Copyright @copyright{} John W. Eaton. @end titlepage @contents @ifnottex @node Top @top This manual documents how to install and run the Queueing package. It corresponds to version @value{VERSION} of the package. @end ifnottex @c ------------------------------------------------------------------------ @menu * Summary:: * Installation and Getting Started:: Installation of the queueing package. * Markov Chains:: Functions for Markov chains analysis. * Single Station Queueing Systems:: Functions for single-station queueing systems. * Queueing Networks:: Functions for queueing networks analysis. * References:: References. * Copying:: The GNU General Public License. * Concept Index:: An item for each concept. * Function Index:: An item for each function. @end menu @c ------------------------------------------------------------------------ @include summary.texi @include installation.texi @include markovchains.texi @include singlestation.texi @include queueingnetworks.texi @include references.texi @c @c Appendix starts here @c @include gpl.texi @c @c INDEX @c @node Concept Index @unnumbered Concept Index @printindex cp @node Function Index @unnumbered Function Index @printindex fn @bye queueing/doc/qn_closed_single.png0000664000175000017500000000654014620415616017057 0ustar morenomorenoPNG  IHDR<T|/PLTEٟ IDATxݿrܸpPɛIsxWH) $Mc Wh5*e ZlazD?w.$W ]??b."7_!Y&^Wz^šJж򏸙, W]%fBO?LKA _  goW @߲ ̇.1v/m,_[ڊBߣe}YWYo8-TKGv͇$c|JN"MMiE[P銃9ſΕy 04t2PͲ!YгVyI@`L,$$ihg! h;tM4t3@ë|ȔBP|:">R?*.U /#Pw|yJd&%k{qT׬zy/Z}{qx2d/Z|D &PCeJD)Jȏ=JătB##Z}g:BHzMA{Q?S6xle@`>Ty$|(D#Pj6JPPdg_B6u.dmnAJ<-,D2f!ߧJBz|^d/vw P(1SSWLHQ[p¯՚lK/F!Z2q9HE!B S{LB 8$i3h/U {q)(D8^gg׽!gy3(X}4q.ֽ(P? ՞u( Hv7泡ڏ-D2rz?$a0a3ށJ$Ҁɐ% D؍+]Oy[nA _.ٶ)KZQ᧾K&v̾ cCO ]2Av}hFK&W} fR]2Y|9@f1j: :hDGVpR) h#/iY:@[OJ@{@p|"Zf?a7-/lJ@T,š`ǃƞw2Y<&kJC3 ~urIIHuZbx%KGpD!%k+v瀞,Ue6?"Qm]̜#A4B|oroO _i)~64ޞc?vF#yW"硣cA}# KABe4T$ĆWT{p ͣn 6?e-= MEeax,^WQP 6W_J@S㎻.Д VD({UAi}C&tAg!1 `&v=1t ڧupOMe PhR ]pk_:С 0h؈]ApƤ. C BǏb#Z:t}|\3 HٟUp:=C9Mա 1  ^Td;= t=2T?.BvߎŠ1t$Y, ]fV#&t>`CsG&t^ ! ` 0-f["ίq>LƤ4 0 +&0JjBh4S{{ >6$8y8ڂj$Pu~T yLOӇxPd? BUG Džɽ`'e/HSs(nُ̈́p!t吆j$  nh"2 X(> B~> ҃rDμ\gA}< YPi~X͆ѯ 5bLFNYjt' 9Wx 픂vGMi$T-~@*B!B͡- ZnH] _@hk }LJ)305HD-C M@^g?JBJ-!l-]f7 a!Tڦ;3je;FGI6M$ WL4 L̊{ =Z84H#j&ǘ C0|:jX7= SDHDZgx{؋B]QN|țߚg fB'!s B+d6,t B ,t B0t CP t<, Ba". Ba.Է2}ӆ _H/tLnP~/ P  hC5$tC|u/oeIENDB`queueing/doc/qn_closed_multi.fig0000664000175000017500000000274714620404470016712 0ustar morenomoreno#FIG 3.2 Produced by xfig version 3.2.5b Landscape Center Metric A4 100.00 Single -2 1200 2 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5310 5040 270 270 5310 5040 5310 4770 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6930 5580 270 270 6930 5580 6930 5310 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6930 4500 270 270 6930 4500 6930 4230 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6300 5310 6660 5310 6660 5850 6300 5850 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6300 4230 6660 4230 6660 4770 6300 4770 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 4 0 0 1.00 60.00 120.00 5580 4950 5850 4950 6030 4500 6300 4500 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 6 0 0 1.00 60.00 120.00 7200 4500 7470 4500 7470 3960 4770 3960 4770 4950 5040 4950 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 4 0 0 1.00 60.00 120.00 5580 5130 5850 5130 6030 5580 6255 5580 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 6 0 0 1.00 60.00 120.00 7200 5580 7470 5580 7470 6120 4770 6120 4770 5130 5040 5130 4 0 0 50 -1 0 12 0.0000 4 135 375 5130 5490 CPU\001 4 0 0 50 -1 0 12 0.0000 4 135 480 6705 6030 Disk2\001 4 0 0 50 -1 0 12 0.0000 4 135 105 5220 5085 S\001 4 0 0 50 -1 0 9 0.0000 4 105 75 5325 5141 1\001 4 0 0 50 -1 0 12 0.0000 4 135 105 6840 5625 S\001 4 0 0 50 -1 0 9 0.0000 4 105 75 6945 5681 3\001 4 0 0 50 -1 0 12 0.0000 4 135 480 6705 4950 Disk1\001 4 0 0 50 -1 0 12 0.0000 4 135 105 6840 4545 S\001 4 0 0 50 -1 0 9 0.0000 4 105 75 6945 4601 2\001 4 0 0 50 -1 0 12 0.0000 4 135 585 5490 6300 Class 2\001 4 0 0 50 -1 0 12 0.0000 4 135 585 5490 3915 Class 1\001 queueing/doc/qn_closed_multi.png0000664000175000017500000000671614620415616016735 0ustar morenomorenoPNG  IHDR<SPLTEٟ IDATxݿnpS4d1|+XEy ҤLra4 ~xf"2\lyeXKF}(`ܨGgFs,uv=KUOTlG1+1PK[ 5qK5%Ou'A=ݖqPCkzM@gгM$t/2 DnhrR0 ')9-ٗ!5"Ov]ZK}fB|\H%|CH-;[DB|uhNV-c}^ym7E 1 !# m$Ҝ#t:BG#t:BGCzfanu2I[ 폯a;ڒI<c[FCj մhH%zp_P#DBu)^2sIJ>#!4dN:YH|Y-L(L@G>ݛOfEDAz:q(O OG6@e Dz~J' R \SGC*@kSAП6t. gDE"J~C 'yLCj*b fAá#tZXо@֠U5 I $6_ EֆTMwKH'IB狡v0$$KՁPlkq. +$+ˠ~-a94iyxB@"2HfpP u2h4M߉RA_Awc?TwvDxjO>}v7(+dX<¡ 6?# @VF5ECuHB B r*cT5 rډD^Bv#;(c [fQNkA gэu(h>DAMXM4iF_fhӲ= nKӊ583e<ҽA:!_lg]>8H} >Bv IA"36!!Q=X,ؙ=sZIG`4}a馇;:+Pmv}{kms^XsډłtF㡡M.My44w1 AX3hQUٰ $84`T/8A@!s R {rZPY@bJ>}QRxZgQ:!da&CMyџ@4Ke S0<9կA&&mSp> PЯeZ i|:@ ^NC"?n NA5Bn>Qϻ? B֥^O6<]!P 3 -tyթ{c|5A눞!x:-Ԑw#H]fY$x?n4ew?J W$TsZ9 M5?rH%dqI肓+M_-ﻧHw^P^`A߉'#cXZ~jY ySQ^H$6O ,J\s}.n/v QQfP.F]@t*%tqPHh XЗHVh0-qb ԯl= L:LQB)2+fЧU""4E^+dNA+ {̂!_jы>tAĬP!8]g| jB,Bp桟&ECd q/4k 0ᚮ.(A,rjv0fnSc}>]:nikfVaC̶R9%)U.CfeW,1g杛%:1d='y("O7trC!7tO7trB!'tA4>vrC@? ]0u{W j  7tAdM  Oh(tA-΁Lߟtw$C,>9ҡ W 9  N-n0&HCv JË4[DC0A"܂0 !;$u_z|q  y)E$هDxXchH,17t0D̺UUWֲQPD jV FJTJ\4V8]P |*tk=ڳ!TΌފt/p0"ߊVT*A UۚHH&#!16!!QdžZB}vcRɬP߿ufn?άPcو9BGND6B4QHnB f  nMi w|diGBj&wH.d3 f/ 6D.0$<4.0sPو ]pBB*t.4.(!DFB2t䈄ds ]dN *ρt}$ClPTlT6ro Jv}ro 6+XZ^v[O̵d<[[;^43o@U= ]T?$bE{BAVALCPS4P55t<{ bt_i^cڊ(g2xָMY!o2rR ]4N6#yG@r 1pݒ}\RӪ/QP9|k-ig4XfR1X Q~r]w'ɟ_hx&얝 ]wIhl?SduhNVM}^ym2Nϋ BYl IRIENDB`queueing/doc/qn_closed_multi_cs.png0000664000175000017500000000646414620415625017422 0ustar morenomorenoPNG  IHDREOPLTEٟ IDATx͎6p֧V{ z^e " W n;o_ |F#.IH)"ݍ7"ؒ~)Gz4a[^zDZ]{-C?IP)ۅot?yMOt_(#h^ofR_(1٥i(3E~9D%AKgOpm8 Y&tB sCSs=::::::IxX}exȕ2?H|Hۗ<bfy܇}jl|O'AXz% }TJ|E\}}G ra^JY)y*WhRc-϶(n zʹ6m+z!گk'DMmXHhۢ|º9pB rcV/mQP0HD+jۼ-$ьa-YW~|5Ot’rFDߋ1=Li~wk4P@fg#{6(Ԟ{X F؝&.Tֈ&('%ؖ.QܧeܟV?}$TU-$(h>Z4 V-4'GI +f]Em''uDZ'R<|z{ht*]MG{%hO!])SOQ~N.}ڋFXV-Aw<%=U+'کMH^ƣYP8-#lEQv/(k-iVSXfUfu hj>Bh^γhvDBK!nh> ~)5郀^Ei?7h>+Ǣ>vEQznFC3n@gݗ "pn޷4iFaMϰ!E+ ]S4@ɢчv&*<Q E0Ki zxDQ"4B,:(6BA0'>߉sCe7? <+ctKMQPz ryJ>Rg]@tۧŻl[h%*E}Rrm&9  `GCt ]Bc,vPif7}X>Nnm]m*`{dJ[4;vTjkԼwFI 4emu}vWtCwzPUpACSyY2oӋVہ`F;֎(߁7=ЬC.֖`6A"T;(ВQ tPOQ"IQٷAC(6h%qGcvjqh!m@!l&4tOziDpC K!l Gjs;nEv`FAV*ζ0(nl˫_E:/,A_Փ5} `7GE `h>2ޓ4|KήSη*zLVث9}DY/r足%=͖\WJ'm;?._V5 FМQ(؝Q(%}mjvw` `@Q廠f? JN{jz'=4h7}GB+n-P(teGp[+n+0}4Z`xt(@{FUWIhd%P ]kġ@{?:v\}0ک!P(Q FuϾ @+ `+M_9j 'oN虠nGgRLNT~sB=+G:,P9 9)B6]7u&9<:B`ht'*qhuDG-":蕺>j4bҠ7fm?4h&o7BRWt{ДW^Q\M]|Wl۠Ez]=yF4{ ݉( ǫz4&4-Nh=SUVjWViO#$\f%Jk,?_^ҀÁfIENDB`queueing/doc/qn_open_single.pdf0000664000175000017500000001570614620415627016542 0ustar morenomoreno%PDF-1.5 %쏢 %%Invocation: gs -q -dSAFER -dNOPAUSE -dBATCH -dCompatibilityLevel=1.5 -sDEVICE=pdfwrite -sOutputFile=? -dPDFSETTINGS#/prepress -dMaxSubsetPct=100 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoRotatePages#/None - 5 0 obj <> stream x}Vˎ7 +t`hQO?rޝ 0ۇ~JݢZ3,=*EDuֵ,C~HGfݷ.5]$N. ˅+q>Dr-gm9 RPpP UT#%{ )A|6C;$VGiRV9R(ilXC_k]s 2O.#wqBVM]Ʌ- !B"9 \J6 Q I$VD_Vkֵ_"g8$h|E4&Wa\X1r+;:g١V*3SHj&@.M8v;2kTN=kmRAUFc84lEmDa[om3/꨸T7֌2pQdXeOE,޽~]c =S!f3n*endstream endobj 6 0 obj 915 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 12 0 obj <> endobj 13 0 obj <> endobj 8 0 obj <> endobj 10 0 obj <> endobj 16 0 obj <> endobj 9 0 obj <> endobj 14 0 obj <>stream x{PWƿ$w֥QR4aX] +* ]D ! &K A+A@@WRT]zNg]mgߏ9~ԝ{;999KSB?i \4FHVBhnP#Eԟ/lZ:m.Xgv%鵻k%FOdkBWXzdvB#4eNVȕ=ZuO׆ӴY9j_}fGDnUGgf_boVS"j1&GvR(j 5KRA/y^JHzo_ B0.GE@iA+1])e8ؐXyvǽ[?D,C z1["+aI}s B;GJ2T;Qt*qO|S~@s?S3=~;KBw^oSN b0hpq Ő8κ\gy+i <ܱ8#YVٍ.c%,f5P')j6y-aA_Ka[,؂JMخ'dc6q$)S5gJ#'awUj\ckAK{[7+s{ej0vI_g+Zz኏~13O-[^7 w wdl 6{Dy ^X™ha|_߽#&<枵.׹YzE]Yp$>ؚ}dW@puܩڍIw;i*rlF3l~Oo]{=B bENNtNGg[m 2ct`Nn޼8/VNXL~7s]% 0}~lo0%/-;!~]=$fm׮dĽ ws\ &8Rx$Z74=x+Zk*ݚ*U~w1ɶ˲K}jSלWsȭK}xaȲ$}fT2֕캁GvsN6 ǍN `r*{݆\E%Dm؎mKBIAԫ{hMf4U`2rCGۇeMx:x%i jBZ@=.r(߸> endstream endobj 11 0 obj <> endobj 15 0 obj <>stream xcd`ab`dddM1~H3a!]c VYyy0t0w~M軟wo ,*)YA i%E: E% F I @ļĢ] uDIMJId```{ߏu-$p9IGVѽ{iѬIeS&_v") a᪒gQ^ޝ]8z]Җ% JtvvMn]5mawC{+-KΎh[խ0csyx20Jd endstream endobj 17 0 obj <>stream 2024-05-13T15:54:31+02:00 2024-05-13T15:54:31+02:00 fig2dev Version 3.2.7a qn_open_single.fig endstream endobj 2 0 obj <>endobj xref 0 18 0000000000 65535 f 0000001442 00000 n 0000006414 00000 n 0000001383 00000 n 0000001232 00000 n 0000000228 00000 n 0000001213 00000 n 0000001507 00000 n 0000001619 00000 n 0000002181 00000 n 0000001944 00000 n 0000004368 00000 n 0000001548 00000 n 0000001578 00000 n 0000002460 00000 n 0000004582 00000 n 0000002092 00000 n 0000004979 00000 n trailer << /Size 18 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 6597 %%EOF queueing/doc/qn_web_model.png0000664000175000017500000001034414620415616016177 0ustar morenomorenoPNG  IHDR}%PLTEٟIDATx͎ܶp ƈz(XTu }؈gK3Ǟ}«C 9,IQR(i$-"jdI?}Dr<$euo0̃4{.~Ls]$A@d y?:B. 21\,,F?,ɫ~C4]8<]C݇#Y'~ %/Pz#Hɓpo:лg+JsV!kHO:~t+B.` 7; 0NPvtC;]J޿bsJm m&\ܔPo/b_p| KHeϘFpc }aw'tMyF"2ƥ ^.t.>%W(=B'aF@뢐^ً')=5O5>::9:uUX$Eق.^>`#% #tdo` uivgp|hivgwvg=uzYYCDVWŃH 5}ggg ݳ7Sn+ѽk6/MU%mv`?W;Uyƺ so۷.+T/S; ܍ >Sا{vrhJ%k[^3Dk_v5g/hH<ȅ[T; ci_z`w7mnvqQu\ɡM&He`nw"S]:-e_lI2[β}]$鿾ء}yًpϑċt`v8n7;`תKFr7sJ覅Gp_n. u]if})_Sq0@!w?YꢱI#ٳ1F8."ycdͽ%d|+rf8n[wG#7tbv;p0wo_wDŊ\#gB12`/q|ߗixv,߈@o<$apQTWRg- 46yj>RtrBU?m{y,"¼ZJNS7nXw^.R+4 q^NW\Q5Sbߗ'nI&7?MlVԗ)ͦU7oL5~P) 废ieMk(N*_UTD>8_q {q\l~ưnjW]plvŅ,͏ˎt+v8.43AW~Y/?b D,ҹRUJzVg.|i-tHbݦ[Ή=P.,6,|rʻ)N4-T\t.r嘦;{w,gq,}9<'͟#tA֪9EB\Ti#7oO1JEMDz+!芇ҧ n~]@bÌefS$,6ˏR+nvOrJ*띵m]^Ir˪岒LUNT[\܂f[/7[4r̘.M?CϯqP<+ngƹ .φ5 ]\v{ԣ=W3.(>o컁7q~ 컐cƾ Μ;nXޚni$Xp{\tqFsG1Zv#!h%;sT&}hnC}߶P1P3P~5+IJP>9[Ǝ+nCv}5#7k7oROम_I]ޖ(ҪkrZi~MuY~x .x~+y0ݞ ?er~M4%u.}*\\?Wf߷@>ɗ|Fj'ca\p "q2U+Su.5>?-מ>]],ԜNy{OjTuI =>Le/5Tcov7B[Qmz/im%3~8ͽҬ2 iM3Mw~Ip zR둗%E|;[iu_VyꇠF!eT_guP}skhnA㎖.32zf{+a\@nks? ̽D'X!5u2aϦ] z!vG19qO;וֹDt> zz$B޳OVK0JTֳ]] P,I.)vN;;;;;;;>ӣurz{n{•䟦ܕBq>mD9Kr\MW@2Ϧ+YwE\U<Ϻ+_gq}ֿ"Ϻ+pgyTYu>})Ϧ+Yui}\tQS,b8{IENDB`queueing/doc/qn_web_model.fig0000664000175000017500000000476314620404470016164 0ustar morenomoreno#FIG 3.2 Produced by xfig version 3.2.5b Landscape Center Metric A4 100.00 Single -2 1200 2 6 5130 4680 5850 5040 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5670 4860 180 180 5670 4860 5850 4860 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 5130 4680 5490 4680 5490 5040 5130 5040 -6 6 6390 4950 7110 5310 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6930 5130 180 180 6930 5130 7110 5130 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6390 4950 6750 4950 6750 5310 6390 5310 -6 6 6390 4410 7110 4770 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6930 4590 180 180 6930 4590 7110 4590 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6390 4410 6750 4410 6750 4770 6390 4770 -6 6 7740 4140 8460 4500 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 8280 4320 180 180 8280 4320 8460 4320 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 7740 4140 8100 4140 8100 4500 7740 4500 -6 6 7740 5220 8460 5580 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 8280 5400 180 180 8280 5400 8460 5400 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 7740 5220 8100 5220 8100 5580 7740 5580 -6 6 7740 4680 8460 5040 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 8280 4860 180 180 8280 4860 8460 4860 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 7740 4680 8100 4680 8100 5040 7740 5040 -6 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 6 0 0 1.00 60.00 120.00 8550 4770 9180 4770 9180 5940 4680 5940 4680 4770 5130 4770 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 5850 4770 6300 4770 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 7200 4770 7650 4770 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 6 0 0 1.00 60.00 120.00 8550 4950 9000 4950 9000 5760 4860 5760 4860 4950 5130 4950 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 7200 4950 7650 4950 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 5850 4950 6300 4950 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 7200 5670 6300 5670 6300 4050 7200 4050 7200 5670 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 8550 5670 7650 5670 7650 4050 8550 4050 8550 5670 4 0 0 50 -1 0 12 0.0000 4 135 105 5625 4905 1\001 4 0 0 50 -1 0 12 0.0000 4 135 105 6885 5175 3\001 4 0 0 50 -1 0 12 0.0000 4 135 105 6885 4635 2\001 4 0 0 50 -1 0 10 0.0000 0 150 795 6300 3960 App. Servers\001 4 0 0 50 -1 0 12 0.0000 4 135 105 8235 5445 6\001 4 0 0 50 -1 0 12 0.0000 4 135 105 8235 4905 5\001 4 0 0 50 -1 0 12 0.0000 4 135 105 8235 4365 4\001 4 0 0 50 -1 0 10 0.0000 0 105 615 7785 3960 DB Server\001 4 0 0 50 -1 0 12 0.0000 4 135 585 5175 6120 Class 1\001 4 0 0 50 -1 0 12 0.0000 4 135 585 5175 5715 Class 2\001 4 0 0 50 -1 0 10 0.0000 0 105 705 5040 4590 Web Server\001 queueing/doc/web.png0000664000175000017500000003673014620415625014330 0ustar morenomorenoPNG  IHDRE3 <bKGD̿ pHYsddtIME 6P + gu%FَF7*ɬDrkQ$hsWm^Փ{sǢS5s Ka5B kaO!Xz8_( G/%].Har.$Xş kZ9me. v725CQ$ df#=&U^*烴"x&BWݭx]ƣ /X IBvTmm{gV# +%V0 Q>ApaV'pmW v|vxGXqh\Z+D}bD^e 9fVz~~.^[rqBP|,hTZm+.qXJSAEx}ꊂg.U U>q$*YqA}>#(X}ʧ%*uˋƸz>7DixvQ/+*ϊU$. WϯY- wUT|*\ը .|elK|+]y.~4mCT6*#O(w`ZDEu+(X%Qъ ع( vZ_=FA؆uA|w@Jc|ثߪ|¯CT,\*ފx  W1*)w;5DFћV`IpatWTvpC(.Kodb%9N.R՗b.hE v#߸9 /ԇto7Lo|qC&.V.[Ar+;\`2`?>מ\bm\YJ.e>װ+ᮞ|Ug@!pg d-~3?Bݟx!Ku[%wvbX*C0h1^w ncMT o%\~q+{XY(8kV7XlUo\qY'$+_LdY=^M.>SX)` $nI),3d2]KKj=:\c\$?PxWz%.nJ(3X~ jSL6º#.e JY%V;ႏ vxKPKX`0FWmtA,`>Bc%>RxXT[oү/\]t]}+Z]ne[I"ū1׭%I+#Y]EIfWvxAUZWBh7%uT{(<ɌjⱂV]mt5x;3 Ѷ|mQ].> 1ՂőFgP]t}~Rꮫ;vG>4·@qF5T!MET!MET!MET!MEi\EaO:JaWiVQ84xrC x{f7aLM1Zg<$>53rowYVQ|DX`$<τSzH,NߒFSP27un3CFz ,n C+-øSc9VXX:qC嵡;_髇c nۚV ok.yϵӰ/)AK0JB N߁Fi9e X>L*<aC84- 1AyLs54䣩HC>]6q`Yz$ 3'{tUT P< bx0w4 ҥ*QlOooR]ֳk_ޞ^/x1{eܲvm*(nD(;ݝ/B-CLݤFq 3wp ,bKU\Soϫg;@[TQګ4ws>(wwv<笡nP44wV|{`8V*x ]P~`NwwCae{*WӧWo\|[j],U_UhO5N%`*xikkUW*Vo;ڧRzݭT&h.@|nmcŭc7 rSvo3`ݺUUnjTֺ=UG㱷A\TX}hԽ<("7"I)JazƓbGZf@=&/-E#G @_MwS U4pVoĈZ+Ssƶ66V%9 &+UQ;2RH$ňzP+S6 6,$'ju*Ed!`$d'j L5sU 76*Ͷ+mJ=8=zQΣ蝑R)xSN5Wi"joC;|6e# =B<4szf%g04ʦȜ< v76t/KlRWe2u;JdDM2aˁ8Ȣ%*828eHU|Diy5N*uu$fM8h7 b$m>('"|Lӊױ[Iӥ.Rqi i6j=H־FHU" Ji*844(u88HCE}$6Μ4Ł"m'a&/D Rv8]~C3Ztq\j* hѵqWѬxl^i˅ԒyFCY63Odv8~OũMxb=yXy9Ў+>_x;$4g狪KSPA,b_[. дc"UQ9hw9qDv&E)pŊaOo;TqW_t E* ;,YYd<aS!;r-> N"PI8a1ьFyn< C<4_em~W+?4y`F$GL服4r A6MLG0Tb൶t$7>ROuGxˍ37 `Aer`I7i.Nk>] 600в>Y-f'xe[O.Iol&oQR9e>$m.1m4<;Rl%(Y %̀ `ӕm3-5Mf\W$iɟx5ZXC eq-8Txs(e26[.ݜ)>2f]9cjdG%#JkW0Z_p,oօ~͢j3I ?^ޭ[ʥ626wxm `e'w/ޢlؼxW~ag;ˌ[~a?[xm 6?dϘ!qjػ͏c3 0̮ xIV!Yv,⏼4QA<&kJڕI\Wzf~a߶>O?H n~#ßR$eXaFm-..*gC D흀QiՍ|[_YtlZ1q>g? wLyх^hr̾r&몶M%]p@5R Q9,-Йh4ml6~=]l^jj-(c6nT>oBnwFgY 1 0yy)6!Qfέ_7 S3D(;.;х3;q93EXF fVesw9H"w7G~ f7 waԭaRMf#{!U~ZdGlۦ4L,/:]&8j~;]Cl&o:1lطC\>{eqE)Emh3x$~eAб0P1Vw[}c$Hd.j"oMv* tq!C}jZiHN9$鴹+¤P\mh `P&ew< Pxzf Tyfw۳\]s۰ 6A۸;zC.WN~8t$f3۴rչN=S7Use*V=3˫I/cRCReD $B$TLO>}8(b*;*RE/.{6OM,֤^mމd;%uĎfsn BՕdl,m&gjUL ^AYWv,?SjT g{J{e|@WQ61W=M#f͡s*ԓfe_EP{tdܼ<MBGJ3ÁjȥaWZFL4MDb:HUzvf{Q)vFf3eH K$*Ϯ7" Ew–YFݛȗuʎp9L*:]FcgVL~4^w(?/:r'!E>bFdI2RBAa1zCg>I8l̔ˉe:ajˋ`HW715AP58:^+oS=H>IHLWN#$A1yZT_5#0RMz<*k;.LkQN8t|۾Q~e 4V1S8,w(A~t֖)BNԇI' pN+ |H!t:0u,ή_tYOzG4DnXM`c/zKmUiͶTyh6 UqImZ,JFl~ֶ,Xd.k6V" 3JimN,iZ('&umqn[A!dp)b3o%.ޛȱ+太(طF!yGdⵥ \M3$zg[BhA@ewgНcoy)\\p==5V,,x̜߽t:Ɍ^v[B;D_`e<^I˗/iDT/7ɧ_@5 F_ `.o-eC栈.W󞋙ҥ/6LlX X \BvDE9p]rcn^wpοrM^[/,\z~qMo] FNhqxu17n[{lv;@ kn*ɠ۟YXW ˦wĻTHc7Fm7UM~ !IWXZ FٸfuQV[vs^lLn\*حk2;ƺ与D^g$(ymAXEV%zV\wAqA1mZ |nBTAXYp?]s955bBζ u_c_گ%3Y%! ~xoq;/ 9xcIoj%2wrU%:)&[%P2 |@n/$!8gZ?c(\Įs=h%;x/xNJEz5f_{<S{:vQQ&EF7F0~8v&^w vAq+ ` mN }48uoۖCmDeye{4yS!l89(!86ޚn7Yj׺^E&.rf̤ZNT"L&I9y02tiD*dbuITUn 4QlwL5CE1F&,m6F5R`xؕ"]q  {,'&'|AE{G_vFfXS'м%peFbܑ֑|r:4!e&R#a,Mų-xIdjYOe`B7:%_ƴx4T#%"RЏƉc{׃HGJs|twe厔CA_.<0ğ!`)Vnn(X&l<޼/||0tsCmHE%xGSvGmzXRt+iX ~6zx?|Q;&KӐBS8]YR@ WwB|=٘&|omd^ħGJXQDd-0Rl 'z\n/Cl7!puQ tC)/Pd"©Ϧ O[uf0L.hti~SW.pf;x3eX8g`ւ7BLL7Bؙ_x@>)]CxGiHRa }ܰ6pHEzFԼ佑XQ=0;X a/Ft۔!}06p|m㠊J7=u]JRyW_}QL'H_͚$uו+.׋95wH+n0!ƻejP8c=3pfS&9"%RW=1y/ԻC+*T U4bhJ!c&/;'ē; T$yegopiUx;aI]]ڛ<_m9lnC*pfG[X! 1W/f=^8x<8m4:|ǧF/t$pяvLc\&. 00ą ' n~R*zsU:P-)"!WaݷkO8p 9wޜjK׃oBRLsx:a[XKUw{wBEXa3~7.iL`]sk'Oק[{mTQ6l] )ӧε!o|`5^olOC+nK|3j;.xHEjO<} _~d6ixkqg8v76*{_l5hTj0}ϛon}AӾU1]™HC\mWBqccW|;8\sPEwf&V٧seӸثm6ۄiuwqchXa,5B@[To {pna[W!`L)pM|3=U_{rT@C*~~iUˊ4FN;{w['2֫f+7%6C2}XALtm~!HMVqg q@Ek¶ݧO:6+$l`cut7_<_ \m+nU_MNEGY o*yIW˺꣝'4%~CzRhX ,#Q;!@ s^svnӧ S]mwm&v| B$$H~{ZBY״3re:$|s0T)c[at"|Z.b7(L7766YK=n(L{೼iB7̶. 8WTƱܦhJ_'> N"Ց8 scO׃×`zy}/ąL[@ ~`q* ǵ0N0QU`G"}Ξ :s$LA#CL&O}W(=g -|Q,Qѕ)=Ӂp om|1g{ gp0X^6>Ӗ \+:z;lmF|"ߪζz)%?-*<o\VmQ:vYA5q4]O~zΝ񛹷z϶)V2A/_4H0xW7Cq";{ƀuy3ԩ2}t;*~_q#pͧu|E4&_rvwڪޞVޓ:>J"b"Jb"/Rl5x1\{ofkU+[?lOo 5ؠ*n1Ko/j}Zw. J=?bP1g@UqBˁoNͽ6xgT+n]Ao˾Wo2hkh(;S1Upe 344sm6xf3?-dfU+^:ٷ:ć!NnvP8#9(| *3эgM`tjґH/ZgmăĻ0ri[=p+K Mh@EL d;]N)43Q7>_K5_DȒ"r:hCCOp˦/Fn*˟ޝGZ¡E,BـDFڼI&Va 㷶4vNqTﴼ邵ęq1e]FyeߞC**YE;CJN7y0y)inWu(wH;fz@4 }M5شC9fTiVq1[~ꪌH]_=" ǁȥaWȺ/Þe`ݙ_EyߟU3":n% f*L;#3x,phٕ` l>a.VmsUvB>3yg,) gǕ<3'=#LOhL@t({xq普[W_ #2C11yAdit6@7W.e:<&md%Q津>~FiPȉ8A5ϯei?4ya%ۘ(My^yF= N6>#l#gRSG*.C* FF@VJQK3(N⾘ZL1Ma9mf^isIMqh%QhzKwlt:!pv""@[7({10rfHӱzu[O>h`f(3gbgl ș:|>әmjގDY P:`vJ<33gTUzs2u '3ugD3 "am-Km}Sqƅ_vGc鴍4t&߇vWPt83~%C6:ȁ\>2$hf|C*߸:].yܿP{S WQCI9f*(̓ѩQwHE`g_DoAHd6WlIeǤ9>2f5xC*v?H6@˝.Jsؠ"(>CPyL.csp7זbr7Ǥ9w$46wL6mq^UJvˆӥSfɆ7$!@ٛ+C_u7jWKSH/e6oJzPEE'Iϰ96<.t6յsۀ lqDk{R Oh쩠*L&ĖxlL1c`e+}D2 OX(cJ8mT|'%Q|&iBLa"8'7`:@CT' =A]H U_<9rDTw/c C#4]hS %.^8.{d68j8L%tGO63L3R ]2`HC]2N5VkkXCPqQ1t*õ'Az:4jܐj؞D7Q0V6ktƫFIVK"*h.=J)(Y材di 9ߔގVɅw ?FC{-7GG_4.ڻ *ړ(>53roDE2jͺ"Wu+&*GEA\T ǻtF<s&щ:2 E Pw"M{H?p  DJ_ԕ 5Dn#fjz)&R(R̚wJ/_qJWэ3!F ҷ-@/R1jt!dS]g#ӟ>uSqE༗E bJL2+(f0\rbL: wWoΟ?OAww_?nrYQy&V @oϤϺ-<|;w͝HvP~/zRkV8h~K³Vu:أcn\sWI~uX6+ž ޥB2.~1-7n]_0P$`@}?$`PVvbI Fj-#?>f0&Q(`h'8uKl?^Ln\*حk2;ƺ:CW. t ɂъ7" _^V'Z4} 7gwyH~7VBw,-ck+ѾI]P #|ѼVA1u>~BNJ Bw-A-!}mn~A6z]Lc]X7""BTX现bu '._[m2 |@n/$!8gZ&]&MZs1 A&k\ڽF`Nb~/XZX_[Ƭk/]t=U䋄#wVu7 ~ Xu#xn[;~.8;؎ ƨ mA[Sk<#Ne9d.F؛W Ic%YId1X0g9*&bKuitWg>ѵF[T!MET!MET!MET!MET!PQk6O@U>m<* {ڐ8Y*ʷq4i*aYTlpHsAc$Rwjm\ZSoeh3C4䣍jGS|4iGS|4iGS|Nn2qbLJΖ:w9(r€'#1"1C SM|TBEwb>w|lR8h/9GNFnW(=kJE=tF|6.:tԔYf&ӠHŠ$pC0a8H>\K\zs) F}^ #l*<pTT4,XQ5wyK^zqzb)~)ڡy!Wτ~J;zsfUl/A?D(tN,3#wjOlqdMS#L P3}Oi q|hu0@R'3?ԺT*445KeY;iPS/= @i=d_?:jQhHGY kx %Q)btT5Uvs(,7_YNSY7-lpTe BL@\ڭ$Y!9`v> stream xmTM@+z&?tBL$d4*.<_fW_wիrc;`GUOV&ʮ[v6W7TvbuYt/N.5=S> stream xmTM@+z&?tBL0d4*.<̿~UfW_uvc;Z̫MfG} I]/ޭmޯo⣩0^'^x]fkn{EK{*ʇupg6;ލ$4;gZ8, M[TPRJGeWxmE7 "/7j;{Yʋ"1tm|oirI ɑc׺>[TқEnn#bBSEV嶭mzsg)gR133w xAb;aGL6K&0+}&"?(Ҧa/ c,!-f3*Ix {asIC%hS7}H=ŤIY(jŧ Z4{SO5Z ekxvKǬ@2a> stream xmSn0+$z"aKU^CvF^p=!94gB˥0pދ s#P~k@hZ+vQڦ(A,Rf5Ħq8>K_X NH3$Ǟ{<0*5c~Pʯ5W42^!0^#rqxƘE3x z)cgl1BҰ?Xq!NAWA*d1)iȧΰО 9璆NVfkVaUJ?%͚5ػbTW=ј52f&p2pjV^cHMcVYxLS7E=1j g endstream endobj 6 0 obj << /Length 312 /Filter /FlateDecode >> stream xڍN0 }H%b8i+Ҙ4P9!Ulӓ4[ˏLƃIVӖuog9yXxiR1)I#D*j5ϻnPkXMLBe͆=ŗjC[t5G)a}]_JD-MMhV6} GٶXg8cJpa#! Jgǽ/_\f8 .70r۽J6!2$*\g0/PRi!M47ifPJ%$A! ;ٶMٹU>qlu%"t9:{6 endstream endobj 14 0 obj << /Length 991 /Filter /FlateDecode >> stream xڍVM6QVH mk%mp(Yr͛!EQFʨRuLj?~}I IQ~ROYV<p;8o{ى2Ǚ qsS 2)*5)R%+_)Wn+E,=JiK2EZLYThW\My5_r +2X{3LLE CחkzH)!"~ˊe%+' N57\:ϕu/So^,3-#Q,mu4esi~2?4%EF֌ Mѥn1_wJ1@ZKL}P}K<f|xɤxCv'es&p/id9't3/ӨikˎЍ61i޲L3gqfZ6h|wYxMz;&A<@~;@MkܬӃvQCxd4F9@L{c t3C􌲥 -.@e2zGh\CE#‭Zr|Áu6U^&!9j $D5oiѪ > stream xIs<v;*4Ys` .*t>I5ϔ4Q,Gn@xR?xRI)Y5Z*yϏYvO8e'+TKעkW8yO", ;!LQOkV4v:jJqѷa;|'s((d8A%#Hx:Ønl6_'pY)|B 機h.v/aȹ4x`AI 9bE4&-+I#4W=k)XjU/3n'l3,6=LVsa8cE ͎ԓwrKjԞ$Yl2 LVÖ%"9ظf9 NMy(=f^AQ 9b߫$j0YZVҡ*JQw5m[v)v^I7&_=Rh^gm, OAwpPRjM}l~v(vI`~)lw۸Mpm+p]cp1spFPWÑ)rDY2As4Ό4d5= Dhow߅vch,=`c'$+.T x2m'ߚdc[T4Fh(1!> stream x]O9s96XBULhC&Aez<Vh2`j,$`a]blx:Xu.(W?2cLq.+>e\fSA-84 N&%LU+|)vPI~}>ԏÁ|0> stream xڵYmo7_釮8) \]ky Jpvk7k-bNA.(  bDÒ~5i !lEr- >(j6‚ӚrbNts`y010S"<@))o Z+93ޤ͂U~-L{ *w,keǎB LX/56`Hp #AA#aU4# kF挜"g 0rԋ2Z{l+wr};4>=X3ve@N=9e'dgO$ ){/QؔӧZluOnví8XWmد[Ewn>7 ,cb#sO9 y8~b_wz ΞEޭC !ݮ,Yf$NEd0nbnop1p98[n6|dۮ7Cmfo6_e߬a xosNQ1fvXt)L"&DnF,m4,Ft1#(FPXPXPXPXPXPXPXPXPXPXPXAb +(VPXAq gP9Ɯ!|4r̴N79i;̻w^-c H zn tÈ #8Liԡs)@!:j$?Ny?wBj !)AtpP q茅FV6x::xgrtM!9/> t3B#9{6i:ҏ˛}dOMJ:EG {Z>SCoi>[ trgfpќ|:EOt5L@ Nrq/5*Av *:/Jpl*|8\_~@o"r$!Mj37Бo<ҙ͘g> "4_bNg^j4*$Z|΍ӷ@F2i~^J,7'CbᣈJ!Ɨy-t9BEj(%G+Ea(|b:aMA5Y"9vJLlLrQ[8W}F* \+P'x ^j1N_\)~_Ixy^;h,z0Z/V>7wU)VI"եttD$cIRUX'WҚrimi]i}iK=L.xTJzQ"gհӎP68<wZ>]6A8py=q#R|Ml<5ag+D%HLN*i9r(9gi39t 6@‡JA 8[4sV GS)R!EN39}.0T+!E4WirT4Sgr:_˞7E".T:) !p%s3҅J!Cο|k3%Z1Ȟ ҏQp)#"*BUC\ʍ_J4!ApyJ%{x)k,;m*qrzǓ> stream xڽ]s6=BL#@郝i$mZ:s恢 gdl.(wh ,5EhqlVn_Evsx @\0/o^3yz&YJ!z7ǀ?ꇛ7"ٕ4L J2X2u,(,ha,A\N^|;Me*~UtE9Ի9-6n: nnAIj eU-+SXi*r@1ia*Q_<{\*yB֋t=Gɔ#]: HWcjͅjKcVKgvjI eEٯD;xY^3aKc$@'$n=f]t$y5]|YTfK_Mc4¢l W٪=&dY=yzgTj8 +%ʁ>BmKUEaϪ޹0=+\kcv'Ƕ4V[~4rCbsX0pB]1l32~!<7Hy|'bT{DV@!;޽ ajuчE$fy J} I"vN6DYB9Ȃ딱HNLUy3oMq./M0:w ]M˪ U[TNKi:h -z&>q?&fIq\I>Ga 4tI6aM*(F:ѧV=ԮФxjlze9Ӿ׆p Ml,h2 -h_٪N-<=mzhV(>jZ :Lsjk;B5<8=$mw }Ea+D2FxwjCug]+|qlʛXJwZ|nۖq ;1 /M՗\ !CHu85vڨ1G[l/Gk:o9.G PœF{Y(☑Kx継Bp4v8"q2R-j?5ў1Y|/+;HpqI aqrFl!,c[N9NG(l1^'D} J@> stream xڭXm6_2Ҋ&M z ˴M,zw/ЖJ0g4$̐bO,pqP|Q_n4|G/$BAbq/u^ˋ"ȳ5(lۋO'Q'Ah"D4%1K_P5u]^07u;sbިhڇezfԫeyOEݠ@ݙM,[KY=[^ncZ}dϛ"DB|<Q5e鎵<ς"ΝO ߕ^/8ڿUR7W@{UZ{ow$V6,]׺.{4IJ ySu$2~\޴K 2Rj gdz'~{,a6Ք6p\xe7Vh וCQp]oV.+; Ćfjte/$ Av. ps8԰#0 o>LA(!}Uk[(b4}{_M$- /JrO/"Bդ]c3*eab9~hGӣ]7zezJI;Z0jx8@H)=F_U08~{wGWd`Zf~BQkI io74iNV "F_e+[_G~xɉD>nqQaA@&rrwȑ b7J/ipHu֔kR n{@cAc'A &%ؕ\Xc2sۘV=i>BdTZrfb\كanڷT'3hm3 dclI/; ta (/ҷals‹qmŠq@=~j,@ 'U" i^0jnsp֩V[PH1@ P6~up>B7 ]꯰Dw}xy}~ F^Cr?7ݪ03ʨ)g׹?3[|\?0mY '  X^.jWw>J2vrckcY+ 2d- x<{?hʽu VVmw= hq֛YgO&”c'XBhwLlg=]-֫v('0m0{e-AM}6 3;g>/ѶO$ޚlPPƂeq"H9 : 2,ij'A¥f;o"Mb"LVÖ89 DdL:|$n0Gk2{Ek v]%v]HXҹ5nT㓨7*S'y< YBԸ-s?nJH3{fmOn/d$a1fS+ Rt;2a ;1$ը#ћ0$"PuiMִ{"G@~e#|G/{}sJp.No|ݐթ ^<ܫ r6ӈ2-Yjq]ey'ZlԳ3h乭mEnP7|x8M@Ĵ~ 8˪LBNO"zgca#6~{vNd췓'ԛ'di 9kciHmGuCa_ ݻu)\jDU-$rSS=315HXƗ8"Eh] gi LbI{CW&ϯy)N}̴,x!f@n2 n,uC突d /T.@֕ Hݟ 5wr]CcHDZi}/?b ?1 endstream endobj 197 0 obj << /Type /ObjStm /N 100 /First 875 /Length 1583 /Filter /FlateDecode >> stream xڵXnF}W"Fr ,_b4R):FAKkD vgHʖLV\ٙ37>7! 3#p #M0)<&$s+w2!v.Q3 @йaAB‘R1##d)LHd )rJYi B*IS`V{Td\*$vdE@V!hQq&| >}$' 'r # p!19$ (!= KR58*"•SU5/ K rpƀ7dBD9 `D{B"yɉj92> bC>$ 7]AAP\ 64 $x#%qD"$"RkXԐ$#I],K G**#"HGbH8WbEdjh=A`>D%),^? 0MhAΉKtSclAwSw_ENls޿g'ECwN))6QzC<.r};{>|pbF/b~b\s}Yt[<;-6,CՇ6z2Wǔ~<E&kqQ#͎j\Ϟ]/6g>H"Nʴ [F(Ns5LEL\G,.ewjYmpwn7gEg-AZiuju6vV9DT?0Tӏya`wn箖;tcCf[ƼcQ6ټEk8` ^섕؊Բvq'7,[;ձ5kg:q;Y;5FK+4)tZNg}k~e)J`{{=қM#ui1":> stream xڍSM0WhKMgs]X rAMĪ'cP{ޛyol ge;J 9mк,_68r̯͛g ՇRu}7g`N)-r:I s"v?m>/}8!)( QT $Ee LYT s^4p,<v'5xyX$su!c!ف'=tqk*hiVmX@{5F!8&;@O/lcrmZE›^*ע⃣qqA ͎s ; kvS. 1G>paojp(p*:/#XO8wWv-az_F=Fҍtz唚=ڤ5j%b`!PZuaĨaksԨ)'6knTܞxH}FM>2qP^ԫx<4WzRC`Kkrߩg endstream endobj 387 0 obj << /Length 49 /Filter /FlateDecode >> stream x3T0BCKscc=K \.hQeUgbl*OS endstream endobj 393 0 obj << /Length 2210 /Filter /FlateDecode >> stream xY[~?B m/PZ#yH/I%-TbE~{f8^=jp4_/xJr-6y}t\za#/Cv ԬCX׎w:z:չbI}ݖx#Ev>c8]t®KaiƲnjg ;`ٹX*Уg85X76GS4@u[{׎z62 J(URˢ6\-t(?05fVjsk3*OWyĐv|:ӥč[§ ɰaد !0X&yT5Xp@6eD1{eNڧH8=&ڃv7d6ekeF/}x}FѡDwQ`)9)e>9 Pl6iՌLrX\eQ# :Z2 |ۢ~ucXyJ XЧc]A źm.<MSɝyz:ؓҶ%I# P!o/W "aȦ<І ¦ѽxdNJO7[SWlaq ףNűG]G\ՎNx]1i4#Yrbj?=C=bEAhȺbB4邶BV["8 jO%C:^6MgE{Eʣ;JR & `Se S1=,:(V d‡i7or5T܆;O޺bj^cɕi}>iЋ܍thz+OAt]$zkYX^<\ܱnU.es`6D%oD"Y|}f6y5J╘v-` OY);E{?eͧK`z'"ǜ:Sz~I_”OrQ)vV˞{ DpM^XnX#F>q١m^f wu,zeQL%Sr CL^gqwp(6XӶ1'yAA Q &G[9_2/z_+(>'< >b͐j/3gCCS&G1Q[#Ԛ¹botIdSs ͭZX<`gGxvo`reh= <X3e3br* #I+m[ ]+(T E.sAUZ3rh%!mg|*# @ð QΫ%#FĽj%.Mf uC ʡSa" -gX3x Ȕi1 endstream endobj 398 0 obj << /Length 2602 /Filter /FlateDecode >> stream xڝYY~j/ާĎ7 vCyGlK~oOUW7Mk< xW_U*|ǫTJl;-_O[?mm>k1㜯Qr(o+,Ks8`y;x##'XqŤJ$RѥNDt{QQH f-SUucWM\]rqf-oD5~?\龡Q3͸U*b%W*c:~eU]9鈌di<]LMɏ)J'A9Qyɸ&H)>;<+~=ѻd5H0L LɜdBGOo4Xs&X`fYMH-ӉYcsF\R'S)p/zSt8TJsu4}QǁTOR0ͥ_VVML{G){x Ty=u+j3 RUWR6D=iMsaI6(MigX0^58[ߙ'MMb t%(܁[cu< ousBL.tr-5,o )=B~w(XGQU  %Y`@ހH`nP ټL0^>d2j \e"TGqTzE D*ߨ.p8`[Cb:еc{UR$Mo*0$gI"ER^9Ž{&T|АI6yB{Oټt`.W$L\Xұ[Մ,$e&)cXJ |8Lzn?,kѲ84O1lL(j)*%=Tّr 8X|O@# Wݰ@G*KS:F,k7b&ft=vdqou9&}d^1.l sͺ xn5i6U0w*<8;'tG菸dU[kME`Tȡ] 6eBp< <9uĀBK;\9O Q\G{pRl%*Ħ7^I|* h` *LI\/|X`usau-ZhcCD޼ I'+UF6AyJ?. e{؋Duaq,$Kteˆ00B.' `$&TZ⬇*%ڥq` u3uwbpy1']BأbBzQC\,fAKw^Uc6y/?TgW.<@†LDK I!C:DžULcskƧ U,U̜[LOi@< G"YӞǾ,&Ӳˇ 'zm:;+a~YͻAm[2X4ˈu뗡&QǞmU B10l7̸{?!oobin Pέm -Nr_8"<&1gt:x( endstream endobj 402 0 obj << /Length 2453 /Filter /FlateDecode >> stream xڭYo~rE 8]>O&=@ v>DX"u|}ER}8vvV!URc,&fbop_x 3{8uYy;׬}c߯(VmyWՆj/]tfTfow{hO+ GK˓3Dlys#j<_b H%"s8%3 Rڮew,2ꊾsL/+>Ae{|R+N$`I;KS?-DL4BD!pE#1Y0z@O$>߷LO,P80zj G~03Jz{K'UADieq{F 1݀i X5?T[2JqS >qs{8@+52c"nY]\w#YY-1кW F=dSpX,qLc%WN e-;X{,1V5CR XG(N7v{$0RGf$%mj!<8u/s2FIgxb6M*ġ'L\'R 7qr*4Ư,Bmgxv:U:C3XU?a`~Vpayh#ݡH +菿Ab*/:n2mpvo;M(|k7dZjq0sW @R_;#6,5L1q >CAgcUc0&)}tJj$6cc`%P質{vi}Odǃ'nH#هv`NJE{+=` \lBzOBi=nZO_aUQ*ފƻuKVp& wHTRI]%{MLcX% lHQ,v;Ձc p?Ⱦc5p zI)S` kf\vV(+{54}zWGݖpaxsJ+Ű:H҅)4!A&ڝ+FĈtj\>fX)EѼd{Bz ६},HEkei~7m {%?l:8?,d_LJ q}ж&k㷳F;Jゆ_#jJ,3Zv>:''J|%LAɒL}-jI^k &lD endstream endobj 407 0 obj << /Length 2245 /Filter /FlateDecode >> stream xڵYoFBpQ W~h6=%,PHʶ]E{-yof7|HE,%KUXoCm78{0\AwۡW/YvLR)1/G}yutx!yْ(QKEJ7y]D]җQ୳ [-}{='݆YeͱűE̲it 쉆0a*.PmFf%2q\c^t~nUgYY|ol_$!id<$A_wz@Ry.wdE$FV$,CA̺HF9!E-KW9A~$X!p@7P?eF?nqZڼ5p4=8t9mWUʋ;Yd"LzO?mS^M5@wF9 /r|O?X-|?c~f|&X'd dy}gr.vqWnY~7Qsy$V@W8 (ENgY/uyWhdkM^u[ŠLJkg&;o'<}{ܟ-l6bR-! a<0Z>is/+ bRr GeU;Xqan|_S.w$P62`Q*a l@_B3APѫ3`% 8~^&ʹBB+iT%Ѹ2h"a|jRd8dM׾Ą\ rof_4ؼvk@- Yki`̈́V;@غr4mukJOzJ`+\ØI AmfJs5{d)fS,Kydoԏ,YKaX7ӽaj0Q0ۤ2L9_*xxlB0b{3OGZz@úz7 n򵦇YMxZw?x SRh[J(DRf01v4}6?x0LN}abf4b 0>8oف2I:.BkP$b-N4tm&Lr{KR YÅDm]MCL6PWH9 &ovM ]NHaupѪ31MMxfK֒xKct;:k@r JDKrCOWU[7׾^rӠP? rk3^C{IOO=8QH?SׯRרFqߓze-)(4aq+(c:R~C'2T4ĄlQʘ :>O`\Kh\E^ឭr;uvδ2D#fcztL=:mpr+36vgwxww1?+ BS>\CH: pdU[0H ρ09qM]&5S%o=b|P ̘yj ~ ,?``,r> !Zl'g}P>9 >M"pF8#U#{9qh/"^0$\xS4Ƌ^58o 4Ƒ{{3afMFTLr̍MZ" q<*bA?iTá8wP}tG}L<~;3Cޟ֛u)|]SI')z! ׮ X߬ endstream endobj 412 0 obj << /Length 1726 /Filter /FlateDecode >> stream xnFz ,wvۦ)&\VZbCr.M*t$BcvO?U^myfϘs@^ޜke~V7CT7[ N6k70Uۉ]*Վe՞6םh: 7,Kd7rqq4(I3X3'C^XqUN)&Je)yk\,BZ3G3UG^8^k}$=u`TFx4 n͑qvJDW3r[1˯졠rV/'w@R9+1ݕv wBmn˯#\G 4D,&FT)o;MS‡hq4½8ǡE9*epŝj !R W4:T{Հ+J 7(CK#!ea8RV=g^O=g v'j /+wDQe)fO'dO{PAr*@s/ eX`2府|=2b#/NAܐ\X'^Tobn]BT[m'K"f/,J k:PճT^_Զ4R)mS2~iifCKpRfB*)Րo֌q:7<}KWpv _azq3Pf`nFJܝIg*$ڙ")O]\/ylLu{CKB-UL`&йU&"NTa>GFny|w%CM`>l2dp|{5:\>hG{[[ږ”xl mYi0L S0-d-K33pSl3J:xl8q62S;A1Ff93IL;gfpѠ,\d 4PPw'W#n.EŠT@m"TbS?v~6 GV.*bgXڗZP\EAgM#KL vM;6rFRAй{R4?q?4^m]w:km3 "@UTfm46vW ݓZ1hX ھk7J!AYpZzpPe v9 OǣVN|'IzIβǿD̋X'BN~0lM6N"ar^>Vnfy4ԋQclCPg*~}ܘ^"e,G&yc=@ ,;:kgG-nZ_wEX|hqGL- A{Qhni'dg *f[~R Q!uēAtSRT6jMktO$$b #ymZˁZrD`u8 :P endstream endobj 417 0 obj << /Length 2351 /Filter /FlateDecode >> stream xY[oܺ~ϯG-eěHH4>EIѢH ke]iKp(q,sf1E/,Uv^n_?n 埮_zc)_\M^/>F<^\u!mʬIa7/ۋZ39AGXIJbRѡ%˕NDaQ_K)˕4:jhs_ dX4 /ٿVFu\ GyV] m4뫼+%ۥ}j~@e3jQtlv~oe9OzߔY'Y]Ѵ0aD|=Pɸ&Qa{lnj[3ڂF=we/55rSCrRU[:u (wP9s@ z5'RFE/66h^jMg#)TuYĤ\$@7$So< \{CN#z~P-JEW΃gūY+!!|`d*i:ﲯ+ZN?Y sϸї*ow_mve8G\ gS4!9 2!U"M7uٖ,+8{7ӭcױh3 w'O8K 1*eځ-:Ha'(r )  HJۨЩNǯ,ۯB xtX /tL(XF` rv KdeF qE] O%y߶.,_Z\x"s<Т B&CL1 fŮQC| 8q}GDkçbER%+H.`G9AYLR$ cp&.R&" < &ox HfLKw~8CX"3O3īP͂9o'On hx( N!2̪1 rXyIRːvIQS* z8?=tU{ߏwꆌ -w㇓eYH𵄒:hH8G?O\"Yn'FKW 4 endstream endobj 422 0 obj << /Length 854 /Filter /FlateDecode >> stream xVYO1~WFjǷx)J  %Y5nBα` }+wo $&sbI=얣_ uQ%"eXj!'8r%տKSΠm︿${K'ҧ `I{T_(1"z' .E$)Lr4M*Z-B"Fh>}XAe4/=I+ kM˼z t>R]Lug39sfS7&~-E^Օt4uVq9_V5&|5G.b6,\OE=vt<*ox\C#JՒ!9rF+}`UmgY]A!&s*U b(_9Ű!Z%(8SB:H7HL danc' `akhO&Xl*=km.7[W2Zl@, !v€5c,mη=@:+ ZʲXK%Q[eV7vxZ&od %܊u " ŽHstHI *C8=xI6˞=#ϼrG}P 8cI0 W 'Bh?m  A"RWQ%?ȴ endstream endobj 426 0 obj << /Length 49 /Filter /FlateDecode >> stream x3T0BCKscc=K \.hQeUgbl*OS endstream endobj 430 0 obj << /Length 3241 /Filter /FlateDecode >> stream x[[s6~ϯ<l&]wӝ&ٺ3;䁖`D${^ʊ;1A:; ,,M4$l{74[`߯^)hB$gW7gRvWz񏫎d)qQMU)#OϗR%]d9]v?ϗ\&ˋi …bH 6%a ľUewyUG iJ( ,6~Q,!<0 "I57n$ƒŕ"Tz6t"5"IgHoC3Ft I6@M E88&myx}df" _d`ڢjp+lXëX;x.hS]om]BEa<>[f]ouAVlS2h~]r:% $1ca=S :wC&,m &}_\$ͦϭڂӖyf$ C<䛬nrPu]]: \FTus45N*IGش#NID.* FF(]',>}_,ǃ$O8ʠ$` P14mTAV!UO!9fq 4CI :!۟CbK;@xZWv_w6+j߄0"}>:ηW?ꇺ;ż̏*۬ ?qYN)CA e= AAκCh*}%Y?-@rv-("x2qs&4L rorva C#WF5yb2 􃌐O#+L"#'C&a@y`sm!uH!Pʌ5:Xc,g#a5U@1CK'A"6\0oKfi$b"7l%F{ol5C6`OG<&=EKؓ𯑨|vFrĩK"Y%y'Z$K α`'i5R= 'sS[[r:{n6|mCGPXo2X;g.bm[hpE$ǘܷ^ytU؆'g˅B pK!NB>E@:gMNS %?X'Ci%>ݔ7Hg0UӉ} {~JĆ(wJ7 ¹c(A)RMCS #Y?ص?aKZ7,h.,Ex% ~Zyxv H*Pk7JJ!栮ډĝR9%Q<|'{09#%r=zH!Q&f-R>l5Dt:41+$ħcA xe堉N̼,`6縁ӊ%MԌuT $*& (?4s8EKA Ta%T? [M:`%ݴj1jR5Y}:|o%^ (-G4E Mrxdz-vN@$ 1rܖU"fT.0h RY@ʏ2ZDQlE{H[,, sbկ|k߇yV*^`v6^dA ۹V!$a{?j-J& 5D`"(RdD! [뒛BumcAMM#@cRw^HI+|S1φtPENx[-^S՚>!S/"FVĨ"[du](ng9{C8QXOwˁJ~W!Nae `+Տֶd8 >EEf}J$MF}Å2ܡ6N|:_u?f3n7<&z1Gms0U=Njo)? endstream endobj 439 0 obj << /Length 2833 /Filter /FlateDecode >> stream xZݏ۸_iјH^6h6C(班,'3$%2e{+!g7-( -,V O/Xh^GK-[=Sݭ &o>m!%F[Xf^nX@q~$8DL QJ# /*#fJ^Y =\xZ{j}i>]10MJ!?5_n)RRYTnelkG߷ /mO jU{AJ KF(!'":ffJ]_ty;os8jY/JY;^׻}ewY"~TJ%)8FLp9LϢizUkgK$%!S̏z[ lRJ,a~+qfa&2QT*$hԹg3qWF }D)}4[t)9{c袊o^<<ࣧDxv}, vꧬxtvzp0Eܘ!QY2„` 9)-v0FSI }$D0搘n`$acA".{ul} 1guA&TV=tu \Ts`~HVD@9lK`eӘq7<^vnm~ ԞJ"FɊ PT: a b$9 9T~#L|k h/0Èb@c~csa! {qpAaUv](}|5q~'|G^U;7k?:[ZL>pKמmdIKvډh$QT’1!& n .Vu9nG4 _Cwba eL!`P3!J;m bq# |(R43#RNek4 3xfW 2~RJZ|< nrqZ8tq~ݐ,aRKSܹ k5ESaDa)/$lCz e@@u<+&6ͮZ}ăb.UzHĀaAS@ c9R*sU=wofx4*qɡ:1tUr tH5a0ԠnH_edB 8]p-ʢ.!TFun/GnAcR'pЧlr!({L-fѰ;]}}m\)dVl7F{c?=s*p1pX.!q[Dn 3!1unors1}3H27v.9 /'sDsJw?ex mtq@l!GXncaP.!KQǮ#L?qQOK84IYdx`]ͽ/W5 AgS6V<|Fb'MnDA6>&8S-Fƕ&V42>|t1@,K2G ;3[x-rIDӮ Vn n]ӅW)wk`Ob[2vcQKʸ \YJg}i9$i<c),mLRG=x,k7Ի }>#trb:=UBBĨgts~Dħf5׺)#Οc:w>Wc#fjei35Dhy>٘COOq-.T0L&|ɴ}=)- #0$Vs׺`Â%I7 b.:yn^~3Bh) )."ּ 6Jh?.t J?|aLOVL̄9tl0xp>k7.[s<;||!Ss5 Slڶ^Wf E?= ;t?!m]|OV?qԃU_W1ĉSûb(``i9T"Η`GkibI,&r 2husB??WפT_^}1-,F?:!3jː猚fX4}96h1~!)0x-̙P ( xrh=nE%?5rf7A77WYfR{XU~ df=S0D*p5vIOI SI"JS3dIXaq_6Z{|5ŏW5EUVO0B%kSg~|5fB0eʐ~Ym ?9qCa{7ΰS=lU~АcW~n8%fza9`]]-+i3V+i$ vƉ}] ױ/2{8ElX@.Kib~)aw T^E'O Ir3^inQڽ+ pGUd\ l*ܳY+JRH%,@֒ G'зuXٟ'$[ucQl endstream endobj 443 0 obj << /Length 1514 /Filter /FlateDecode >> stream xYo6~_GY7`ڢ-0@aVbmQʵCH~<~w<,l<Ҝ+h:}ku3ߜр:t k)G4&6tty-r1E/IYx9TKD})mDWܒIkRA(՟]}s)DHe:.noOɪ :bWIC# QQAO tgo?r&QzIqHԁR}O۴F.`yx ,V@cV/+m (*+9['_J`96gaI>fS=Tg~2_O3@-2hPоk3<:QRh:X T߯P@ TV1Fn8z4VѪجSc<]"A~`='aGt@T&_ؐp5vjK봄mHd6nc(H &ojL7& 'Xf phB I$XVŇCv0nl8D2aT a%%w"JX @P"U BbbL[A== [rB]`AO_)ON&*^_|^!|-a7 'C7)֛*>ldI܇K(M7+KI *,pyU7(=cDs!jRV1HGDZBiX<&}4JfM:0 #lc?xǮ.6 B%uPNktOAIX11KK]KDvOBc>\ݳ XN{d8r9CSh#NNm]V+{w#; 30a`ۻAJ 5KRrG<oV،9yN|rڭH_${q?ح甸v%p+.Iw]e|=tl>ߔI>ös#ҥM~)x]_in۪yQ퓻;9Yφ^mQ]I灾V},c;C/81Io€4&X8 4z1塎!<<{>X9b>j2:8:z2 b&3DdLǗТ^AN\d Fn endstream endobj 449 0 obj << /Length 2932 /Filter /FlateDecode >> stream x[[6~ϯ𣌍_MYA,H53z,'M}/He2>l td:<<%3 32\ϖOmngOHh拫'})Č`d!j r3 7}ͭ}䇫~A陜ؙHB8AF1iʿbAL&K8[`DS1š?JOBƸkw R" z82b ^b5i2H":_Iu-VU lj H$E 3G {9׬om/uH\(R q$';Ct33IU<?##bzޞ$WXqR#\Ω*Lye/&rt~6`Isގ3P%,J"+eE>#"8ky g%dOɱTn)ߣq y#t"z;hEb$uf{7!㊆czCjBbXCtϿ($HUN\#(}5ѱN䌥1ξ8qvp,]\ -29 ! 3Dg/h8֒SJsllM_1jSo TcɇaS| +t^t3cy_croqcG⌲J vMBEF#0 ?Ŵ7D-L&,e#V2LmQ." s )EEudT#xf/X.(N)k@թ:CnE~qu2.fσf~BGD.~5T!jF>jV%2&S-С:[.pGo/$rh#1&_4k1>2tICH ) ۟V.\}H>S>ڼmTD=V"5ǟ&30n./vΈ$F 8RB/gTցfCZݺ=4yj-pT?5rb0ښNb[C¨U\ϲV($+$J<|A߁kF,׮ UxȵoW }g^$Y(P= M$(lR,? ;sa觲]skя-]Y6>VLTWz*yfܮqXh[Y& ض>!SepPON7RɊufU댿XH xqt]Wp@n-*kv9{sxIRcSqP^ë}cў] 5*rLBBƽ,##!.9td `RZܡx7Ւ HZ)XhFz9D,Xc>oo*7 gτD&?Й*cиYJΙ79DCϞ5ȶx1Ip Eرi{@3߫$IlEԨ9 "lAR"٩rDMn"nQܰN Η.3+E#̑-hT9wW>p(7=L,o|FgQj$Vb`X>Lf#ܟM;Fݸ-ȦNc:#êC-$}̭+<cza(y⫛=uH6.r]׻ms H-jT7svm0xzi_p+D[!v7۹'aG2MlGK}eil~dooᖘE&5)p}߬tXn?*V?LWUi_^Nn7_mŧKd71rM"mw, 6F Te"[SK8lj@ܛlK]p=Qq88h]^.ޖE=ܲf"CenY\u"&ˎ/e*2U}qw%45=l클$ughǠp``zzٲ_ySXB L<D(Ć*ɱ".eY裑_u(ܵSC{9*`ZXCyjFv@ȣ`Đm7!bD4Ġ(t Q1@67-!TfDx{j39*qPQ(l۵X'fYզK 9T%FK ) T'g-7؞JʿϦ5¦5'[/] )RJ ft=I xc1Tؓq|KB W%!Z)L_Mci l66Lo=lO_6$6 P9Se&BRwe(Oh􏌜 y+Thoî#> stream xZYo7~cax6`cHkX !CkԒ;cVs83R,jQW_UPN=1B'b$4>ys8J0Juvoٛ)\*ȫθ6s庞͹ez[qC#Aʼn0!Q;Ym׋ܬáesO#N) ̅+/aI)gp24Eᱴ%ߩ%[C ghng0pnzk<ԅB,n5(Jc0WAc[tQ,zfm 5Ys:[٬X4M[7nW:Ua`s\eSDž6Y |>̀A5y7VnɪnzQ)vrtGhr)MP`#-؂tĀdwl%Y~]m|ĭp+; yïW̎@(bZSyףXi}"Gb)QZBy 0+Oc*o+I]:p1'w˕u> 6&z6u,Ty[mVU{LʉoG:x\6.,)ǧԂ0։#)9 4$@q@FrrNuhCX>?ܗO/m|s8.-8`_^sƻ&|c @@#th\%͚[Y͎`:{{=71.{vJ`lFgUlu,')K0f;`1tzW5&s.X XRS7xFʹ"2xc5_4o) j1QU.ph v;V#oR&;ռ] rBnxA-ۇ|z+URVyC(sxp(Bo͛~)ةoESd6=՝ a!lA}+]x߿^neR(E\zF/eJ4vp`Vi,ЧKCQPeFNj1%O'9Z|̕`vcn0ty x#8GY sv@F`xx8 `ݍ]dzo.S|'8drGᮀB)R%jYl.+X.w$ Fx]"ǥ2cΙ@fjyfuV!l\>L*LpT[_~R)gb"뷏bb=RT}bT-):|iԞn"HbJ6(LF+m108(PB|CV`PaL=t8"kVXuo^].2rEkH4i@ȳW *o?#`HmFOõT4.t0;H y,g3Je,w ?`Fك L{8,L*_րmW 6ĄCn ~P # `+'RE"g0;H1i @r-CBׁch1(?dzL%>tx*t&QGpn+YEpHER 4@ZO9pX1bayK-}}'ܚ).\[YxL #@P?Gp]օpޅjj8#8kP ܄m''sӎ %<#H*\Fn7kr^*=m_MZ¡X@c&0e!I>Ǧ DRF^eO<]ne_HO endstream endobj 460 0 obj << /Length 2801 /Filter /FlateDecode >> stream xZKsWaˇNm*V\ÈtI>fbH*-* i6~} ?6stf NY,-pPY{fG-RV٧3a?94={n/8p'HygL {[V&dXTF|4>j|!Gj~{j p|F3D .?7ʦTv;1X+*j֯+L}rE QBuB:]6Q&7mX6&VfW ~><¿ /wz_Vz~uQ> @mF8d /* xqmVǻs7gn8(-ոAN. quD\#)9Gz VzBTOM}~7--2m1E7*XIh)J#Q4$ 46mq=KH3" тJRĘYBssd|0UjQ7+gY 4+ 5+ﶻ9Nx#A00WYo)? 4є%s&eMul F$1 3Ƹ;\`&3M(#-ặTSQ\x,H"3Kx:צ>tx*L̎[ &]tu k; Vǧ\m7L6c;D[M!ݭ,)E("mo1.}ӌ)G3A^$3 Ç(:CY}z7j;w" W]up?.?t2FA(8bz|j)}Б̙G,;z_R"S y V w`AJ\"(Ӄ]S1`){'VǨ$w_O" 8)̈́SӈTD̲ ͨ#L 2qd8h8i9tԋ 14|!ݺ-dd0;)1>2# 1>[Q6 _?4בFN)12" <%Œg^oJLĐ\q>۶ @(&KJ˞c$l_( hG1pڟ艖6g`)ېcv$<włi=$ma*+].w`@u~؎ksO/Ҹ+cpXQ!ESWl)ڽ/'I8H`P{[1xUC.pnF)rR:TR$ʟ>eӼ)zԱi_siߌ\%ܰv-;\9ETcsYA$&ac?C<\ZTw o 5hPL&3ASP\-IwO1%@6FOԄ~o? 8V/m1&w2::Bt"Nqg'* xc{='kǭb:Mqn×%]Y >G>߄ ]5Ҳj}W.NLK/K[Ԏ qu;x4ä7y u'(qUj0+mk_vW)'zHoLc;wyhHpv<}pܜOnaLZ%B=4XR6x)K2^JfS28KZw(d{@a[Cq1q![c9^=7*LWkTnq0_J xnC&=uvpᆮ'}&õщwh)N潺_j| 79X@-mlT9ܦOV G`/M iAxOQɋSŒWp}s"0ugeY77KYJl}i l\?8yˈ#\8?@P*q.ݓtw\(3a!QyrǗcsU8?Nq*;q G;+\(VeVҾX- endstream endobj 465 0 obj << /Length 3091 /Filter /FlateDecode >> stream xڵZr7}WqX1/v!Z)bG)x0"Gؼ(áv0$47 ht>A6fΌI;[nP~~b4\Zt fG]^g/󇺨 !D&RM^}s |.cng[%3ș0!@u^/hšk߬ M bmZ<9jΘ%δM?:sDw-Jd6pwM{w&̚bDO?U2IC`IY"O"V]hv,5wpaf &S|J 3b-?Y1Y0v:eipsfҰJ&eөOnsYEk'K a؆/a*){$C1 ZM6 GC^^/R ('efʝU;+HuFbά8J]]m:xM_CUaƢ(J+u:,r Իe,XrNtb@lB= _R1 >bb7EU.->#.\;W8-"ƂYOoC#Ha j9HA?%3aWEt|=K&Rc͎zxyB{ `\Lx D|.`e ,\47M#_06 /Bg`3;K戡-4 mi &V]71LI8Kpc ]yw1ο^}Nʧ&| ǘ»/8lj b!bA`t 6~]U{Hƫj 'Ō#xz6[E⪮ʿR.%Fv{=NƃR!I0z8BMVnph4L#[G̸d+ŷ)GՇ0<V ;R&c愖/Vȝ%~01e)v+ŔPv6EX P9LbObKMM :34Ⱦ},+%޸W.(σOp8=x` Ϋ4#{1'&4RHX5v5֤S8^ ‘dLWTw +X;L]>$L?=CparaSߤ OGɷW(2vbYMbuu;?I%6c~ݭHO%9&9JLԎ!!&:TJ(Aا,wKNM1eO dEQ3>Uۼ:Q5r{CX#oEdkN3A,aZPDde8x0wa3 R7?λ(9Ůmgc1}w\g[4Nam:[@DŽ/kp]=w(00qRiG4{߷Kg@ >ChrWW, #U22iҮ&y6i [N862*" =nk,yU2iBhB2ui mT^3(W4.Ȭ gyM Ba k^%ɸNOlH/S3Րl\Hٴs25|ϞRNz56l5mBϟtFcpPm 3[0NrCvdoSky®>~sJ RtƋnBE41 4Bz;'5M&}J_tvˠx(j_oR{'U7ۇH:ԧ=C1((4ը")<]9 o?4;}1П轪,ɺ|Px--,oA/Ёt[%yP&n`7蹼FC[HQaQX魪zb銊* /I#/d^Ndl9pf Wo/J&&WKw"mW+,NV7( Kq9|SI=6* +0n&Ȃ nǼc"TH'<ϾܗM?݇ӐSmr>F]NqmSǍ0i!ԉLX!bj+3pR+%W_rGhik -ѓJ|L pPaop6AB>5tq 6bBK^`/]]`ݍDD|MzW wG-h<7LHd:YT^in C6c_t_R'oȈkj9HyacZ3B߆u]26p{w| oNcry=9- }}\tk׍UFƭlɦ#xU= endstream endobj 469 0 obj << /Length 3230 /Filter /FlateDecode >> stream x[[s6~ϯ#5kĝH7餳;ә4 MLe%s m'3& B|E ¤ 91"[wR;,O=~ &&3|K)4%&5tqy=%uyxt ɴ*vm-={q9, ;r'8s+zJ3-T&­Ӌ/~zq~Wd@L.VTRǤ(+49͛uC*8*\{|T5'| 5F%~y3] k_K%]Yz-jS;2luO38XuE9Wg}f ρI7$?`L -~7weSy'KmywU\*aSxudtJ3FT 30(Q_yM(ϜZyB ɟΓ؂ …bD Dc [0Bfۮ.;\]K)nq*%7je |Is.۷yk/ e4)$xI_bS6 A`.FmwBvD휌Q$テ1Bog0jsw)6+{3=aUBzx(7eXŤ$i6`R: ۨ,1r8ܰm ^el4D3#yKͳA+OB9H^(qV()"} xQnЯFr/ p0]1$O?BNA /Up0F[bNmEyuPjF4bBbgB"fЌ3e Ny#wZ 5;.a"#n_Gz{`T< 4 S!E õvbq %THz4W8j:-ۼ|F1#SLj<_r &7}PAf_^\-&tz#9nmp\?=<~aWT0f]CrxP:.!U(~DX, 1)UkJE]^Ǽ(6M`> ) rLjKʶ &7e]6KL:̓p.xI€I fZ?T䘄b&o’$c4P,nJɳ0T0|-]:7eX-v0*^i|Bx#}QֲS  o@ D>us]mr]Zנ=G \#Bo2lVp,Wjm)#e7g^9`Xq4CM哶sYkwU{xslmlIqS;_ඈ: C9x\CbjzMt&\ab1"[&b12CAtD* ɏc9@s.4UONxrd[5gj] Hʦ\1Ӂ=$.zPlk$Z `=uy4&^8MD~~3, ?g!A 0ARç5H a)%h|u<Z>:E7xmڽpxVn9媛Hyt/7Xu?44uBn]P¥Ai O)?crs،"I J1d{ oq[ٖ]U1DmsVl6~FXq!!b^]` úo*p Ha<@Hu`i0.8swEޖ']5GΆwU٨I668+նޭ˨`bkBjmߧspe nM~AT|Fh&BͿ^[ 7+yoqv':;mc԰QjfPr4{Ҋ7lrԇ= FRuA Rkҫ",D|Ղ*U6ҁ7!̰XEWg;lj;*{mׇoRXO?Eizr^!:gF]u~b!`!<bPRHc>cqlfQ{uˋQvڨpQFeS}N铄VO)c1$Ah> >P;w!Mbv쩾Vj>u.ŀpV&HHX@׭9S&vD?T<^d&EӒ]4kO =h |r&rqXJ(8D |Ia!aϠV`k.HFeR5筠&5VzcM@$X%m~µGڧqf{T냵5AF!(ܡzCլ12V![h l*@J`m?7}0CA &7c@=|@L gSXj0ղu#omDT͉@)ßuXNM-ksjQyUCͤh GvqztN[!ly`GZ.f[N'8H a%*jPA( bIQlr;2;Iƅrëe\Umє?IȒ~R a`̔MZ> stream xZYܸ~輩Mj ?$8O]yF=׶4οOITqb#UblVЙnOͿy9LG3xWJ%-lZ>d/>s!D&湔*{S36⟯L7<ڊ"lq'/ڊ ę\j1撫b%TEitӓKMjST=OckG٢Ř/2m26wש-a0I+KҿWvNJpܲuǺl=O 0MAklrl)Fr{Sv5ynXܢ7վgmMǢÆM+:vNAT3A 6mx^sosŲ~rsfF?ի}H/Ȧ9[A=z!fz2 ]a" &SGɿv?'ׄmttGjoy+3:)}!(r~jDCŸ뭑N H=Y]ݣaprfZA0ٷzs_MU4<4m J.f)4X ^P"Nr΀)~ZC( XAS1_'`ˆ,0Qz})yb R.JtEqȓM{SLR!Yaȧ6jnEv^UHE-^$a q L$ƉRb-v}(ȱH_n~):pcIn=a*>ƶaF$ TM#wm~GSSDn(ġvwM8x/7M=05|Ekn TcOuTK Yۣ w7y[+34f KHp_@\s^* A@ `&lwq}4ڏ9ںl2cн Lڥ3 FԑmAwy\{/VB0BA9dd@=. .wx8 ]v t<(97<{$j:ł!V,eԷF=V T'H|${]uj@&վvh>BIZv)s& ?޲.de1b*^}$ E(oPqHq0܎%~9ȠRp 8\$] ´=Wcn!HM {:mPb96 ­>58Ro}͛AZd `AiysNrq?E#c!P>a nxR YnPS>X}IFfI N:..#7&u/e)?ėUc|@I%9|`vMӃ45Pe4ˇI΁j"ߗmm G:1 `;(9'R>`h3(l2j"=Og U:D X]h> stream xZ[F~ϯGx`<37P tQRQCv1KIM]wvcg%*xdmB  ^8&|[&q4‡K`vJD1E$E2X-Fv8 6ZF:ᝄWƒyUHƑMܙ L`荲X 0 R`Sj%+TG3x& pʰvO$;`& k-a#GݬS<gn .z'dp)B쏷  !plx6ˬ  7x=e¸\\B()4X" &9v9l 9<$/ ((S'62#0x\EV1EvHxJ;F9 X -%)AV=F,5}POP0Ь:9Xx 4b0Ǝ6@$|$$VV')82LADX<Y1GF/W~ϋr=)x({mbqtdh&ꬬ^m2"#ͫ_>aY煜Xdz;s)7r|0Km˯jq/_M?LOk5{m_tTdg٩51X .6kYb?Ngd~Ó4/!x"h$p^ Ճ_bR~ZI?U'󋬧o8D"TȌHA|7AjY|,o\2@] isg 0 $:MRlۢj A0"5Ҧ^FE]u׆w^̲o0 ՟Ӓ2ۘr<t l&lmeiP9fŴԕygu>-f"U-Gg\8};8mwrp 7iY՜kۑ?4蛤{aJ<.nB݆؍"-O=Q V Y3 6f;FZ|{J䶳fuÕ;&ߒ|ѪGO;<"+:vk ofgGG,'G={5hb*(\\pު:ʄ@sCmc*'9@CI=m{2U1wAx'T޵ۡo#mzޢq>JIf}<$C0Xd{` =V.j0Ʃ]ʼn?8٢:I@d:,Ө?}}Kƽlzȇvy,Oݭ endstream endobj 481 0 obj << /Length 3015 /Filter /FlateDecode >> stream xZY۸~_GD+UY;[Iy<GgKn<@Ax)Wy(l4褀tbXa&UF7oW4ab>/J9CRɻNh T]-[@2v&'8s&x (#/ #lKŲ^4ZfڬejE^I):5<ۭfM^לg֋^/X)~ބEpeDn_U&YbȓD)N_" LvMXg(tGYֻI^BSB'@0QY5j;Cz_Pj[/˅VզlI4YLip5VPBK<T'6Jgje&kjg>o̽=ZLqFg8hW0vOn\/ٶ)b{_Ϊ=^p xOmO!;Дphg*=?~+vڿ= .XEJ.$辮S5xEzlvXE4hYURd=8`fQ);]RN'X*ϚM]sylo>nKT F zYoړnhTu!ĘNW?l% ) M,#L>O D" D^l}A&FчI#pJWhC(?_0 rQa$,݆˦C{MXAʛ E6Ws>XbS>] n9Pb$/AI,1s~y ɂ[:,DHb0N0' H&Ƨ\!(/ L.r9 b$E(UL1Bj2vGB9_AcΒ9>FBL4 s@ec̏h/@Et WC!2Hz8mG($;, @H;c->Z'Jn߅]hk] Hʸ:ZFΐ@?$RqN'oFltvU٤ȫiT`=sgp}wTbXG1ЗelӌXNqN;?6x|BN yj\ 4h3l],vpԞDOwH3ݗfsYߔ7fW[?ԑ}/jg}C_:`r ~ӷfѨ i2B\v Y¶mp0Ů?)]%#׋ o_J1!\pjNҧ]'",Z<%FJG同ޟl o%3ջd/!%J/n;ZL^#sc`bj%8Pq%$fDFTcn"*F٧O1(/$S^$)}zc&u@<b?%#i|Hݠ'n͍S?gm{p}K mdwBI KP,9.]@j%Ѹ{ܭz% 澽벗@?,+gdW@wH~#hFX\5 `$'iM.NvΎ['lrpj٠v-NMu\kIw0L޷ͼ7K{( 9;.|PN0,⩴y,`[91 vbbtoiE3/m(VvZyq8-Gvڶ䰹?^ endstream endobj 485 0 obj << /Length 2240 /Filter /FlateDecode >> stream xZKsܸW̑S`~XCvN9zJlG3V~}dG{rHb@AdaB1 ׋voH[j$ų^ lb3j馼fbrŹ(~./.gvR3SPxg//ڂG*i%OTc-0H+ 4KDF1m%\,VI̸L7HS Tyz)5Bft׈h(58ENqB bP c\\ZVŽI@%x2^fqcU>e݇WLRp4cc!BQ&u[W_o0++->AvŒ%LJg9(%9n$<& b " 'E֎/̸RaŃg݀0.fIjr1E\wަҮ=RXv.t7l#]u~wU;fMQ:AF E,601)A W{}rmGfۮMdus+*ݮMvcuhNLĭ:`{Fj>/(ʭ}yCrΑ*$*ewVAMŢV^z}-;/yzh qB9SS PGx8fK&㠟R`=+7@߬2x$F!S2 'szX@:# vMoDpL#(݇R̐~zL $lͭͦ( 3^evh65cY]oǦ'VOKM4+fpW7Uwet;t跏ޜp+^Mrk/6PsҩzK_a,.M{sք$Cd4Ի%o~[}N}gXnkogH2i1'MH+lǐ0ᐶeu%)]5Wvn `I aݣWM*6Qrƴl>UPARgO "2SnBxVȾ\|g=NgC 5Sv>M\jʱXj4&Ĭ2 )*s=>Æ)JA\&*:C{MaǶ۶ $vs`)A ,><}f%NNR{e:5PN(`XdpMU`;ћ IDKkc%IXgb#,mcWT{kl)v!?ڌzF~vZ^rQ5rRft Y3LZ>T@ƺ=zU٬LĔ R u@?M|w~P@Sn :k HHsaR1-{B4>!v9\zK?=ejJϿqv%O9]U}kJGa c,x%?Pw0 OfF#4ezDe)~T͓56=9'8!GvƾNN")Zg ^=a)rIMPj4=Hih\=͡Wa}#9Ws $| ̷A!ywc?otՃMp1l4M?4Lyb+0ؕɬҏu&z0CG0]ߪ5,͞_p>.sK(MпYx,]@ qbWTH۩Bkآ::TO{VX X8lct^F~Sd?11A3 j17ɗzX}#f5!G"kaͣDlG揟Yz1`JzhrUl"hL4^Yuh-T7}i⊳Z;WU:?X 51є}`'}='#Wf#[@``^G AF4A|$AEs{?y}<I?0 endstream endobj 490 0 obj << /Length 2014 /Filter /FlateDecode >> stream xYK6WDm^Cv3J%U^(%Zg8m+IF0Q2:K Գ5̾/A0I}WI2cd4cvj}\k&tFt3sq.=~{rH8'(+j $<)- Z&$J$, +y I_Y'cu7Є6>WCz18{`ylNژ ũ'-3|f Gn^ kvo-tV[޲4#'Arqma+NƇwֈNHĞJ8nГPc 4\/Ld6o \uð-ŗr[=%&;oĂdA EK&µ/aվZmYWǪnw_HtU=Tե|bo$塸ÏˇSn M:G:^i>% psEYłp"ar4?~ u~VDD`^`ơt"Iػ;@\Ҿehj ~D¬?[~WMUp XShsF4p~3%!KseeIQy4֨o,aʸ^Oqb+8I:*_-Mi^|]7Q.C)Er"N 3 vE9j/|BSWt)_M*mє6i-:^!4y[$Xl ;9{^lpu~lJkml`.c2N~Rn+,\yY%>NK8BqR 񲇾 ;JW a)L|»2rK<%ບ "Q!+tOt 03 |bt4f H2Mkd ~uJYJI\WǍMicz!Zq0uR&K6x [5^h&o[v!&2Qt<4QOy:Ǒ-·hab&XOIH vkZXe }~Wؗh2ftmy:ۦt=A16XSWM.U9JR|J6TXѡ]~n.Pt:/ R=@xM\۝Y4ETi~riC-wx. k%Mr _'#‡HZBp r7 @dA@{~D*sġ;~훗ݿ5 endstream endobj 494 0 obj << /Length 2033 /Filter /FlateDecode >> stream xڝXYsF~` %& T~PT׻b[L%UIP ,== T- Lk!DOhH2NVWz|!0=~xG,2>YlͣٵR@^NCt07H B߀1/i(Tf?~u8B|qK."ĩb\*r0LA^1}K5q Ԑ2Gܙ#݅|Tښ5u$unP95sBhDWLYvmg2(:ٝ# ]k)l>[&5<s39rKӷjا]Ck`w ~rx*6+*m%']\ݷW2ed9K"eO=#N y΄?LZP,(z Y6U D4Ei{QT+Uy1i/zeZVOfsq~ c][{y/6vMovvvT@oR1[q؍ [ A:ؠ<tDh@kEk @ڇG%04\9)w¼ ')l Yd%3qVXzm[F} v1ۊ u1Iqt$c7 Hz8I̢DzX*_,CBJW^Ny`.aH"6'zo"m%4ïKD G?"ʼM5=hg8.c{@%,V4 LPEQдn&`SW[2/yH嶳Zw\=mWWK `͘Sz$C o184#Ѐ#LB:C֖Ћ YF^3#"<Zlݵ1y! uU3zw{ݽeq,!c; `f9/gir;ϢY:8cUD0?oK4J%u%UTOkodxI%R DOڔM jw᛫q:„`pE3,wesceiEGyJؐjyr:@dxJt<ƊD$&4qcnyZfR%/,0~i}X\4g\trO[cCBp(/8B͔3F0D-4`#P{9aYBzpb9ںp+8Kp J^q0pd]$i5`#̈́8z8 5pmMۛ~f7Mkэ 7="&H,KF4C7{kVSřVEs1KҬ0vyt+"ލ9'Ͽ,C|8arlò"U>d"%,O3 !'E1ئOն%bCPX?1@߃ +"?@%Jxd{DX(=4Mzon?ޏeJ{!fəI25* ~t*E֧緵k^rTȋs?~!Ŕk" :8\_ьɈ q({;ۢC_Oi熨?jo7 I0ǚK OI#w[@l_ʺ>y"Q~ۃnW+]AS3!JXGNQp+b2MvHh1JT%כq X^ELvvOgL!ݑ)<|bTCD@iKsrFk$S\i7飩kCS"_+5Mw>SI ⎞7gnCcr E2/v[UV6*@:*-FdcXޛ)Lk sw_ږh endstream endobj 498 0 obj << /Length 2068 /Filter /FlateDecode >> stream xYݓ6_Gb-ghe%VqKKcSn̓lduR҆kqĿt5q(ۮ:]nB1aHWeqLWաLW\%uz܋jJ) Z](pv4^@zij82 {e`{vQ[h?]yy҆>5}75é>WEW=ϏUކS;o7?/6l__[= e-ˌ}qG4s1LB:=r=x<aby9s%_jc*Tb'Yɞ}Y4qIgbsɤU]7 .KujUn)cs.~EۺYh钟.&4SvX&` i.v2\^>pMx+E܇P;@bu6hOLAkiaۃApЀ-{Q40]U=ZK`FS;GàWA$'8 gOZo`kS-;ϓ`P?CdZ{з_Ƹﮉ`*m3;c}6݇0nuS dW͒$KɲB4U}A" u3~S@LIGQ9"XK3J~]3ɻW0 m:c2$}.Mqɀ~>ܟrK W-z~dgЮ=-cBnBEh8,Usƒy)7aFɕ߆={wzѳAqayoLdN>zڹ98gR(YQ' ؚڜA.hdY\WM+R^*l۶)i6$J`yZ!kO 9y5wAuI0g2Bu.f&&IϠj95#ћ(& 230f8c?k3 \x@/겁Iq?QO0:#VcÂT>ї?uh9cByf{tlG4ϱ> :RlKn#hhNdO JhcM&Z;thE4P_ ~(nZE{7q9 DǠ.ͩz܊Hsʗ:z-h*Bݪ8 @+ΨxE?)\TV?Z-5gPU%śK!&ؒB ]4X4U*ÜVw`/9c͚ـ,̻?a8sS.=Q̃,fP.1F$ ̣5ܑb P3"$" V;|7`ncp endstream endobj 502 0 obj << /Length 2088 /Filter /FlateDecode >> stream xYYo8~ϯG5\9b Ƀ-5Ñԓ"))= CSRXWlA- BBzڷ-^y\ۅR FIA Y(.{mw/{5pRy$R>8ӄ3%L*70!qrR9.ZVeWv~>U >OmW[p h cZag?y~a 4d]Y{z RSZ-Tvz:;%Ж%XXVmP sBWe[^#2{`ն6M{6+ר߇RYy bqC[|#a:QnA۝>u۪'Md>CVxYqۿ;isJ*@/Mr~G"$f䠬WZ.,G~H޻j~[;1I"Vl牽OQ7Ѻ]W b/|E9c bU딊9#1C3ACNG| !I}c!m.缣n]iÑfUj'bvV9r}}2$KUh % L `".ɘ{RW KKBC N;8/}[V$z]/]MB>=dUAo%Z$ DL-p 5QYTID>:۰5nu6+g?!n[9Zd3tUSvi`>ܸJ8"r9\@mǮbWZwCCk!֍Dj[!43ӚfJx.[J]%] V>_e){@(II2OKPi!fَ?)PQ+b6b\TAȜ >fdD8A8|τDZ  e[oţ2yu%ԕaPf{Hd5qċWP M[5U4Tc|MLsZatnk9 r^{%7I1vRyO  %f T]<C?Ol E5)ȜXn6QIDqljj?:3ޜp}>Ɠ#ľ~)}Oq8Nw _v~_@>s5~y5Awg]C|5Usź9 =ę@g,~`;kE=mv:RΈ raдvwͩZ)˦!4&$%v endstream endobj 507 0 obj << /Length 2894 /Filter /FlateDecode >> stream xێ۸=_/4f;mI6-l2I[Q#NCRiӞna1stVr9'Vbut݇~vusX8Vpq/Oђe b9{S0s3n,17iWf{r1n %&bT(5̔r;,5QfۺZ~j[͙uy_of{L'e M0r!% o{Y;]^x[ʲY/-s9` &z9`8f]HixEs`KX`n65.~^Q[}F]]׻^W]u1pm޵ q4-%j́eHE. Uz8vq==Mq\&1UZ(T`:G=vukamA^TzmI WS &=I<}Ob%%Y62`&PTYiȴ,nԿo_ugPnË3Ë d06ZS9/-"l E}tg < C}|U5ڰ.^l6H[Uʎ3)U`.|xAES~}62E A90NptM[EnZsk9"؏3׊:N9+f:x:h971~Z4p[Ӥe@-@ zT @]NK(Qlt/xx&0\嶓 ss)xYJ/T TJ(7#"{U8ϾY5mMx1~z| jQ %N76"$=ъfs 0B;PQ4`4 r" ㍋mZ`{D&VXPݠB )8xn@0]4v\4H.GZΗzP6n4p ϔ39 2" rd+"'15́&F9&~j|TZיpc?B%smv\+TQ^\n:@͗˞,GJ2Nse&k\V[zPIWRUM%WϾĆjɂ&:Tːn|Wd.nrQ<.G FjU1 x(rӷ%CtjnRH)k?\̢Uy)VPf}UNg01e V-032ĚӨbɒ޶S?(KH!  㷕:MM,ghUÖXTNS N3h![G#̜֘=>Q#~sz8Xm>I8FTݡ^ WmD"X \0x T=cZj߼+gKxllf_B i5 5cJsB)HDXl0<~/L\=-#Zƅmgr:.u%#Hs^154)$RMt$>@f'-[e`y:5I" ;IN MB=c\ 0*DZkGWzQY ,* \y9TZaQdywXob`yxğ#'OҵZF6R.YH݋P[Kut|)m2ԃlgcBi֟2~!x<.w{W' `S쟿󩫒[2+:z/H(3ph> stream xYoۺ&7tI;qm?(k,W;|:qvaSyxxa#3g1y2['w37u1,+/'bF0XvHj}ޮ.1c,o1"7wEw.6>gҿ첲Dc#\.:~G2nV>\!$(Ʉ#¸c8PHQ㾜$euk~yTg?Ykl[guco&aYdTy~$I10i9"DU8x/*5\S1 :7l7|7"‰("ݺw~:z۾;:q޸߬^*ZS$z"ppo^''>Ez ]Q*5 %bC n"eg{ m&٫9=dW7 T-dWum:ΩO97s32c:a JϐIy9a6$ص/Z /`^N޾(`cVBJmˏo/C9x 0QAAR$E'wpa*qtInTpݥaj}j e] ~vD̽ef~?L9G6OS>7>f;ÐEoܬ?D޾raAKoPLE| $q7.Vunld&*|ۀok [V%hzgȗil9OC ix-y4Du+D0mIjZ6h`ToBpyoVny)Kb[[{N p8s*1("}Q!,ZX'R<46w\h_QJR035r^) ׻}cH@_K_gE0B ō'\Ii ?={WHD@@0Ԝ2aBSHh92NoӒIuSTk9=ɤ/ݸΉ:D\4 Ԛʴqḁ[C0HH+8 Š4 "Mk6.U8QddoxѸG'7.xNDьl|+xe+6%?ᦥ1|EÁcL1ƱIa nCm,+?NV]aAe7+HW!Oz< >jkg<] _,t:$ d hM'6|z68.pQHod` %pNsyo ȔڴHhYՃ ~gMa9Jw4,Վ`4iM8pY&0=}f8EH;dYiM8jԁ2v C߰/vI1{1_˖4䜩 : 2ANL`e)mW8d6}: F&@='Uq 'w!21z`LkSXXX!<V#*=ڕO<w L1(}|5<8$;38pCcDF'POAhz]Qb9W. n$B!C?$2G2? y(>lݘ'#~ %Ա1~*Q9ȁ<39nJ)&ڇ:AZ9SB_۟?h"u>.W(7pRcp|6&] 6ӁڧLBJ)ԁXV ,eº2ӈ1RuxuO.T."> stream xYے۸}Whߨryn=JG,S-Rspu&TH4OlA9]!H.js?< r)ӑë{~ԂQӜ-ތZ/^&.__YN2cPj{cݻ'PJ>Vd I„>Ufd,Tt,A&: 'ì2B$˔gI_>.IU7}K]ˤ}dIUєA}[}񭟪{0M'>5 +0Ed˧._.ZdvxE9b`2"WĐįx|nm_7_l}]lo҇ajZ6GiP#b^g%ۛlu `ܕ;&KnnĨQ$%4ɓoZnЖ{ϹƎV֎?LP6_B7_CpK`cʀ6!:l8Q&&7eIuL|/0bQ7cְƖ n_VKgfpqXH0 MD.SErA eʒ=en<^0~<9EL+9T`xI~uz\$F\)_7BXأ0 =E.;W  tFW;WTԒAg&ܘ1 t׳7c*,fTzÀYkڲXN>˯몮ZϾy9āb\mgy3ٍDC\X gACAQB-d0N$[ӜpڧK/(,I)D),ԴHjӓ);,Lxănn o*6ǂmVr7xVhud[gy|nr’BXbӰB,+B;"C5*]U\Dr@ rr@K3Ni}*xacFR*q<[F(Ӕ F*BOjm5XcիUPؔ))A>*̬D\>(,"}^]͕܊+sVYK@t>1uY.{sutFLRVaCyCQ E(`O=zaScwF1a@HEqscXҐ,!b{瀛Y lpG )SN0Į=yn𨪋.(ZFG(po!PKڲ3B}l>o @urqڜ䙰 c-!:S^p\Y RHDwWŽ|Mk|DF4f z}7O/$H*HD NsfDm ?ʴ9L]ÉĢPDQRp`c}Y͸n~E) WR=ɱ\[jDC7zHDaǖdz"EuD19/5Q))@YP3QJ»ϦqCA&-7_w Pm,< Lޅ_$¨])Sbc~n]: k8P*n+T=5(vc}Vr.aRig)q<}wVY}\C2aLw~|엫C="4m;3&y%Ojp>P(`B*Sԝ~TGN㈘̴ϛґQ<徣zF+Q8V>񼇐/]} (#\gv(&C$eoER=\߾E,p:E1q_={R(8{ TȧxݜӃ;> NɒI [5Aʛr?ƌMEl6GgKQ捒J)oCƦGu:vu0os?ru*tƄ.ѹ!ꬊBa}91c5^H́ vF~!]] " X6zHCϿ(v1 G{ĊDKq{ {v&B]paftdF\aEۮY; ViA4 ٳ rrxu"}(n\hU6US, -{HRIji0A%sedwa`ATq@u͛޲K6s3So e_Yyhsc2v;a:a=V1J+JLgP{|ñ8 l$L\NVtsK$.]аֿV/L}C5 jmXQx]5μ8UjPkL5KL#ؔɵ8~-3~EUۃ;.]IwoD endstream endobj 520 0 obj << /Length 2536 /Filter /FlateDecode >> stream xڽZYoH~ϯQH`$bIh S#R1~-$dQ ?)Ɛ:/ats>#Ab"Bd# ..٧myUYY/MSg]땿y ]lg1Xٗ.{O4J>\h39"{>'8(B H2饮Tb4H}{xX(`zT|RͬnzwW_/ϘUכԸ!BT3,úl # ,f7?F;Ӕz*&#1f YiD4[S$&3H*ԅHIΓ2 a}@̺Mp2HK$Hྟ%uX "@+:>}^0bFgNtAP.kg"ψBZLR0 I "HE Eʋy1>&4IBRS'"9>~pZ%4_j 9'o7 "p]p W1,p{"K Q(3.YaQ%q'e@ABE-A~Czˋ0&ÞнxPU4o^9)`\z <=)8?2R@a[=F7B>7hV˪\o6y B6R3bq! 0-H[=Yr>: iZ[3z}cSI4^/0 5:mҚQn.N ,ЃEozOӊUnY{$K;4^oc'1VX#bD<IjJd՟ڮ3G9&^?Ρrgs{)`c //y_.e2!oH4I6LP?.`%уȼ YX/}-λ=OF *muBFi݋I3X6 Kpv~ (bd@C'1WXL&4 |P˥}~pU:HR 6M)^jngYMv_!>`gUϭ $ozIjp˗ec)2jܽc. _3 .h*=a ??S!~kmvABA$<]\Prxw6MP BLC"HETM~6r y\XP0jSIQ'BH3 ~$qѿa /p(NW.D$y # dPnP=yQh1YpX:d `i1YN6,ym>EiPd365[eor)\" gm0m媊ɲt|⻗6O؝w 0#^&P>T$3P=~xS pht7\4gOƮ{zo0qX:]ٶɬDOϠn'6\ veD]=רḪgm,zNh>n@dϙ((F&#+ixdQĄi6FF[ ]5΅ ̐H 50 endstream endobj 524 0 obj << /Length 2685 /Filter /FlateDecode >> stream xZ[o8~ϯ𣃍,f-ڝ6)@VbMe+f_ԅ]',EP f39̖673x℆q ϥьTjqθh R\]+ ;9&=p%8R.RCLA(~g_D+(o8]pM޹dPp5!1dُ(IMBYhŒÿЛ攙X}`k}o:vwUhcz@/S \qL&UQIMIN(JHQLrEjYzyj3>eT-Ok+ma;vUĶXyVsCb<*+pb,7uwJ煟[睟[z*aEh hmMtbvAaJ?+Gޕ;ݺ\='ewK#OϟJ94hl0 M E CaEӆuϫ;;Å{?N Pby(Pq+Ѹ2E{낳޶aHWnNjoMS J7)* ;Ar6:T6p|xovuu"PV?gYp0{?NP2WiuG`Իar?"~iu^!});އr"4%%*\Ƹ=UfGà+EۅM}_:0 #&ȶ~#'=C!ogғKpu,_oor/RyE) 1 wYQZk3^ _С`ӶM=Wm$!Cl_BXΥa.x `dAh C>`M33}E>4C*fb"A&O_0̵CzX`<HPIc<Ţ#Bc{2S;+l(F%R8q/GB=d!{!2p&B91ECj d8HMv=r4\F2?+\0^!4þ Tpdr]9F=0}%}@K3nd |I<+O ፹ml;t%l)66RAT 66 ؑ@ݺo;Mqd^5HԒuQ-uq?AϽ0XV6 r`Uݢ ;:Hqݩo'X5*R1OI:[,\Uw-Z(F5Sd (2 "4 BaI|> WU Jmnfm[/+$.P{-8Ʀb:w)p9ā c2{X9yq^AOj :r !o ! Dž iv(CW| DZ3 *%j&eu_&5EIӝh"u\>RW}M &h6.p~*v!AA bOH6*X841Bgb;lws_!M*LG/YHFϨ> stream xZYo~&/V}8ENֶ 0Gbq &:3~/O0Julruu5(r{1BL㋙jZ-0.j7/径]]v3rS!._?}g*34׼9c؉0!=qDe~ƫrKwT;L_lDDfO4z?G9&Fr1).,FN-yZ]p;ݯ¢ ]_26/w.X.783+aJEDj-ǰJg^QqlDh"USNgi@ cyD4OK8S׏khڼ#;ܚY:d@V2nDի hEMݻIPZVtF>/4"(.n} Ͳ({osI/ mκY┺ZِB{xq?a[E'_tsfILS7AS/~_{z}uY̿vu,bz\5B5΢nֽ3mpsx=ztgS]Js:ÕW/QEKI\.E4xٴ"% éJj`Ղ0łnJ_.1aɅJX^ 18-'N F!(p !r?Ge|uL|![hBl )hݯowĻ4z2^EZ;!~6\ۻ]F\/AmZ|5/r A_ 5DFd`]YwHyVAxb\q@)7V}ԛmL)-iXP( $*~ؕr_Z.U|Bou7,@jnDU)m.w9$ wkBHk ,)-WfoiFtˇd _tz,2R/$R30!yl]Ys"iOh)@O>8Qc7";G`2jYl`tc@MUsCB_vTO>dG)݅_n:K+tpSiClgȉaw 8@!@.Q~i6DM b h 1g :(Y(;E|mp(@YȎ<UuutDWQ´Ի9E{~ . puHV'x#1Ѹ^ ͉ Z $_^ۧTaQjYoT--j'i[x_ =(}h6B^|!oƄBxJ ]~D{,_bӴ-0ͽP3nNP=;FEG_JNid@rNpwC"WhHӔH)$Wt q$7,0Aվ>Mǫhn6cD̞p_1rVj; ZH.$hv' ^P2 E 7a<_lagWpӟbݙPpCͮΡ$VU'c}4FzOKoci"Tq0.%vиMvA.N Oi |պ̘4 tLG~>LNĜ뀇gu.ᖖdA"|SW{]ɫG/)|/JGrbv*%_V ]DC[S>:Ӫcew0097+&3xK$rոc0K1QaR3,ϭN?dX!]I Z(,> &;4ʬ(1F"22~-@6kgṚ:tʇ]`OGf~B/~eMjB&٘&#(AЉM 9 Y$B|^1;~tN3?AMH Ed)*Yyl@$r)y"|EuTW}rPUO+WMÑ+}4I3C>w?Y }:lm) Ulq(]v:u8BИb#dԾ/d \ }Ono` ҇yKdSO䅅wUƁ 020t?s Q]?Ja!<R)$|!4L@17Y3`G f9fZ?4*2O bypWkW?tx #Τ m<9f :blAošD\N S9> stream xY[۶~ϯ Y&N4g7MI]-kk8d Iݼ @Lǹr,tÙhVV37yz.?/_p%匆DΖ!z1biǚJ;y쓴ǵ%AǢ($E wwX?\ElH !9׎038±RUeU_2 L6_p.4 xW(és"NS-1ѐ #NB)0iD:uFP! s&՗tiƎuHX($v ϩnYR9ʍS]v>}}Z%C8$PF[*:)Pc4_90ޚo@Y0&b!U>[72YV"W Ml7Q?M_kyl:q@'rB%uvW>mԋ:q3c>ɿf#B)LKY-ch31lqRsa1&j ay&Y1pioeߤYiҲ4h$wW%ΚEYԞIg?|4ޜ&cBo|dw3iU؅gk~XMwUygD)lMө]yJSjVE*drBv!8D{=XH|']J^gd:398VJra0 y>b9Gemƹg 3]<׏%I'Yqx  E!#W~AnD .|AlupTSGx3Wd `ՀmKή)ܣ͒n㯐 ܷ,bhPml2$ӈH51FX賜ⓕ$ʈvb=%%4d$z(s,X Ryꃼr8Bivj.榣&Y`ԣWHh~ո :ÀBǢAmL=/ڞf|4c1_k`ۃ`cMKOGamh# XB#hr l*Q1߮*iK%H]X ꒮'<_A@1d}Tt ;V. gurZ(kz#|/lg|# Hz~aK֎Eg,x*0LphÏiE-e*``g)_i endstream endobj 537 0 obj << /Length 1880 /Filter /FlateDecode >> stream xX]o6}ϯ D-Z$YץKbw+AvXd6iyyyyyx$?:I$",˽ȴWp~G]|#)'4"Irj~1Z7mVOCy ^LC!d0WEffmھmMi4dp98cp#{bh rņSxbA(6r2L kU*!017Q3Q#5aM]e &oef[uOe=eqy45;92ZW.#gh51ᝒ$?QLzxB,4T] @lJLЦimb2dq2. *&.E r `PuEZ..Rxa)w0ͺ{E)]^`vIJZ4քErH5| 0r.[Sko77u;%/ |MdeFӎ6m^_ {a$|@vI;JW d-Ila c:?<:}-%vE\1£`~no@Xݷy|| 'g?XN'n"Daۙn4?miF /C2%L\]%a0xg|S bCT CF\oj uz̸_ <,_[fZ@@ Z4"c<?W=nXۥ%͌*2yb% oުsX[d9sltPfW8>xL<(6&uN?)_ Hw]s[o#leesYh/|qptqT%]"m2.76˺B%i'-o -Fd\{@H"(xeijo|c^ؾn/UUQ˯uf60ʸHMH~vETPmɓvw\ S1{vùf[HG;||};'gÜ,]ܞ[RuC9svpfhbʝ9i]-lo 'mbYu\o4~2&Qq95[]EGALI/SS?:$vReVuc{ b>_3(2n_vqK(THJC*\QXLN4T!5-lctknYQx &._} endstream endobj 541 0 obj << /Length 1493 /Filter /FlateDecode >> stream xڭX[o6~ϯУ D,  t}P%V[-9Mw(2Mj<<Ð?R\(Ɛẘ-O𰻽)* "WӓB# )1UdrigAZ2~5]سߦA5SEӂpĸ^9";$JHZN')獕`ߒI#o.DF1m %hBQ/Rٙ#KUSĂLC7if\tfn5 80Vg BbW1I,H@H"FWϱ*Px\c"Ï`9.)'H!* n9'1#*>ҿXx(9/U501SH MCD4uqIxKm cH.+JRLabufRQ].گS16V\:OԷ@zwf[x-vnWfMHٻ뵿LgQ8 T4@$ -rM MФ\=@󶋏Ov]ׯ;MkgߝGN;v񾭚{\}[/P1KN߫Ά.SUi+]RT96 ' )0RĹL) 2JHʡy@Ja(/ %֑H_Ql eU9@+5*NB &q0.Uh2R (Ƒn@8*= Fל4*12HYDBàg(&ȱ,3 xB"k&`#cW.`O6_Ͷ[rJpg o]_֗ѽŃ@P ) >#>ˀ Wn?܂e D6BbF12ogV}άA͆dH_LᵽL}_jZnޯl e&YŞVIx,C ^^rfnhz)o2*׽=s"5DϩKҲsZdsQZqʤ4m%m S["_OA)Nuf.K,(rm&B%ýn%`^2dҮ "WJKȖ"7`!PR@1fj-4 _Vzv84v8VْlxٌsmV/F&g<шʃYtѬny:Gً#:0AX@eSZ4+ -BxOUvO $7Mڂ;u09lPo?wϿ ƪz$) [#)9M' D %~?} L?WfxvxD'BųgϾy췏bs^Bj!)ދ]> stream xڵZ[oܺ~ϯENЇ4u66;7RZ)dmf8o(/"OEuxƧe&ng3rOWizGaE!6ݬſ$ozwJ#q3 u硊SgWY8|\٦ n688i6u)f$*x$q_,r0љ A$ T cCơ`wǦp4{(.e+ǍJy8Rpr戨Eit_ EPq6Ck7ؙocao|F^]WB%њ售jE0E#Y0NcK$+ކ5]ֈڌ29#aQ2|2_ J<%s< uc?..7b7Ś[S޾6j~4} "eJn2}Y=. pS+"nuyyW4 T0wGpQ}zy<#? apD%8-H,=Vm7;QGSW-#QHE04>ڱ2  HjG;m{t"aqZhHY/,`HXv4NٶRۤj5 VeIY[d@]N|-3SsgPW@׷MzV-3C#W,<=$4CѡFceQK$T߆/U(L Enz,x|oF[|, ri+Rk/'>{b挖 Ot髎"S!LMa iSM!s"xA1_0K}܀x^qQPoR\ia, S/x?m %~NźkF!;n!z\pPOe px(3bALv'qg+fՉ\(oȲy3RNPz #a&,6Z'p/:,XД^ȫT_JmpW?ޔ USıF?ʩYWY4<, Qi<˵h-D)OkuK`06>ցğ=+ׯz=0Ԫc5H Y?zƇo RbX9&W H1u.͎ h)8Ez({ <8l\8l~J Ҕk4D|G56U N>U^ wP3:T(|elRKC`S텽'Ft2^|UYu)+z s'A4 B-WJ n¥pg#8JXWG+;j#L> stream xڵZYs6~փ%+$M9me˵q3jIo70boJĀ8_&=+LqNggn\Ϩo˨?/<1gPWg.>_g\Qlwn7w%c'[>ZfgT.$KZʅ$|YJx3o%WM'[\՛5lBث-ŢAy- ƴ9֔jqam2Ym\XoZZ\}u//Wucc7 -ojK( P X*s{p/Jݻu56]*V7ʷy#9+GB =7ZݬPC?ԷXfX[.PЮk/f M 2s''/ /xnWۻUF*#J:~,XQPMb Z AǢ,9غDj*Q?V'\T~']5x YBg?I[<&aLq`$7ʒ AVVzPKo&Edn&!u*$EĊzJDNDB+"~ru_SHm`F~@LbJI *ksF`ĒJ BeI#.fb;-)(MSMWYx3Ź!U-y۹p#Xw/m/~gvɶg)9R,Ǖ^b+!sVz)SY/^PAJC/ئ&x1u$I7]o;ko3"ꇪSg 1ŪCz$|pvG%#S>HyiN&q.D>7(N5tYI`ܔ?0 ԋ_RMEy~s{i{W xn?&"BP`ٽ܅ 4e~][#_CBZRvg- E3 W I'(A*#0ۅUD j,D.72*Ĥv8`/Cvkh:(FY  St~}liU_!IlKe4Ў3 (h-:ha|q([sjx閕: )5OAY3}g# ܐUd(Lakx.ky23wL4vfѯdF{C0ǔI:oT̅nfkUϣ0 O+;\=*'Q!Is)\vptI.'?82D-Cg*kؾrT8@p8p-YUDz8sD$* $ unt x=V>|qofR4 Q65BB 6S=qهؕ?w k, 0p# Kwm\2q^=:=,f&ф,TZ:$nB2!۬NHv&iT£SzO,Sx""TgRRځZvعj?[]k4BN֧z`G> YԵH>箾ٓ@љ2 fL[jbvˏpDA8/nE`4!~3US7}ѐaq!L߄_u|f<:C<1~ތ| `<ʫb[ȶa3 ,')NS _t06JWO#IQš qI IAy t*KM7&=c'FV F*h]oM){XaX\KG@W!> 7i7BnsqXM Cp{ă .')6Fx.?_O Ηi.JDX0k!YD?G\uz~] B_@02 oUm=1BT/C-2䄠0}b3k-í]'iދQRό?a)D`'R>3Y\iS>"7U_ M0uX>w?^"@@6`Ku. ceʃd,I7 9KYB)ȬCiԧ|:Yr D9ڬ4I;%'\@ 0ȨI07)>ɉdiǛu9=ҧB8݄'T㥫1|?򵭕 endstream endobj 551 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/home/moreno/src/queueing/doc/qn_closed_single.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 552 0 R /BBox [0 0 172 133] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 553 0 R >>/Font << /R8 554 0 R>> >> /Length 763 /Filter /FlateDecode >> stream x}UnT1 +!rP6, >`Ejqr$Fz''8jSw7oW}}Iap l6;u`R"oc_ZA,0R"CC\"vZ|tաEhKo)~Ko$՝wx'a2IY2WCYhwCHR-°ѱ dt=k@p>q)}4Kvc$Y loY =g82X,J kWI),s*SJ R(gؑUJ y#9l2ɖ'F׷ ȼs"|"TƁ3+&L\4 ٫A3yTϪbT۔T+!Z0qh`MV%g8YP.:;)q4aaMr=FN!'=xS1FLpM鿜H$y5:(lцrP#\3RJ K'~e8sG1EaQMlTqyq'&(-r&|#m*/}5~ 08L2@yL "Ƶm#3Ӫ|ԏ,s\?m|e5|TUT4\ebco endstream endobj 556 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1750 >> stream xT{PS$Z6*4BHvZfQa}"Au !$A@9Id <~vuVquY ٮ;춖N7sL/kgڿ97;# A{TB^R+2>$u"`$vaw~/+2W| ]#drSSZy*]!Wj(Ne|?RgE XK"K=. pïb5x"}F"L,'V'3›XA -p MC BpTZvka0 "h 2ZXk&ˏ7T[QǬb@ $瓝a{[8˜qCQK{`K@5aIojq l~կA ;~/s_ےMUZڲhnFLz*GoupB:NHhiiXR03N.Z17l꡹.˶ wuӶ0|5rNo `TU5|qUubG[C uq ?DPK~}@BV)22Rm]==gvG;-yQ8>71LҘ 7LXtY6{U= C@7Y/IYqVYyMӐ2nϥ?Z$!9:C\Awt kp`ЧJcp!Ă>`ZfI9Q(Udk4FϮG>h7%77=y}.>-e-ۚ!ޅ6PeU&J*tim#WG&]|-Gۜ]E߿8|b]L.5IP3Jg{ocX$}rY+V/+t23$P8ru{|ɮBC-s ~SK -{!97fe endstream endobj 559 0 obj << /Length 2776 /Filter /FlateDecode >> stream xZmoܸ_eD2 צH(yW*Jv׎}gHJ"ܗ\6KFp^-Gg&)ΉzXl?s7+@8(x7RhNLn.du}~\۪s3b.vU޻ uŜ tǛ^f\_2vHyZB Bp>xSSr|-ώD bHHٜ(wD4@E.WŞHDbAV>cjr YBveӵvmnmJkt]Lƥ6H!DI} el뇦^<`Bٖ]q,)Q0޵5@iwS^?X ѿW,F]/kv2}r)IZ/ "/` '"+`\Rqd0v!,dPnVXLngJY "ñ or MÞՑ'r@f]؋lx<3BS M3PÞJphTTL1?ϛY!!W>9(Ij OԉҡKXz(+闝.yy  [w#v׷? 鐵]X,Vunmc, \ Pb&,CSmBЛ}ujO-MƦtl/^cDv6'ՀЃ݌D>-jK4q%G8z9; TB}{]n+=$1#ƌ-0DKb ><5By.m$ٻufx[%M]_'m [WL Zjӷ26\{}rq4o0Ayv#-+4%kr1f?ɗ>W1ʍڡ蛑0 fh93uf~oR\*Rب"9-vY}Ř}8CzrgLw%-D5J7& n[k_ .GCOJfH&t؟4VWTj{8mrۅkCIip7]C=o`S;½H.=x"$CPD,d5kGAjʰ:AчON7PRdj񛯭+Oz<8 ]U0UG +:"rs&V8OC e]޶lR_SpQh'@NIas 9IQ1'D@I XU䔦ZJcJJ뾿 )׷2%cdBT!7M pV隅joF,bNgYYzn6Uj?G>.`X # }{^\' g,gSatoLp.aYPx[h FkSs.6A":3kI~BűaZ&30)J&1~ CJl\qip41(x L6o9*3u~:K hw PQA|˖f~$=ZM! endstream endobj 478 0 obj << /Type /ObjStm /N 100 /First 869 /Length 1928 /Filter /FlateDecode >> stream xZkoF_1 uQJmDB_U]7tm(,Va׾8Ν;^'!N/-`  Zam-Qfު'_@K6GdD{J(Р5Zl8n:e$1B4})!цrÆg.BEڍBFuB+` mkX0kW<#^5)60}"6lyAkvàz "m`;0߱[cq)< F w 'p'߉J<ά"A 1@ f \ڱ<8E 0/"aYEKļ'DQa4>2$p,X+PJ6nA<"BH" Cx&zLR8 a@+h7 gwGS95F`P3$(4aX0L~Ţ&l y?H # 15b<2 :`h$%aX`=ُ?,{-ի믇0LJRwq' [ "]?{90dHF^XPi{a9vD.7!Es Ṅ١ЃƀMIFqV'{Q#P\g3b Bu1΅Tq\(i!p$Kn}rlrrk]yrgtMEВsb[ώ moALqccN=qt^h0>G"6jf]uyHLӃ ==Icz`*qZzt);[3Tqzu}hNn] aC|=Zd0:tD,>^sRT/18ƦުqNTmq=tm'D^!̧ t1u*oZF8RhKcs.SЕ8L\f'}oSe|0i BPΫ*uHwb3E>xJ4F(q6Pb2PzL+Ȟ~{ŷ"ݎxz|̘RFUq0کԫ8*hliu;']#ӯ aBm䢦qQIW7g\ql7q8vB9>Oiˆ!,wv@SNȚ;Zדْ98'S|0TuVRmdd D`F_ ƒ{jN9$ûz7ӧeYrSELI|QxQWZj+qzTW_J_\A΋ ?ֿ,*_R닫TXT~q&wτy,:ы'/|y^Ϋ{׋V|;Atſ6!m~xB)JU}YJM$ΰ} N^D{}_"zYGHԙeՖoaf4 ñK*%mUK^epAśo\soI^\#!1:P"<+*F "~n:\Zwqvfgً~u7Eʪ묾yVYfv'UnExii&w]e1E2[oIX8/7+ڦmǺC]jmJM hFÝ5)LdR qY{ջ*.VV ocFQ&:?Pb*w,"W endstream endobj 565 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/home/moreno/src/queueing/doc/qn_open_single.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 566 0 R /BBox [0 0 198 144] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 567 0 R >>/Font << /R8 568 0 R/R10 569 0 R>> >> /Length 915 /Filter /FlateDecode >> stream x}Vˎ7 +t`hQO?rޝ 0ۇ~JݢZ3,=*EDuֵ,C~HGfݷ.5]$N. ˅+q>Dr-gm9 RPpP UT#%{ )A|6C;$VGiRV9R(ilXC_k]s 2O.#wqBVM]Ʌ- !B"9 \J6 Q I$VD_Vkֵ_"g8$h|E4&Wa\X1r+;:g١V*3SHj&@.M8v;2kTN=kmRAUFc84lEmDa[om3/꨸T7֌2pQdXeOE,޽~]c =S!f3n* endstream endobj 574 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1823 >> stream x{PWƿ$w֥QR4aX] +* ]D ! &K A+A@@WRT]zNg]mgߏ9~ԝ{;999KSB?i \4FHVBhnP#Eԟ/lZ:m.Xgv%鵻k%FOdkBWXzdvB#4eNVȕ=ZuO׆ӴY9j_}fGDnUGgf_boVS"j1&GvR(j 5KRA/y^JHzo_ B0.GE@iA+1])e8ؐXyvǽ[?D,C z1["+aI}s B;GJ2T;Qt*qO|S~@s?S3=~;KBw^oSN b0hpq Ő8κ\gy+i <ܱ8#YVٍ.c%,f5P')j6y-aA_Ka[,؂JMخ'dc6q$)S5gJ#'awUj\ckAK{[7+s{ej0vI_g+Zz኏~13O-[^7 w wdl 6{Dy ^X™ha|_߽#&<枵.׹YzE]Yp$>ؚ}dW@puܩڍIw;i*rlF3l~Oo]{=B bENNtNGg[m 2ct`Nn޼8/VNXL~7s]% 0}~lo0%/-;!~]=$fm׮dĽ ws\ &8Rx$Z74=x+Zk*ݚ*U~w1ɶ˲K}jSלWsȭK}xaȲ$}fT2֕캁GvsN6 ǍN `r*{݆\E%Dm؎mKBIAԫ{hMf4U`2rCGۇeMx:x%i jBZ@=.r(߸> endstream endobj 575 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 313 >> stream xcd`ab`dddM1~H3a!]c VYyy0t0w~M軟wo ,*)YA i%E: E% F I @ļĢ] uDIMJId```{ߏu-$p9IGVѽ{iѬIeS&_v") a᪒gQ^ޝ]8z]Җ% JtvvMn]5mawC{+-KΎh[խ0csyx20Jd endstream endobj 578 0 obj << /Length 1222 /Filter /FlateDecode >> stream xڭW[o6~У ,ZX&CoAX-ܬ~<-Z%@H~Ma _4Ʉ 4j?A'8E9({oW7J%,YnS*D,+A`zy@qB$^G(m$aB_puW06M"sN(U{'Q d"!"ܔNBTz:RW5J+NIyB> ΡX`ѵ#&L?ӞШ5|(?QH^ $j?Di"q:KêcǀB>x4c? .Qܹ>Qϙ L1D-E6U\laq3(< ;f$SKşQk!D0) ,4ޕ S+QLy*כ T*>TSyt$cwǗj?;8mͅΈ'v^vGnΆ.`rPз9^9cUX$\ F)1DhFr!PW"H ?Lx,A15<Jǚ,cǸDeNt '^eGsJgdBwY'Npy9Zdh#2ķҕm-k7H5v!16+w9!?6*.㙘1DsOepMb 7 (n!X) {A2Ig'}y4㼏krq.twmrEd܇$'9h;di?M搮bNA&bj̡C2/ǿX, endstream endobj 585 0 obj << /Length 1841 /Filter /FlateDecode >> stream xko6{~?@̊OI-ڡХ/m?(6]TGҖ<0Dx|,*gf38ey3"-l9%\'/UoBJR:y{[՟s'_~ ,O\~rB3F,P9 |z/f6go!d㩂S5Sg*HWէCk|Lx )xPUKttڕ]GfC~=خ:Lfe?`Ѐ8AOr5\(-Fd*ˈ~1鶍gGi9@7z>E=:o^3*Yn=jy#֕{- qq8ê'-f:q3o)Mδy@yqĞPf"Rh2S< Cs` vאJՇKzeQjk.z[R)P>OvΓrO`Ȓx9)òmkJd6{Z5֖6kMt݃T BvXR[c2r^b0?BP}Iis&7.#ζʳjW;WMMIS'/.99хP̤ЋA3ijdU"!';;P2& $"m.jWtZr">RdEj%zo˺ضkgC 0Ҳn܍\PY^2Ug|]j;Ya1G ;2Zd_mΫ$fN4J)2h'BŬ`a@d㋔ #͙ ,x |y-$24,-ɺ`9=gd^8޳,?QCH#ej3CqnM)A+F5 WA}Jw)u(Hd"{(Lw]q HM޷?1aD;H~_ 6Q!pu/R@.ol Ku*'S_PF>C=q΅?o87Ǝ0FPC>5h??J/PDN:nnF3CBPl(k BʩxJxSD&Ou۳/=@V endstream endobj 589 0 obj << /Length 2605 /Filter /FlateDecode >> stream xZmsܶ_qy%^vݙX'#N:?PwĊ"%'[]p:IQ~hFAp,v}xxh"(E%ՋH8yq! o/z!I<瀑H Rt*[eyy8Ą9D ilƚ,{ΕALQ/}S*y|zby`x6,'{Kb 0'GRh$AkW\db#,Pdt@%Q>`6l}Q)FR}3a0~/-?;!]cǡ FWۑ["%!L%TTn j,q]BwJ2(N[qnmJW+Eڟh' ]q=~i}b1Dq 89&?BȇN!_ X%rSV]Á䍻qIGyo^.S;tQ!uB|Bvkb$oWs0k*8q4' pW 2Ck.`ȷL7 ]](MEftެ894slV5o/,`y3>X9qR j 8?:Cy6x0dʅwuq:mtoլGc;H,촥vJ5Z's5i7gwI,sVEUjF/Dy#ƍ Gq@s$X=J㖦sP? Qc_iumöueA̢)R&4pO OݻO= RGyWENz_ɑ%O':&Qc]4ZG ʐ0|yi8>p|ۿ7k%.""鰞\Te{3{W1mD9!j#A]6VZ 'P1Ka}wJh ¸ \Ij{e 0FWEnRV4[.81; 6dx,cj`n*17k[Ha5:;_imnzsx)&Ș S_>ؓ5$z'Ng2GvnقrsgYtSSrg&6 "$aO t~H]p}RA&"c~s0=G{)Ўu2E[1P"p#.6&HRr!$br-/zi=EgP:^S:#"H_AzA)y^ zw~Е^ɥWەŏLykpb )KNϓ)qkݙ6vL=YU7.NH~':t|()} |,0k E]/W?Nl)-1QFdUM.q])(f S{݋ӣLقќѾ8W_6T f 4Bd8}To0΃ԏɚTFi^6/!PU bX !JK]CcNcH(U O' Ryֿu/c=% T~΋N)c)0 =wbh1o=6ߔyS.ɖ{C)bQ endstream endobj 594 0 obj << /Length 2761 /Filter /FlateDecode >> stream xkoܸ{~"O|4|i|H{I1KBޕmZ#i_R2&p.%GgY2K9'гQbF˙m:cG?J9 ɒN/|TU~^9{2z.EY_їEt v/f"Ku$ӿ?zv:/JBJi"`V̔ra=XXb@ev嫠 =Utd"ҏtY {2O# L;7dqBi!D]F CCq BM#08[\8Mq/9xH&Vy[l#~r2^l -6xx~^ϛ#U.Ή:vvqcq` \$u^"W|t6zJJ>n#Q; yH<_Ԟ-p{ C }vv;B r NHY<#:KF;)'Po7yQ_Lk Sa ߉mgN14(>XˀdmnR.,9I@&K?F{k4%4L-[8\n`;|Q иj` umن2mԞg{jZ]Zaw!6% >lj[]߸:Qb,H,:D\O0A3>:v^؁'Gx^K`KƲh\JҞY7ĞO>{-`, ݢ/9UcK<պP7nb,P2-do/+pSE(,EpTJ@ Bzu리:aIgBt.ephAUHI=hY5,_ؓ\=:X,J8/{ZDHKRe^.`+`4˦XKrdIly:F)91w"xTC4DQ)Rve,J6rj{:J,eUWuy)@}sʌ+maAuqS輺+ e <}q4 ,^ $>*ڑ4i`y~^V所PӓMjH>csK #6n֕30\C꟩aXjLbeɔAqt,)쇨fb8G2Sd4eђIFq};A#&Fj+aOXܚ%DS;yھ?Y )uS!JubzL)߸Y?6q >Ǩbp0.8;US=Hr-@ҦR@AE Rb*W~KH+Cm%p>_n=mcÚ^P`0A{]pļg z`SF_{Pzcٖ{5S1KMFlzSK=9UDk/߷Ū߳ҺOeE>ߝn4y5v 4ʧW< =,Wb!D"Tt'[c7a!"̩}ԩw i5[`dWÿ% 4=8I sTC%Uޘ'+_%.W9:*Sߧd[ce$ʺD2%㠉‡dw զ!C&p[xs~R.p27Rw;g̅>Oeۿg$|osPf;Kc;).`;㶇8b+8*cLJ *&48#zvG&\YWr[uB4Ȫn\[]!nU9"V\=Aq~4`Ƕ5*域pmwRiyju\(6G RWVV 'U2f |vZ坊q/$MbR1J\ĖI=פީnv> $IQŊ%[,AzF2)Nj _߈͈R͟!{Cȃt endstream endobj 599 0 obj << /Length 2804 /Filter /FlateDecode >> stream xڽYmS8_1}1{XXR{Ubs]G奮><6=r[- 0ڤ RO?Yb!X*|,0͌g/q+烠?|ql'f<`iXbޓrūHR)h1WzǞ_0r%(h)Q8^ #&gQ"}’bqw+p+9\DN4ov}!j+LS'޶U>;9"<`:h8pQUN 'f~p me]an7k\5H66*27& I=6m?$G$H=4\N=|[W[p;0$0!]=H9VsJF<-ݧ-|"ܘ +WNj;[o|3D Ÿ\[)-sSӬyv 0EٴZdA01˭|Ӓg)xMEsgyЊ` 8,,߀2t+'!De0zj}{%'';ҝd=gvT9!)Ϲ&Q>>"z9u:-ZTpWL]w՛ BJ|:oGuK\_3}.TxL0&y2$r|Y5a8nr0U9(CɯIx/6^ṞF )w##Cm5!}]}>E溋h cU1:lzq|:Fo$It7 M|U ! a 6찡R4C8/Bج z[nc }!/^VZmc'#P}r9-+naiKwWVx^_K{u^,u>ϊ$Wx s Rq$MMt.2^53QoumTF ȍ*ca74?p e+OԴy rxV{UK4<90PRw[QpCUop*ާ\E^aֻ.+4pkU]XBcWYs$T N+{.z@':r0+*}4n;TCSnd؂&Fj7 B9BTWK<;W jtFةwH&Gv6fI kh+b8j7svQL',j ;V={9a莁w6s6}2JƤ='cBTOU9H$2ޫjUSA F"4Q *$Q^]}? yv{K .V?p09WꉟeH ;~#*4QΥڇy1||EkcOm/e%}RWDx>j|2PPD[C'A%P,5RxhW`_f^6"Ȑ.{`U8#㨿xb$"x. z!L !a8D_= ݑ|im8dڴ8E?7kCh7 ;W"GZ|c+ښ]ޔ#m*(pi5h]޿^6m-J0\"rzM 5o:J`T^b{zڳ5'okŚ-3ur];Xs`4o[;+kF၁ }/ʝMڷu|T~Л'< endstream endobj 604 0 obj << /Length 2691 /Filter /FlateDecode >> stream xZmo8_X@>,_E~f^wnۢPm:Ŗ\In{fHJ:vݗE"Cp^(h!H*Łk><=ʟ=x$);8YO~.ecX*z2+iF<⿲Gc.SDR>r_qBJJP$MAH„t]VySEl0}# јAotc#^EW]?;^mvnv:;~ly*ZH+ŘٽWAѹ$XC_E7tVV8 03Abהb%z%O=kߎD ~Z$\vBæugwMHZu l Qy6fyyf.33 v }qb2_RX]"l2qͿ9&$ʛ˅|c'6CMܴY];hA y'G,j.v9IE'A7SْԦ۔8ILJ%:,ab \ u:X4uyMS5b8a\sknM05A$˼vuzDoOѓCP>y_¬gXF|GQNBRLavfޯKY̿?t\eqcC]^M1 ҙ!&q"Wwfsi\R,zT:!dR;;ee'I!HRh$ ً8$f,ILYV&jf 6bɈc!A_906T굻⨃Z܃aWDRWaCJS$¬"ܧ]=5ذM]qa𛛅fE>3ha pPVgњ,k~3PDXvn.?9>=~qn01Bj%:x `*]-itjUQ}gd|ދ Ezq9P1ޥ (#;xk>\,E;@6E*~{ 8@X&,\rmh<'H!sБNӈk,U4~J#!LR[Cfj!v#|30dh3:ϒ#U.m;[19i<9& RVLCEh4I6/Jro?5Իޒ7w)S%[܏+LM=roS_4O{;õE++CP$-G7zbBCՓUU;Aۈ2O }v8:ɪ+;\N+yXS T>ߩ1v7jׯ$S+bMMx"L7*W_txi1{B8!g:t{t&Z1/(нi-6_n9ߖS@W)6f|> stream x[oo8ϧؗYqc;PptD)t6"%Y7N-R/8؞xl X^S<-x yg80+h2aBLf|?"pXG櫍!ibkɪZr< cCezHp8欼XE{܃uHo9zYV׺ie8g<"$huˢQ>0r%>m7"hWW]m2}Vvi^qACwz ,A40? L 1cq뇳\?;%:\]E^fr$ךBRsb(ĩu/Sّ8~Tk.EtGb-v;- ӖZJEUjչcaQ-r9~7#Hґ Ń EP^Wd8 (r8 8zi <.,:R1x{\/e45)͇+Fl-*}m/sV=03xbc(aDPz>fH~1$.Pq - up-`uC ^fҳٮ )U/G;|MlJMq<ɚ̑H@ؠ^JNCw%oRN!Xf>$E_B) r hγ;!8j$ ^kހYײ=J4!p8'1 g dFX$(J)2iH![JR4mh{R\:!Eb81B!Dl(@4]gXhU_w|Mɐۻ=lL##h̞$v`-MSGZwXM~Lc]ydتo R׽7U-ocC|5] U!U^HO"Gxҭ8x5W#IlW=:/m'D 矓Y^L@^@~6@]}q]|eoR4f2Jq7 ;|ک>?ޔc7:\DI[x);{[YnwC@\'Y#O!1kN.+ywURj|FZМ`ԽU Z((k Z?)=RW㬨yYA;jWɔ>|Tiφ0KCf0<[L [ Ts{.b6u8J 6U_=jU#]oI==l^x(;VoP;_U_SS|^wP %6dn/oQWD!xe_1 endstream endobj 619 0 obj << /Length 3403 /Filter /FlateDecode >> stream xZs6BOt/2tM4}NvnXXKCRqҿvӐ%7x$o, gFJx hu1OqG7۳{OhC :[VUUGs)e=8+/6ˋ }5G"_Y]Gsvýg#!d)opŐSct~Vt30 /wGF)=˪"õw$u4֔t}p3,2;ԲK Q2\h$ń-N;՘)|q-UDXKY4D7S^5 H5Hޮ>.bVE"<,M%7f"ou X봺Q{GX94+Zj X! jќ%q!l#UdFfb>_^:;)/WwqVV*#P/lLAx=9kq)! GF H"ThVfڶdPd{fHުU SZMZn"!B9Z:`xH=e-f wW٫cɧRrxR+@$"+@ydE7}4fٖN6tڷn;ɾ>\_&ӜǢX?,4L Ӕ6UV_Q+j[Ao읱 aNI?dzœb@0_T>C9i˝@1dI!cp2h=M4*Kﵱc)^˜k_V|l/ަj*TٻmV۶* ]k /vګkFr 3gQ]YC<(%L3S;Zn)SpzHYN(aX*ͮ45n)wN㶶P1(]G$§bb$/fۣl'ןәnRR0c=; I_r5^ F-;s㐅}x|;P'= Mqf2)ii"򴈼f] Ӕ˖`f`bxIAB,}"Zܳ3> P3,8SZ,7u:NJf & @פg$ۺ_\]U?䛴qru`l*r!Cެ88F1Ci1S9u]>v@)MX6 5Ld$[DE %l}XՒxLxn}I7TV9IP7$JĀA e.m{tu֎ 3۶}&` 5 &yL۬?zTJmLI{h$BYR"}ڇu_=H,S/Zs˩[ xϙfo6{@EŴh}f0s^~01;N1Rceh SBXKol /!ijkK [ֳ{/ܙ1l'bfbM}1Ej_Hi$M$x9&G$e Xgyi/`ap^Lx"FpIƦ_>ۻifLid}Ve.f<l0tb/ , 2  ii鞜 } 8R% "=C FIi`#M V뵷 N` |OY\ H\Vb#f0 #׶rrNv |=N!1ք[D #ل~O#qi[H3z\O)L(*YĴbGke"YڿN^4XMc0l`9Т,_>̡l?u0p$xDf I˻[߉ zM "LTuq3MGWڃ{EQWqL`[`02;V'Ul+3s=h<YZSʢ)+~ķ^OhFɧ7ScbUQ(6nb,x%}6ԕGxQ-TnZؒvKf78I{*r a}T[8!tĮĞ(NEbRsy"# endstream endobj 625 0 obj << /Length 2679 /Filter /FlateDecode >> stream xZ[s8~Wѽ͒`*`XLp{vf`#ר djad\sdzÏ@qNսn\{ϛ`{Iy@cbbCNφK.>DB>x!ZXdM8v@2vCJp~R-mTY5s#:VEt9c:z[KJfs"sSv״ץZ˪NK|=i43W܂FK^o6MEx؞v"LfSNt䯲jG3|(wtd0P8EyKMg@;6=\'6:_en\j,4`u2d5 &D%ꪌ$1m!_mlQPr/u81@Zy}X#'o5N #LNE]Xo. /1:^XV@kSF9آLj6^b[Tk;iUhk:3Y[J/N.=ChtVmjMhǮ2f ZY ZEu/r "U~ʶq'a`8p Kg3 Vľ,/|)1R2+v/nR†PxZgvah ʈ6ov-bwX^|d=fC1Q3Ktza3cH;ɮ5.thC.JI K f[SC 'L/_-2f#ļfQ1A@¢$ghQU^\*[QcjcL1ʑGB1"Xb@f-4Hk"DBqt,kQ Cj^۠jq hCPe *+GJ9%%m*; :#,nw{9 @-ɆhL lA]19HS"t2ťa`S,]\lź}3A/~{zқh?Ԅ$NL7+ԎO>')צUr4~$&DM4QZO=ሇ(yA .K10$ۜ N$j! 6y+{mVZu$KXu !̊ E(9D!43aȹ1h:d0dCʃ%t"ww)˼ʽ/MW @1]qb̸KDf|$3μ܍Ȭnj% KЅiI3>HgA 2ZoAvpy9ׄdbv^"oض ߾Nv)q?Yba.ńQKw{5У fޘ:f).Cc}+NZ+_8x" NcECX3Mhjp .Bތ=Wv6wy\p]gvH%&5]׹K `> Wt=˦ Ky W(:X`m} Fx_Hf a]7$]\EZ]h`x2&kv` l*l& 2cP؄e@Mb %lNo9:~ztJ%51B_ld$s1y|A,!kkVw-a !|q[|`㩿QaqgVjlE-jS2ɠ$b3$4%dvx3Kk-C1zkYQ˜fCw6ON XFq'f Qdɝ gb@.T*b7M`z໦颮b}0>#IAPzv.z:'bEK$ip oCltI0)a=L0RME AYtj=$7IC~;.#:lڡ =Y T tF'ďo~^fnefZ*h䧜osg#> stream xڵZ{o8Cm׽lۤElPm%Ŗ]IN7CROSˢhHQp^qh: DsNbM'-n&01œ篥АaL']RmbpΧ,BNom7v,f,~?⮜L:xvu'\4%cG 3w%IU$Jo ᢨ:bPEx#X%ϤֹJr\Pe)ޣcBQ 7^S#Mm.ǧպl+E,4Y|@զXIdˬ4LC*-5XNxf\[/5WIY.7R.*+;ZV߲֧0jFaoGY3%w"N$_KF*)EuUIxa4jVg]B,gӍ$aujA`OKL5p"ef#Z!{"ZΧTw5{:RvT}3jLu QHmJAC@XS'p0á5hА(n|3X<2?Է603b&3>xDD$F珊P +HRa I9-yj-`ZO1Q] 6x 7Nm8#,6RFy:=##l@3 OKL-Ƃ )&ȆDŽGxtX&3J#ѐ@s/-rVvd(CcqH(<~}mp$b6& !˫pw t\M%-?yoc 6=H("Rlpwa "| (@~:j^:ňG.J&X(㺙z_h>;\hz֫9`l#E#w =Z6џyX1iʺ$L/z| )BluI%-Mxk]Lrܮ9*m.UM_?S8]vĴV>Rnaܑ~Nb fch\~o?m>U|^D9;k?֭*|w᛾Xؚk,S,Sg(2W 5_4{mr-3])m9SOs6oO n"J}= 6j ?57]ϝpgھxOaVL-.'ͳ/Z>"˫kw`֡ <]tO^Arvw2#i@ypn'+V/<Ჵgqtgmz!:+dE:J"vXQGDW<*dZǾ+ᯫu$E:OK{6no5G!VN:#?cϛ"-݉(u8`Īr{*AݼK"U3%bKwꞩtȃ.IJ^">sW'o^g=EjX.lekv"L7>28Q䉏ed" NbYkÞ;a}I%uaFѦ44>ӣ1aQ|ΛhY/ubfy.ve NYC1ֶ32?w5Xپގ\sME2r,E%|Y]wd76^h6n>;npW#leŌ>WI^reƓr[ث:5t:A"u_,կFu/CG'v`[ڻfχECE:w_L%E:r]2j_@O,j[m:t*X57MXQR7K O~Y7+ n_Ǻzl` Y7U l]$}yDf+m@qRp%׳w/}*EMQo(IMTؔRζ+vW/}BmkE5-C*[1JUԽx9;hkK>f2`oN1fnJMy:lzu1 {]Ƨ)˰&M:67v k$[p-VûAN]C E[p[q7^j2&|w KU`0ǂCO_-?uYc(Jt^)/2)3eH(AyBPL#%&LEN4f1VQH̠(;34ޟk8^ѧq>+ s >YZ9M*cYwyMw?O+[ҁp`x!Kaq!hj7Y'ta\HwnqfSk ~ccnlh f-#NA;[T$XpA?^(9||Lǜu3>8s=Tܤ5 +1 'Zǁt T{'^v endstream endobj 638 0 obj << /Length 2806 /Filter /FlateDecode >> stream xZmo6_NyiE)K ;׹kYK{hWM J2R+3 g!4i)Y%|$._Sgh.el}ƿGs;2n6G<r4mCņ~scolM"r) 3fdh"Lٜ@+oy8NE*zp)Uo/mN2x;/\T:+?PWQզi3%1!DV5rc"ޱ>Pο}aJpૺ6͝jlHضAK&h*Ȉy”ND #MREC6AںsLp +N݌<& ^iR4}SWkTrfn.Ϟ]]-Vy Xp3`ªKS D< 9ʺ?L6ǎC:Z,eQ;ZpZ-f% =s*khvXk.Lk~ի Wۥ)F`IGRmUtuHoS(L8{L_%`< `:0w'MZN?̯.RE$ΘǮC&TU==9YVym0ܞMkՉHԉ8F/AJ{wďl}rhsvXM.CJ:#"/&71fO^m %?C8O[YbpzB%Sј.G.7w?89S  Pl0"<:IP!K˜'HقeU l lbN|`J>fZY!.N="G={ I.0 4]tN⸝WuXsn㮝,6 p^=7>Hlt/}L@k]f N0i)$/`$*+6SWSHx)ppgY bXF/"-d \AF[ ]r4q1U%vo`ɭ>-wM@\zj΄q!>U,'IYS , 1ͩAJb[)K+\#D4ƱJm9 yf(IÆn 4Cn*[Η.4PKUgC>WEiB|WM 7JCW {R~ێdd;~D\wWD P*NN\1]sv1h+Iw0#n,LDiU^/ұ!@{YPꋽ .{׈:47 am3@. %Vȹ~qH'į]={-ï/ 1n&m!  5H4`_Ctcj I+>p x|1U\kB 酡8ENl:j endstream endobj 645 0 obj << /Length 3266 /Filter /FlateDecode >> stream xkoF{~>@>LZ9 @KĚ"J%Q pH.5gq83RXb,tjF7=ooxE38~v9%\'&.R zy1W* ~ܥ4+V46m. >OY=sbc_vgWO$!(bH)ٙq؟qBXEXįa>GY#[EZpV!LE}B3-Dj5Ú!v'%dF}n_izV3UȈ i>ųat%/rgzΗWWpriGAF|[}W ivE~0r2{e%ո\q{<`⮱4:/m C.W7QHqWxZ}:~sOF$b(y74pw7zՋlgE w!ؽz`;V; [xxHZM+ ZAE EIcG imrp:Nƌ 3^rW;7G<#5M@y:h8$4qݛv+M20w焹Jiw f9PJy2郎 i@9ϥC: &-W+>6t)>d[8F.jXS9}Ԃ˞SM*.i NY;鏘}noMa^3L!1ιJp#=6r`l rz"PpєQQ N]v%bpS Nz<, P!yx{ߵ=ːLjK{!" `wc$(IPc =lzBh YGXHOxf7|hOnv{K]xl(2b,N 6n:5%X/<0aƩ s0r.$nz%e+ĞlMZDaK}WbPqv v!ERFI+]ۀI]x8 űmس哷5BڿgkS)Ä98r?~[4(0^{ؤ;gc\2L z4>v.~hOj & endstream endobj 651 0 obj << /Length 2978 /Filter /FlateDecode >> stream xڽZY۸~Gb! 7{J>X'"O7@ljF$F ^JsN0Wܵn?]xBC9tz_^|u%l?h ]Ym>'/n $cgJ=DQl, +e\y D3Ik.$E뢸/U;c&}6FgGUYSnT7. vi˭RHH~ϩiaU.n=)TVmݲl9<[5rfiN9%Z T)q98EeXLqmL'M5fl!p3-=tT7V1O ^IN7`27IPvYVOγv[lP|VAm:M{i6{k WJɣ }C'\PK&91 DZvkX ';_{L3SFspQ{Y2{U0KRO 9 NG]L{2~#@~P mxk”Q+!uhԠj؁u2J0K񐱬^Wm[.Ȋ7>7}mxR4n].7-7- {UW5AA`;]8xAr;=N|Ւ {FG1`[&A+1lA߼y.<ԾG(GgDHqt͖(ه] B:XBTהycg[6lljAs<{fDE=Gn->ژә``f]k\m|Mkudr^Dru~xzXvÃ@[_/֧" 4jZyx_,;(5Q1ֻOeprCr~'ShWo^K I *a[-P;Xmnue&h:bXKCCSuJ8̒rbj.DNIsP'A0\5!%SRи(>|>KHP!O|Db*, >bH_g`!Sa,鈠ШO *B$+0yg :X3#Fl fS]4YjSKxmM 4uUmbz`h˵ۄpأCtӦ4utƣl0Ok,F?lvRA0bUIl.^VmuUiKBej17Eb[d0]_z]k7q@L_yDsǵ%nC#q&×= %R"ȱ|"?l.C+axѱ9c{oL`J2t0ڛncfI06w VD:iĠ C:: h J9 $]6qf oL5H#rm y]Sn6\*TC|Rrޓg${śs6C#qVRl՗T@|?z!%-J,il &ubeh0Nnu̽%\`:v~$h'_^d5pR7.lqtQ3|R Dac]W/iT 6Nh%#Dͨ5G\W &;$bs&8bIe}f(Nj4/Ӟi8.ҸjXx{BsY4ji6Fo?(xc/+6 _Xp=찼p)Ar.So?*D<c "q%*f;vmƷ.o =]G#_ bdZV91+Tm2"iF7[_Sӝ@Ů|z6nY -UOL}dJJXp}=cN^  G/-1z (t?ΓCK?:́Ǖcb:]\6O21ҟO^quBё5w&kp` *\zdÔD'_D s2Q*LIm\zA-2p@kP̕` E"|Ob 6> stream x[ێܸ}Ẉqsŋxd$FI2XCOfZvOkRT"Qj<$00RKTX<:UE/}yxۧ w_Qn WQ?]?UQ\МЋX-+yV\ QdcYӿ%S5+&Y/ٟ *-O5U#Mr4k 9~lm:|JS5jɵ 56QD@+J$Wk74XZOmnzwڔ_M?D)h0mBC ư-nPGfnp+Dd28e6&]z5?4 QdU:-T[smAk ړZ\gwƋ_ZdmW͇mnOEx؄֍M^)sT*@yަ࠴)QCȇۀh"βP\0ffvuB g\]Ӯ\ ~d*;ڪdQXsݛ++bMN79IR`%G+j#$7"jw:C4L1U'f&>޻+fvTm f ~ww?aTDp$MRBcF RX,OfnbOv[eHypYl &?BmocJ Wt#ZѕHxxN: uP៉ r?&I""O]tἪD7LYpqCUqXVYfVh庣..z_W&邳+5a ^©Gv* vI{;z\l.7Ous8D ht~Ĺ : ̆hG?c̊ǰ:w؁( #bag$X~ %|pś>k`Ih|h/imwLd?Vn}}׾َ )uYfmC \60lfZuݖBlzBnte4Υy^]|m? h^b۸;9wePCԒAg P>u.%FF` ߆Ӵ. 7ֱCP/ߏWN`1@b^S~v|AC-;*V!!D99 :ߝO QZT绮T*$JKs}E}ňpgˠ5C\" bO!!` 0t.2؞_b:u tOYT '[.#7n/7YvHoOa6߂AbxcVꙆ%`n"֒1T㑯LorV,J6jP1 ;[h`rWXtW4] si7/&̀sܠ6VhQSw8 7&a6RiI ]TR>@coa1? >>'㸛; &RC`-'ҧ> stream xZs۸_Gj_̽{޹4L[L$GRIwIKg,r .~tx8'ZEl^ -`WRhLtlyZER/>&P=?/ $c'J#EPtP.켯~~YJ?FђہvL1(%;quQ\]H k*}*obS4sFOW"jYW<,aډɇk$ M i7"]׍ey]pڵ>n&syXY^Y;|ɫ8,ZQ$aV5[p('jp5%> !4{J투3|J"%qҾTOBrMU.s!>lJ|w$9L9tF.-_ Qyo'HnUxU*ϫ|Bu5E Ӄ10w vPBD z1_}UBC"I"d'KGObT aairyGX5$UDIHc-)Is6':!1-43=" 3OE]w <=1*dZ1R%1UP1;4=mƋxjrS07 *v@*r֓}^N(f:x%1pDæ%h[h.0n[2yʸn˪b ?]`&w H2~{<݉,8-oQeWd 0 "ꮐtyuj2\._`7Lͣ囬h1R9ޯnlؼ\ +ǞkXZua>S7~+|M7=uoLi0~niGC+gGͺpm"Y*]wZ~8 7+(]Ņ՘*[wO w O> stream xڽZms6_OE{;7iӻIt:vnHBRq_4s!,}vr9IXr}2_?KLm}wb_|v3h8ͳB$N܎Y].Mק3X$.Ng6EygkUtFyt$o7?{~ӏ/(=rL%ϔyLaErNĊ*մ5C2SETz$4&&3ZTS/om:V | nppIl-{C\4jժMs8x}V5g@خEջ]*x_"SXoڷ>SwC+=W\z[#),6 $%u=T^jZ'Emѳ1瀘zmv$*@Ì~ bX ƀ@o 8]gI!^T0$nN7rP[4vwa3*(ԯ+B2ZV8' /؊a2+|1Cj([ l׶0QGthK[e& .&zdpaKێ\Xf`px84`w,"mS9H?S&<\֩S ,dm>{`A!56 R O>LR:@tnhYOn1},U|x$ESƙƩLAN4/TLr2BۡQwUV>P–#c`!S >yptzGzF22F7m]nQMP%d|y<_C(zX|{uH ϓ~Y+$&J}J| 1KQ$ > POTRNDfZDI0޶@.= I0o4}Lm\+Am/0"f2zym}k6LnX ^_&6LݰD ;1@T(f#е@sڼx!+Q0 #5>΂ O_Co?!q3Q8(7_ M2ix""/b|δ@9JQ8Vo}7#|$Kjm$O(^ ѐcjlד;ןB;Wן_.j{l{H%>!O(ߎ\x:r|XC.b_nK,mޜ7iekWU-rVm9VN}qDW]U2l񔇳`8~0ό{8F^u-+0u[Q)Y̚N'uh<\II&D<쬧#G[PX e ׺ (TEѿ?lp g^1ղ -}Vߺ]ϫ-ev ְ_yYvvito6?/>vxۯfтe#S, Cdy~2z=Qfƀ~X݋İY:ð !ѦkUuA$/]j7+(;lwO9 #]:lk`{sd-}A_؀9 Õ`]fsYG]:G:ТDV*]Cȯ0 {cхՋ@\?cL$B'_,?Z,:+V X)028sQ"܅ o!Ԃ%Dt<ƤMܾ&󅲻`2\9=K <pumOL,C"sZΰѥ"Uti{|e+/ f)}|>Ү ـ`I/"XPX[La#:ʁ;1̂4^cg߷UqĮNIEBP Yq$: S.c<:eDH$e$ڋUBc,`&􇃈AUZC^M&ouϻXʞ13tl$&:IOh!rJZHc= endstream endobj 673 0 obj << /Length 2898 /Filter /FlateDecode >> stream xڽZ[oF~ϯ# c}&Av&ƛN@jD$J%Na33Hjd`ãs΅ хsbY,72Z-ͻ@a:ͳR.hFlfxC"?Xb]ꗮ芲w.o$cO)XQb eh!B'Q^vaULyZ@Af=@-GI"eD(~rZAz=l1ᖈL,ђy7G80|R65&3)#{>6J&Li9#^Wg6ٶEoΘI9gKo¹S3G&TRE*6u9G*F*WU?UVD^Bb Pmoo,p2n6rdp|= ,6GᴫX(LO{&%QchB`aH9.'9! D&B"}+x ;-iٯ4'GS8 1A7&ok \z(MF.Avm* lv޸yo|Ň.vu3$@|dm'AeK)m^_}ss,$&Ct^)4xmbϡ'@wk:ϣ4AY•ػ/1[P6xnd($Q=)q" 2z$BE2#OŘB|}|dqM9v ''Xt ̠$ybX춻?(3Rdd/J[?)JPAP}y\ ='wʯAI[,:J bDl*D/+5|C&j _ogƔKz3QNk0*:C^xh:(DC;0hN;i98RӁ)D--3#s<#fzκ&pX4ɧZc!K|0JHb"ӰPQ=u._^:b 9-\AnN'0AfuHߠ{W&c/7u)s }5K]^XdW>mɏ'<|SD 7`6rhKח|Rq:iۭVq^N(bÉ,5N3NE//0Ybq 4*ꖾ&5+΄3! E'ld@(NLC ơw@#*jh;hqqA# ad f.fcdD Iicş|7&T{EWEPȬZ]pYF,Ur[Cjf咱1[ Iҭ{Y\,ʰMƁ[Ŕc4Qdɉ/%_S<\,{?7j<|e7qf2/zz_~aC3 AˣVr/]1xnP v?dk~ 7.VoT2Έ_틈JqD }&,cվ&`X hc;z)6ˏW &tq!v.}}OLZR@Xָrv[+zQL TԬ_> (gìnp? /}(DNA">asP^>6 yJ5Y?LȠmͫ' !čf i_t!Ǩ#b@kX{4?IHӨ>u4l-V7zubg2>\y/9 +TSVNGlSEC2upt #Mn1BHv]Ѕ.~/Do|= )Ǿ6l*8/A) 0N`ύ[|3Dg㱿c'kiCP|2,? p2怔-6*ʛ~ݶ8cGT)VB|O$G?@A/5q?ƺ endstream endobj 681 0 obj << /Length 2661 /Filter /FlateDecode >> stream xko8{?@)J]䀽\bM^?*[$ܟz9t60`Qhf8/3d# ?6H Ab#۸x9 NzzqxԈQӘ>Q]Fyr<Bx" ޮu-m(EOu(=xӋ|OF.)cFa$ 2˻wWH4}h8Km!naT؇QDs T <I1ig0iUPSX0֋1'a}l# &} b$ڶ6b8NŲNg#LuaŚxv.iY!h0aYbE$$ɲ}$쥏>2d-<"p`&vwf}qrzrq19DK(qcL`-忒L1VO%>?Ƒ ?i8(죸+#0*uK L>ڹ& .i;Y;}5ZWTaHѲu3Vh@Ծ&$/M88H"b"<{b8GsQ.ĉ^/b&#):e"n`,:MD'l*~9یNf=tƤ:dѐ$Jj Lja N "Ur^<<I Rׇ V,$,lX/;RD\$;'=\./$>^2x.hM~}e XAf#mC†҇1xz9u4O_w"̑}$1OKXdT˖.^>d TB\x&o6NL'=A|s{||l@)H> X<ވCMaيcj[wmwz$fNOϞd珷?Ԇ BqgP<[c/]-/*#yRԭ%:q+c+P؏f1)ߌ]żSv~mI|R!ve|S57QZ.rg6.>[k߰Ȭz;}l/<[bY{B*XS 5qhA m+I5u˚En8sA, icփ/^ YZtPV(UfmhtH|ڝ%Rt*xW-!U] <NIĢ+ 0O꓄E;_=% eTᲰFNmxI_?V`pBm΂YbSBl. -M f7n14peu' G8+莿.\V>0hn҉qף Fy.}"A!Ѝz^#% f3@:"{l^ۚtmH&a݊->I{wZDfAݒ!SBD׺)z@y扅A?u,x -TM-XឦLqW ._Ho1ybelOJ0ƐVOg)$X 3Ysݻ(; BwQ>k{9+J7Q tEZ_Za fq^y ]1.a$T] x'P(9ZZvg9ꁂ͚8_ ^oNFՓ6GAR{F|H wk>!"@w.łI&ݛ;F3lҸYAB\+d?hˮ&Tn{e56·GjûvL€o92yU/ga;o=yw5C6] wH(o>7ڬn?@̞L> stream xZ[oF~ׯ&<% $q-^;m#167ta~lf, Cp9߹9&uIp L :Ff5{ɜ8*Q3) 28äxG&MVCAW ` ɈLIՂ hZ4 q%xϔUD{ hb1%:!ۋNhdieڃ qP`N f4OĨ1P1> ؚ8b`1x z1 eMDZ -w ;On u*1pœԈFh0IH\ve!ZGOZڠn\f.`eIW#t ,/{aq Y{eF1 gp2vFc{B'`0$qֲtK@O8X :$:h(8Ҳ,xEW pp(vXel2j j\vNhsWC>@d jC0w)MM Xq F4240:KBg{ {}ZU9ӊEnArU^L*c* VP?HM>l''g,)N(J,4Wܧ?XiƒW _2"-bRիߏ@)?:J3Lz97?l_(.`{ l%,{pR 3H {-`0#ON+AB=<>H~ҳ|8odZ~^2,ᄶUQ2O85%y5)&Y2fy1Jʤ:eYR]_٬x<"m`5шx=gϞA,y]+X_ǧóF %IX_F+lr~v/n88?@x39rG~1F~e[!JՊ'|Iiʫ{MCBqN!- vCAoBI}+dlf"*ܨFlj; JhA<{$E.덵`n KZQ+k| CP7Q;)B4Np 6ijvrt*tT(qI+Em+*+]k4F (&rW.65[ʼ7}_7 s Ȝ %T>ypjk8 &;Dhg# MQDR'4Z@3t[EZ=vOДF#`CRhrk%iuAQ^h@G{}Ѩ7-kghw9V7P=W=No4mSO_B/kG |G'YOgòʆ kLR^vjdBɻz ¬A ~ɠ4zByTm-Eh8]I߆6 ׶׼fX5-ê eTY&ױ/ӻ(RD8aZĬ5Q"[Iuf`3R-QpcS\9 ,*@Qӧt/.~<3lv` !}=T:K'e󜟧ckoYR>ɓYI.p?qt"V RpЀ}-X@#W0nI5@{&񴘎u4fߴF؎[e(7M{6t2M_~s9? qm8}\tR8Q[ e$[ endstream endobj 689 0 obj << /Length 3438 /Filter /FlateDecode >> stream xڽ[sܶBO]wMc;MZJ&%1#gG?],bΚfjJbFܩc&̉0ܯM~0X|,V9-QK(N3MJ1id?ij^KKA :sd}mMzQ[>enDЬ_WLG͞ig}su~y k5mUjγչt1ADb{Lܟ/)xDž>OS4R>̈́&Oi8#0M% x}CK?նo ޲v 2R5zZnk{ 0b k4 !lp'C@&uGH0 8@YI/eҋCMF-q;DO%h$4p`L2aVّ"O+v[8>x,7F=e=i0#;Ʒqo/J1!Ԁw~Aux":%I0OtGvJ(LS\BA/^Di'cx䬌FNsLsRwP7X77af:)|/HY) | 87q@.~D"pDAi)~',|xCY:G,撀 9"TR((c5`(iW>}9Fx<?Һ[!eƨ14BvPD-[Sk'*&m3aFY+0$+#0`\=ɶ"*)eYr15~q%e98<8;szg{/iƐYţtлOC.P3V=siپsf9gvlҐȅTdD8Q%9ivn#I" v*+gGGqyu1\&0ҳ3?]rD8nj{{wmC Gxg)ɅvL[ 9HժP$$I'p+s0|qaQ0DoF2(W 1$bTpH5_lUw z|$Ţ/~Tc:pD"9XDB6+^7x0s5ܘ } Mgf3aG1S 7%` ?ة9ΐ$1֑UbCXZuLb,6A-ݣZ vL̙OjTWii m3kCu:=`*ǪbEY W4/*FvF(ytBt&2\f7y +ZzV3gy"w]evOsJ"4 `Чz#I-\q0ryKI Cm.؇{AC׀0:cqfKOk~ﳁ0!*9l{$/'K\RCB˦ JESfVeuhՆ޶MڋhV~Tmp(pUbo-]Y|H4eqPr{\H`sVy:JV8C >s O}yv/~h}0#-k‡IYڠIŦFæOyzA<|Vv{X^_Wt並oZӈSl& endstream endobj 695 0 obj << /Length 3231 /Filter /FlateDecode >> stream xZm6ίO:Fk[-8`7Uuef̎l ܟnI^TjZƖ-IMg134ĈdX߉mk}1s/ޡnwwH9117CVdnڬ>s#yh.omi$ms4g$;N)̔҄$3Bp}Id%L(u?e??sy?P|5&260 G3Y):&q]05aJvsk֑^i/\ iW~N==w<7Xu$"l΍ zv ->3E v'D+B׎" 9S{܏~q~4㸖d4^P{uׁ]r|D)蠸juٻm^[[I!x%?CIb=~el#jfŔ(&ܨUyK~!>bU'#ZϘVHW *tQ<:waQzJxRgSdr>vy7u`:j;55z>hֽNi?yEZ_t#U9{WvK=/`A3 |59qЊ \t¢ z}-(2XG|XF(lvfSWs'b5h 5]x@qK=:UՋ'{9ˮ0Фmh,"˗}|̋ ZhH9.LGA~n:nIn vEېPnHЄC/N8}zrz潏;P#iGQO48z <یݥDIOФv JCei9(m8GhS[8{O@@h):lÔc $̦-Pr$q?IS=5LqiYp%{8)rZӥKZ/A'/v1jU:_UUM`Һ n!Um*]~ʽt_eVmPChz|:]cfTm|FiW$_ Cau@׸UP$(:,zV{tg0iQNp.6C^yΣKheڬ`mUl=^A'RzO β:e0%!5d1i BBN 'k 6а#6>^,8}>-kAهu,Ϫb/YOlm&"6Ð Ґ."( D άx81Mu/]Hddڄ6g>e]J>7D۬mn (o{ %FVa<>lbC"E.b\)K)a^c>_`2H#ۚ" X&0:xs۟m3OqxZH]v%*H - WyXñ:c qL[/ǯl㓿)oMG[!4(* In-֢LsY^.Vf釐eLes4l'~]@%' n,>ouG^؀ꮫ7U)Xr|HNKU0Aq؆+624D7 _/M['W~Ӎ9`j|/n9tuu5<@=6w MgrOv<{g7߫NaQƻD+Hbw MV <~G AOAe5=۠&v\)trc0a7)R)G9.XkEX"OD%IWc5+@ނ58Ip!I/q+ù5l8 [2<*sP+H ih^"@ `Ś=ؚV(a%39 _gK%$KK"#ٝ|R}(Hg(װ"a"oGa2)4 ⱱ"1iw̏r,4 U]&bcH+|Zh\%J8TxKAق8l 3q8v έz7 b@ [&J?KB5e\ I®qrvw  V5DdT;Ua޳ΰq"4' A޾T T8=z.`DbPیB/^HnuP[mMܓpStjwg_cx:3FD bFQt9f2|jo@=U9!#Xǰ↎wpʹv6ns#Nhvne> stream xZsܶBO"$Ӧ3*Nbə4w1"5(1&I#Ƅq 7+=u J̮S&љ;m~]D2#TmUxCVmbduZZcD35l39 D~`b"ꌠ*b?jX)B"ׇr4[Ju4uU.&a+wL7xe@u3uq~q=؍ekdYFAUQvNMڠ-}ѱwURa8{}ʧp:BAvL0:l8 S&>XY0?-nEw֢C}"ڙLϽqt?l5:ƞ8GTL!KFL8fiR„ ILVjPUrh+,]9}dBr$Gb(jsqmV6ykmլ=(3^݂@*6>-wk!i.ߪd뇇zB1NWYؖ&dFuu)KO|ruЌ3ᣨMl57MLhS'6LY{iEkқ>'dd57,V.+7[&m-x.Mʘb.ׯξ5 FlpNQ ~`"#3`(vnW%mrr0~ZWe!:~J=u*`]:Ǯ=\;1Vir߭UR_թ7ݦ;{EN<& 2_x9G3`v^S292NE) ף8O(cB؀Mqh`c 1#JTd}:R؁I"M$c2Mie(m޲uú̅۴قhڪdpќ`c`_ٻf6AZvw|h~rP! CI-)V^E,&G"`F֬j㊿[cܦ@IX%S3\*+ەMUY7w"9ofk4!Ȭ˴8W]0*]*̥7Ysy]5oۨĦvBӕmV폰:v(rr#?Ό9?×G+}dKp8cN-Mu&+NXYlT + 2Ӣ>֑8xWw;E ^3\4Fʢݴk&Ă[ nQ p07J ?Yoy27G$\L+8>~ґaa"3 ~I5cG,S,ýBGsz+wpJ31U&"0MF0;و@m=/|ܯckN6`&%x=l% {wu'vm`jGGk{(8Pǩs 0qփW/g(5Լ7GdF^;8YAϹqkA.痣Pl8et' b'Q?+O-Ϗ$?dTJˠ_G⾇ryYw* 7T+(a&>3˔\a0E˸ `M)2krtU:c&idm^hM[OUV/ތa%Q6\K㜪CI%|dV1 C>w6SN/adwe8휜 '^45 n#lhm)n]R [ }9dcժZ†@DrlDShFepxPg3p%~+o cƺGg+jE*W6ѹf! y2G=$!aYk endstream endobj 709 0 obj << /Length 2488 /Filter /FlateDecode >> stream xZmo8_܇Ԍ&Q{m6p/TuՋ+͵C%K;šIԈ>̐4= %Q9I:gmm>g@p6ͳs)hH0G7nG ^.U<*ky[/uwTpgxd 0d@EM)UDEJ*{q QtK7T5l[‰z@WkVԭ^ijC]_#fتWܮk*K5{=a0~EXĮqDh|^ۅo3ᓙT cdxx̼ڈn\Sq8ؔ*"،M+&+ 7N$Fh,/8Arb !tB*qةP'X.N9FFxyRO;RQԶ dđib_d۾ ,Ը ytX'}@b7?JmKDb742(DfBxҭn>^wGcU?z:olWL|ǦI#L3 ݔG^f JgMf|tn >w hRK6n8,43=˫B#^ c1Uq%@!JZܫ ޢmѫqN}jDy UL^y\\>pIkf:MAV/6jb!sC>,G1,`Y =یͻ&:5`xuӽK_ss eQP!ĂPNK`,GdNb +i`ã-@ѨG^!MfjXdlT]>7'ey% ۖ]zDjʿ1,Xև${^r#Gٹ1Gg,_y4ún.ȿnccs@c4P')_1n/F1ncRP.k8^g{?R$~ocTmB[6r~r(w0%&-.d!< ]]]<;E!;܇m-^P+bQs6v޵>aP? .?i^vͳPu.ҽ;o2[a6vK%wsm"?DGI:E]"X1_N^WgʴYe]*-v ~bCJ5)1&3 cp3lɎV3!qQkgǴ(K(Aϻ8P>PA#/'<Itcڥouӓ;.m^O\a%LS{RGɧvumY2 O(azFslP'w Vi>^ic UV xD7I7֚) ˹?]4kOO @ub\GoVʵ {:BPƂO-C^669B]patQB+2loL)r(}$O b:]Ls_t;%_*si:]~mnÈu01kڕg=i9ڬU/U˞A,qAo8`  M+`b^P|Nw-B|ni[}y)FB~fO.ktQBZ,5|zHC.۝Of7Ѕ4;"JHVvR=b-fly:;O$Q56@YhHbuҳt:L^i÷p:mLu}YnBu^YQ]e<wDyHUlr{[F=9Bfe; 1j!=Am}="z&+~2C.}I endstream endobj 715 0 obj << /Length 2738 /Filter /FlateDecode >> stream xZYo~9l8@Zs1ɑxG# ։y 쩮jU?*IݳČ+{g͋ab[Kbֺ8ûf Uu(nL(!SN}S]zݐ$sucUvVhoڃ̌@fx Ku{VzkUav^\s@edkƑ5ݻͭOqFv9hΙЇEia7\6m9@iaHZeP"6vC՗EwڋbeNhEc]i,FZ;wjMýh}Ð9} õ4;dWFV3n6h &yi!ufUjVգZb' D=m~v<@%QsSAH |_woϜdw(eO\3cOp$j>#J~ "Es &vOvN8͛_MiiU9k[:%"Ru6vJ䵍#! EL` B[ *R/p@XHI?;uh  h䇫VU}&-+{;O>ʹ3D(|4?fhb}صL땆P @{l(IϿ&<z2*(dIZ<7%Ym3vyߖYH9WhEou$cxUoJ:J'ҡK,lv0o!Y ]ZOPV{{l'ǻ6+XC=4$dVgˠE?t- ? +߮KmR6X8,0Z]*td,),T׏Qg'~#UorכcDe%UG7uMUWK޺Eީ;3蝰 pl K[WJABjL'`Fz&E=TNÏ: H(;qeG"*PcqrlW/I{rAwTU\s+"Mg igY9-" ]Rt{C ŬS'701AY앳,XiV "eZD:3H׹@y:e&3׾5s A(׃CЃ3q^6Siԟ9؆ õ;%=> 'IQBTMuzyhC>D)UѸY8$()6%7yoƖl8ccGX]bN@إ6).vG|"p1:fO/;43=r:Ӛ jI,B?h!'\;W&A`0saqO6Ъ@ nBQ]ćtڠ,/G21Pdjzʫ0y)Pbq|@0'f}yx؊ǹXqv擔a;am \xx.5&Ӡq?h̝l8 쥒133x4}2QL&76)5ەLT~2}3gaZGT"[,jG Bg=},4 ;$QiOk^ѝ;V('bCQlwVؘ62Ns[2jc<ǙݎV٭mmǏ!-{9wkEMsGp,j>v6Ӣ*ݒca?Nǁ&Ge5gc'I?l{՞>ΥM pew.@rapXifG?=UGx**x Xϻg~'c>OLjGx "e h\\u~/~*DNψ '#""bs8'5Bq-٫:DpGz&2}1NP菁yi endstream endobj 720 0 obj << /Length 2923 /Filter /FlateDecode >> stream xZ]sԺWdΕUo&-J )!ÔÅUXOv|[#g7.:̰"K^=%4>%Gl؍[`_/)G8Fi⣋TwMvݪzFbvj=U$_U_5%aL"A/E>'@A=2NH”Yq=]$4ڕ6J+ӼP$08= ;C޵HэxF݈ e^M"0}Lv$p<:?ʦ*>+7q<< Kyگ1Cs3DX/{սͿuhMd"T$}Tm?DT"g:F>YhߡIJ#j- g<an=Y곦*4Xt+8Z-8j8Y߾}[Z rR ^Ttb"xDUY| &tgDjSy"͸PAv#Ҍ%")E8 cQ)>& .Opє{W_!7^oAĬM}." O5\#o:g0_zb?b4{å]6\` ]Y%Q?7n7&(@F>dYeEVkLYd#=F獠oF S1o<(+s'yTDΟxL"&,K4tOwgk 1d{6u(%Nci:fO4%#RiB$8QɓK#QչMUOzf33 t =  Z!LP'tMo!< Viw 4X᳄!AKcȠ5H<A D=3M4(:2@&FK԰q0F`&LhYo^@ej?ʯcuU4&gfZFܽ`N 0fguuf")%o7h)7flҴߓ*ֹv *c4J󀵁m;QyG dl!ޭZu]l)  ^Z1raQ[&?A mU`,b\cr:ɷAxtrT+5&Bo2f:<Łݛaˠkl^Wi %b^l:b;P>`619;wi`*^+޵yØ/$xJΕX(&ԇ1:Io|IW}7A4kJ'~Xk\VM~ ^쵂X3kBД}S0!JS+H40:Z5.'(50eYÆ_ʘdTd81!mċI(kl5ڪ!?/})Q"x$>njqsk*^1J@,t؇V:Ǣ`JwH@7 1 [U[آ,\7`+}Y㦬2Pыaubn\2960hҽv\ :ɰ L(-럽OZ09xA}qMZ|:Q;PF-sv;5U0`.f63c} $.Yi(I*dO1⼨ΟŁXG%ԔtC}埻/s9)KdN'&Մ6a{^<짌B_0H lYd_tq_c=TvV( 㠤0 zb%,r :Ɖsa$NЬ9A/m.݁&NX_eWkn-E4\DhsD{GZm˃إϰ cS]&s>K^Iܷ?xLģ7H_%хM64F1aB2Z)k}[։S#?mYH\ ]AvA^+;ޒxZLJHpC}2vg&8Qby)Mw QuLd"f(9(л-. }@@ǹ p~.G >&luIFA5 UYi':HuuQ RxQuof]؟utR({ջRMq!kG6q6AVh& endstream endobj 725 0 obj << /Length 2630 /Filter /FlateDecode >> stream xڵ]o8}q?DI ;;lv Ŗ]eɱp(#t=p43', g,Ul~jF</`gDь, S>;[ I-gs.=Iʒ8*zwyQ]޳gA$7JDj$JL'q!Tl.>D2_b.h(3"0f%,IaZ,9JJNm ut~W״bamuxs0EGpL4 bhtp ,Py;*G&_NPـK]We7Q}n64q3%Sn5V(\ev =:6Y\ջ*,*DT[]UTTDSc1p;,/ǥI:sz2,u N90xجk4c-n sFd[W+02e*L5.KsthBkӱײ%S][ħ,]-FX)Y=NA'toX,h:9ѝVӂOѲ^YQ{dB=P"f"NG!stmMW޻,Ǽs}uLxwCV_k [{ 'd݅~`c.ek^,H#!FlltrrV4TOUrE!A~Z?`X5?4Xx1wS9u(&_v*;ɉ|5w 1cC"(o?vغ"~SEoΜo4gȷLyz$Tb祿 N>PDc~"'?GLRGuX_@[WL(tܧh3;ӓ! 4>|@ C0OMS5 9(: - T,r\U]cfS a<!:) BhN 9 oɫp/`G! E =4=6&!٘pȈ:kCE`\=рkV&*_S+CB, &ü &v.䰝KhyM_ġvϴB`.mdZD}=*QT8À(R-~46Ԭ0^qiƹ @\ƭaw|wIm]M9!dfpSoveFsg9tD35twvKQFܣ]6]Ip(3?zFB."vġ▐o ԤW.΃&\8fvJOvÝzrjg]fi cVGN:xh/ endstream endobj 730 0 obj << /Length 2092 /Filter /FlateDecode >> stream xZoB' G~HMqמ؊ Jl"_ٝ%W~|i pvvڰlQ$IdgyyY3qpTdeA&?[_qHA5]ICWR&Ib6 cI(OT Q^3=ED81F)䔕u3N0YU!ϴ(N|$ۢj/OvOSQdU}6U/qu/WB WP\cuZ2[md{2NNj_.^u_nUsՎӂ[#hjx~klz:S͗Ev ӳZM^鸮UOV_`7_ttY9Tk|e_YV_F_v848epEe0|grrx~6p8M^俚C Kʂ]Voa(5&fuv饙R7zt9ЧU3uUe{e昶+?@ NA-K+Y:VF}$:uo G4'{4Wv@k!GVFa%h=_ͬ#`H ͗tUjk͖EZ8g*̀Imgv_x*q!lF1XQ~D,!!$(:nfTF*2J6WB"Ky]xOkO/ z)gYqƜPzߍfU/$z$u!l6! 벲JWK[@W,Gz_ύ]%&!HÙDv!E<6 ^iq[n}&1qCB[D0T=&ퟅqiSwg`N`K\I-;E$;+ yHlw/alWIt>  a9tw^=9ե =XK}j˯'* ]Qt(HnK Lqc@JAC+_ NP݋[h(L)xF?&?\S3t+\@a8`mlr|c}mX$`W;68\8Վh u924[~&ԴE-%T+ORW `}C@p cC@?' 6Yj i@j= P#:F}*}M,EcaZ`Fā:olϠKPq]̥D$A԰A<1>w*QG='K{"!KQOs1ĨU^0"ŭj5C_3 5d$+nv$h4ܴeSs2 3_04L\,t؛<\j3vUef.L?ϵ!@}2Oy2Mn$8;ֹ('mGեɦ6}_9qBXm:сOlNnknډN s@]-:4r믶7ڷZ۶?5vv#TMDr&L84ޜ 0/eE5\{Uv> stream x[m6_2.fN w-pMH.[JrEJxmp8 9/ aGf1)Pl{jf/ qt \x]]$3cU \_>I+#%1pAl&5Gq;󻳹f>[Ui,&$@A0X0i98Y"I}" B-!.}'af\z6GH~7,-?,kEqcѼ 8$G"nkL>SHR5ϋD=@a0D# J!&=Nb 7Xf_%ND]=©Q$ŠY/_溜9leOs1}8OLaC Z7YiĄn(E~ -F!<*F5U~\V?%*/|cm*D[N# :m*e֊C0a.}D!1 B -u/BIԊq0VfOedgVIJrиdPؼy;|zt٧N OEƤiP *0$u{&UApw;Qc{_ء@ Ufju&%D0I?N]4qpU.v%T²'uk"LJ˶F,LxZ`,sNXoS,0}4VEB4` gT߃%ˇ-X;> pѧL ں1v >akl\աA@K@4w`I<Q'0qgclF'Q; 1}`#H?/읍\qX7&uPl.e.Ĵl\t4kO x0X6V&&|u Qp 8xTqdt aZoke,͟n ۟2बAK% (=B]'4xdGuCj!ZۡR0iSٸ_g(D~~L` &fp9ˈepŝ(wxk\F,,jSnMr39bZ(KtcL)Kؐ QUAkHmkH< ޝ!`Ӄbd<)Z:SZۺYjl M#0 ."[^Q:ZBnvwq(ӈsrd>r]GxxudYOY 8N؉u< .OivUu*WH?99/bԦ:NiΠ帶Lnyi7 o4v 9/X#nHӻҰKεV(|;KKv!ےTװV)io1kI_s qr4kpǘY7#>zz:C#JEU&vYs8"iĐ$oF J\y S()]0z )wzS0jg% endstream endobj 742 0 obj << /Length 2174 /Filter /FlateDecode >> stream xZYsF~` snYr^G]);~h9p $hIvUAo `#O|PȃI~h~=17ϟKۢ\ (!\^Y].&e)e>ucx:u9/[IzmF_rJVbR?>9(/ߖ/0nϛo.jٹGԠ8{PRDj0DD55vM"|9U5FN. ^=`G+ۦ dKi^-R<^/7 j)\JbPP\,-K*u_GXXͥ})Z!5@*)HK=EiJqT'+D(jGìqCC!׆4 ! Qs9%Q06_i>La [snq_>G<kaZWvov>v̳!Y:Q"AQ.@9j_fX ǰ_c}]}uȒvWi` n)2m}\eWY!'kA#;35zK+:kKLi81!Jk Nb+r,SW.I7{AǾn7f^q>!Lj֪ۢWQ\ֲ@S3t%]%_TS$iR*K>+#jI3,d%x.̓j ӁPҗ oRӷwk6*2ɳj"!->@H v8DmJQ@ZT |B(`N޴`! [ga:,,PXhj\E ..@aa^w34_ n7Be=t I ctP }?3u_Ge1Eh%e.42 hjwˑq-#NhUX&|6"cmf;aYg?fe6Ypeea ˈB$@8@H!Ė(ѵhwdch4r9)n4{Y6  |lApKQylҤ! sQ~ۤ|{hLqH46e1}R* @K`$sex,X''WMBJ=i'V8ZEjDyojf\m!ցӎ/"ڶ3>v=WC&*!NYߦt96Qi:wc5&7)Q}\Ǟhޙ-Jsǿ̛HQK뵿5۱ F#tf١6\^^Έ{&9=Bz_ (K~5C e mx8H}3y ƆﲐG:Q1u6fZm+,Jg;sx x-(JovFr0 }RW93S (T1[]ߣ>xnߛYYyԞn*!TSdskܜ U;l#2*bc>sՆ$dux 3;wE]Y_ { :c’دDEj1lvzȰr0ִCnb2Qf{0h 8کߌ}Wx5:=odmO|Δ)Ov" endstream endobj 749 0 obj << /Length 1784 /Filter /FlateDecode >> stream xZYo8~ϯ T\b"v>6T:v7آFp͌$x C  6Om|Bܸ/'? 1 %8!+j<| xi eR/kV\7JDܡ 1Qat`b9 ciOZ AT Yd%8?AQ=}C('? bζkC#fm> <,jRMhErQ7اG7*b2KIw(ɝK`+F=A!fa1"`!a)}4 [ƻm(wcHq _bgĎ~Y,.+5 /<]N~T+m$(C,gmTsN󴪞F^CjiG,j_GQ~vՅ[ *D=[%C*U^eSenIhB˜*0JrdWQDl _oǣ q4`z+4AZPDA[WP ݵ*Յʁ;VS|S$1kmt )눢fػN$iOAG+ߜZ`=Y4Kiffj.gnWYk>#< o\g߄IGB`-+#D1D|WCi-Խ0"1= Ft-}A0C2c-T !1.s*UeJ J!>q{7}UѤP 9W2 'ENjΣ*ۡ>>Ob0mA0i0*+ސ`2q /-y(J(H^MM.5$81"{LǸT@tTZ"=4^B֕;i5kRUUHC ~MpowuafFwߋj;dvk7/ G3Ze>:|pQq{7R0э27u_볐joܳJܴ&*!Zh;3<(w^֝Lr ;0ثb8ﻴ;lHŶĥ pGg-؝CrY 6m,ῼ&ʹea~c]HҼ*~-C0$5 h>cQ"7 Bhΰ9dxnn0o?PGq37G{ txb93 vi.Ԫ~~l -5ˮpS`*dyf8rFlp7ӉW#jA '.XUL[T TR".&~ ;x @FEۋ8~Gf @qgybWuIVqWyBp?j- endstream endobj 757 0 obj << /Length 1935 /Filter /FlateDecode >> stream xZmSFί<ϺSfHӤ$4Ŗ${,m!/egis+=I) ;~q5=l 8I 9a~{'guU'[o^QPJ=?`{2Q$<ߟspR P-yRYcTO(0eÃャyx(XxoXѦ0AF`R-L'@zߤOw]]ϼ?il IwOsqFINÅvgQa05E=Ů5>1aaYIPL%F3l_-sbGB)J7sHxshiYމnkMla{ҸС0X~#0^2!*VyvvBW˖F4:J "(_hԥCl rj5'BRHC"t94ΘEqd.%IM0ɽ"}.PaUH?իY>렍́V̹ p,J?iQTl*1"i"Qj+frDA5~b\Ylod/g[`̣6U|$.UfTZeq+Ih.yGX1K-~zh& yˢ-1a%MWxwiJgau۸qc]SiSIe]3fi鶒[fc=Γ=ԛG;am.Jt2iPb("n)v.+.FN*&DSBHNK⬚5_|*pd݆"ui+ͳ"F+=>qT ק2"?pR*lZ H$Y jMq:QDkqz[ळa DEdw >› J-9~Yfv Y,0鄬"l#didm!֡gd*M X<|}J8V=[Pt^\SlOlVvK79p@վՉ ezK݈e\߿]L>:D~)oɭlgEC^>ْՏu ?3:x[ˍV뇼-(aVeIC446Nu )Ym2;#؞4YO c4-k,5:VtmC%;\.q3m@QJ=ř<:ޛ}3Ux Hܦj ]ήPpk77v|0'EC'֣֣آt 5$VGId| ZucbNYz:;[I![=:%CL3nU(nYwVCwCfHf > stream xks;hw@i aR>(&`FR}HBz{X^={& Jy2.aZ^ #b;O' 1 8%ed6x)<0q%*,vSkWݣI{ț.)$(Ȅ#¸;wtltllN>~&ywC &R ah" +:a"CD0f4~jiwb&IwݎaLr=VU1 GOWu1s z3_$ aOqcLưخO媾V & A=9W<'Q^z ,rgUԅ T2v+2t D/b걟]Em?ajJd$5{0 "I󬜚fYF$M}â_^ U q.Hq6q<`H-`"ῌ#H31I1r0˞465l֏=kRlXflUyu|CB 1Ipa&H۸@vA8ѓEe,"UQfDt'_dFYi*ڥ Xޑwvӽ"f GH{;ƣ5U Ȁi<}6awaVh_u]j>V=T-U!!!ۻR2);0>v~Tr8 .V1t龍RuCM_;?><|1R"Zfa~w$F:<U`A !p]f:?3y;X,_[&! E 0xQv$J6!<`[gyW ~jAsj>}|*c]B>tk\96z޸8 T]˻z(!ZE}8qݫVMpmx]t,írdz2?(߮߅o7b*iR$ѫigے@F?T2-LœdYNY PBSt0)MBۤ->j#|3`Z S-0 -*]^S\$Ix@~{A}J'7q4$6PD& j[-k|[0SMVs6/P-ݢNuhVvTA|טu&b:8 2:nDiҧR4麃tJ JmV k!ԆV)>(H{\WWV{o^REG{>)Jbߧؖ:+nȇG|%mČA1~V?%M`V%w0-d?N݋sA")Mk! ;'z_&!JI-SBX"%Pki^3/^&aӖiB<6˶/z6D}8+aRH1@ Hډ(r6]H-5%:4Ix70. :bsӢjŽ}tHffmBW6_ ezؑ _d' P 5Ou ey^|8#Hp݌ߓsˬ^x9pgFMLD_L\^JݴpUݺG>}ԛF:7l>\toG+!Jo-,n ~~)X EYr7EP*6M\zHWnMdaqCDygkK,Sz&<e_e<1=5%( JSyx@kQXw@$F)vo33gᖳ2HrhJHPkXy C }iL$`r9Q0(U@B.}`CH{qYD8 ;M}:|/_4PџűzmMiOCepRb5PZQ}xhJcAS\ 1[V>a $o2nC/o@ޖ>-.|Xw"3Ce\UIuy|^og욍sXqWtdYy,t5-s'Y-ݍ'!rBAvȿ(52Iަj7e>u])5π>KW`jʏ9"Tkqte'wͬ^K ]KYG/ʬ2+JMh\S8MycXPpI /ƺi{C=[M=LY ǚQA"+|=hFaۭxe~3_59I.݊_W2 endstream endobj 779 0 obj << /Length 2946 /Filter /FlateDecode >> stream xZ[o8~ؘULZt\[tfmm+ɤ~!i'":"s7PcN$dzFly=qϘGyx+&lrq_b1=:nkSNgBHΤTlLv'$EθLui6tv#E8A$N$aB:v5MDYX;^K 9 c$U3żO2Dv*C'Yl77[ynNlZOͧ)CE/z^]_i!qB8K>RECKe=c@ 8jQrkk{5VO-rbe~zHHda[bu (kSL]sw{Xl֋ u6g.mY]ku_fMYlo,%pSX+? d>±)@3f ^D_0f rϮ O4_Y`f6_f[oG\.olE_l<$V-h-ybS3,*={ǻ ;x"!PPTuE+ 5&`{훓vqAmH :{ILYYK8\R`+ʖ17{PL"ȪyʃsR"R9N<qk~p)ΐОEHZShkE4O.M-. aE$(s"+ubp@,i iȫSymU7*YX/@.ZjA !ط\q.SzXc9IX oܙC}ͣa4V&[oa@6VڣAaB(QAŖ~ͨ`iS5DŻDys/3=(@T }g(PAǫs^Th,#\Ęg -3d:K],Kgjs{k-J vxDNxMBbb;0 "8E +"uJ[\e7Ai0Fq aF^lvPU"K[X)Eș:jt=^1+s6 66T e)ܛ`PRp>:=fp8!_6^9턤 $h"e woYZ_bQ®_6Yfv[nӹNl{~aE)5d AI}2,AiE.L֗ &aheSJ*⁨{NxLAzi: j7k^s`4G#ihN}"iHϚ >4ƷBVoY2w2*UĂd9N\Y 0\3¨ڪnau 3 `NDo^Tշܽg ߘPsW2L[|2TqҐ\#N0hU UrfMH d3DqLX +#a 8POt͋:JO1tpeW䧩&'3 ;;6ۼjGi<(gǯώOCVBR{gcyYeU4Dg~qiWyܔׯA81 C {lk b={dיQ7#3fa#> l]`ݛu-e]Mn|dkƎ^8 :B紥ћe2y 4KR8XRi)@/tBg:ϛ8 w X 5Q:~Pz䁎xQ~AhXNvlu힑S]n~S׷/?_9;(ˍ1>)bPI1  Kǐrq gqb@_]z&䪰{,̲j~Qbɑā/27M i&R]se/0hU9҅Y^뼶YI ;g=eCo?yQ199jBCbn|0(r;ǻC_7fhaFs8|GwuG)9uG-dZ8_o{wTQwwԳyл_*ޔWy[pˈ~ѢMY8 ? .jdr ĨhcceK$zTX;lhu5Ua6۾#uAiL_?6l` IBF,8.WPIҭC(w5!J sKƕ6FnG(ѽCOR{ H8zn'Oo{|pD9Tn7W@njBeS} Aӳ?%Aq4*MGRNko}+࡚[ȍP1-wLl 6u3?̗y}c.k endstream endobj 786 0 obj << /Length 2896 /Filter /FlateDecode >> stream xZY6~hI cX"^d52kܣѺ5>~xvx}DUMŪV+#XmvOmoW~OXˁ0Pw/Z1J,luu3]z.3|+QXR աɏWGrY)B&tWmJ3X-"s?\H߯s)lVsEV NMV=޻To*RFjEW l,#ܲYf#E痭NߴD2.f线޷͇C{\kj\(E L CR"Z ӳ$+&tL!eucBd d߅fm.m`5»wS%U.1ܞpbkGEpJ枌b9nÏsF),)X1:mbIAHEʥ%ښ`?1ݘbsD e*tDUBS)pH!X]H˲}Nm3MO9'#٦{=,Q0"?68N3 N~m:uu3a&U2J |,,a y"/un6ydwêSߗ|jdqMDe 8:t' |7TCpLPU G> ?<˶Ux;sKӗIg0D_vKpgR7}!DB l:/&NREz "6 6;v ^mn8Q3?=P)N$!Qᯔ/50ϒuZ! s}޶OtX(*A>I(z<]J11` +L_!N4*D8 s02XQ -Oa! SjpAh p F ͷq#}:ޖL`Bc05$˘QY?'$X7"DE$$CćJm^B3`:>}CB>_Mnf}R%zu;1hbV2jQ)$e|Oy>t{GP Q3* S,B8H{D phRh3y :vK> A Ɗ ?aq .#g\. %B¶i*09?awq3`=⏰|jB>X7q[C x 5 $UBPh!' XmRSgG>:Om]젘IZje/ dRyOLgw{JCz`*Ak؅T̺FBs渡)OHkN%ƎMǷg1KRgpl4L <\!0#$bL"XNi<ΓE#/p Jw7.ج5CI75vژ!K@z~Hkv)ou7Gxy&ZAmpAuܭ!TI%EδhiE݇A?nzjjXW_tRvSR)ҰMm\$WT"5CAn7Le/ uTS's;R{۱sZ.yrKE&0;Kqt!;ƞxCNR`.AC j)m I@XEVЦ~,-̵Rqi;/ 2^Hi*q9wuu6'!lVpHƺPz%˕ OSʻ_~Aǯv1c͈)mG/O4~Fd$XgPTQo8wd-!|_GbޡJsa nVG׷/uP𽏌} L9gY2+t4$Pq]YS%v$'GCAġ~I|630i <7eW(}W.l#6VL']i\Ex>6u5:Cp^dc=raƵ6`K E7]wi^JAgožg_FYIw:l qu0ȯr iO=2%$:k³.vҖs96?b~prv=ha i?-v#)@Fz endstream endobj 792 0 obj << /Length 2032 /Filter /FlateDecode >> stream xYm6ίXSV%ƯTZU_D98J^.%Y;c;xoVU9όy<" -IYַ/[ $:u[lqz1|4*۶yT.ҍ>%7+_4˘THn}sگ8?RQ<)Eb$aB:uTVۨګ%rLtlpJ'*lo}qUYٛ;&| F%)2YNT{0z? ̔e"'%kgO=~{>妩U upVS~ڗ"NbUV &0D$L|]0?]Û/ւ13iH"48!q ҳ'\`db?MHpݢb&=Ux4QA)0D+|Aҏ?F'3 fid";I)lMn੖$Hp<B8,1D*3E&"y ahU]2kDxd8(ƒ!?1~\U8G ƍV[;7<`v 1ga11Z ۓ;O?,I'-u+fs]]Z 6Ŝ"B۶β,"PSb ^ap+HX.R&G`D8"X1&n=+aG ? 4!sF nhJDCuY\zjpaRg@lD_xUCBH T;1rT4e] !_2g. 宗>Kۙr'Լi|/ʷvR d[Cl7)BkLt H/5`k&5H.(3sS pB|N$&ui8mp#UֺV~=/yO\,u] 5o$j3x+'B_H@%dA&#aL^{w]8@ZJ5MyRQV6~uOk7x{vb]Y]A'+\AF%jg܉Aw/dm KXNH=P@ sBPS~,f 82X4Luގ.^CNozRF_.ٺkuW :o\3b_unvu:[o ]]C 7?LSh0-@q:xWf7JVA}pjCnѤ!@>Ggր}1 Ĉ#rrfwA{f//9)0)c L+9Bˬ_H`5a{rI ^Wqd90Bo}p|05S/_lvvs|}}E$nOH(zl9'3~`g>K[;nsu}JAd"Ƿ/i+O֓"#kf9 endstream endobj 686 0 obj << /Type /ObjStm /N 100 /First 891 /Length 2226 /Filter /FlateDecode >> stream xZmo7_sICAk +rI](yuVJJbɫ@bqw3ϼܔ8r07IRLP31\%:Dވ/ϣTNбB'#`x;N4bĝl8M^ޛ@ys`B"AÙ Y{ 9`@^%fI\x+ˆOe$^CX kb'x=R@h(CSt/@"i$Ǥ-#LGŅOhMd}wtbR 2`$Dhhbة {AH;0%:i#f6Aa@nA1'ùy`h }%Lޤ3K1Ћ^%%LG3hBA$]mPW&;} ei$"ddvjTLf(.`gd0 dp &4x\̠3aMQ{ X/Š+)ҩ -KV&`R9u-FO\զdFW~U̼<`!ڌ㜬/_Ϻ~1 㘧OMTz'fo꼹g`] łQw#S~4RV-53_ȀR65f2:y. [^ ~(' ie2;`^fMُzYO~vU?@z2kԊvWz:.uQ_}|EMrNk݊G/^{UpD£cjP]4C{]!ۈecO! Y)J>lc^C!%rw}b777vڛz׼MY6sI}޹!l5(`*Vyˢ\dm鵫?ޅmʖ'R6"@Bd$_. ).yTS7/Z-bP"N:B-,_JhNQ=w+i ;Z*w~c^\gԏmANWBgE@Z^R-נq{`:|3]⵽_םnvVU,CCB l&2R!Ѫ {8P[E. zdyk2\d +("uA̐d6/L۟_g'^vDrb 3҃+Qw!WL n;wtae.>{ XCjְY-^]Hv@C =H!s%ԣ[3œ-x0J]v|\LXYuJ|{5 66i0ũȐR~Xky<1laAخeSOL걎*]_KiP2 >݅6R" k! 6{r2c2EQ?lAڴq^zv1PܫصWO(O9p2AxyZG]<}|iӖٜqt0̓=9ͱs͞Vۗ{Χ OOr8‰ #nBQֹ9sI[dm*<$*xxzv">N`  !Y=Il*(jE'?G-f-DQy|YK@tYLyuRcNf:k4+PoF@$:,TPGꑈ6dX뢜z𾹏'D] D8EXwR`XXآ;8q \xו| H4$CGGf= cI=wI˷ xɯ˦mQ]֛$=2bkt'|+?:YN[NP'ˋ#W$=@ЯB :;,|O|o"'&sLaS9w$WR>$Gfo߷1CS][>s}n3ݽ;S9it!LP%xTP]c檞l{4l;k6_G ¨ endstream endobj 793 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/home/moreno/src/queueing/doc/qn_closed_multi_apl.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 794 0 R /BBox [0 0 121 144] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 795 0 R >>/Font << /R8 796 0 R>> >> /Length 736 /Filter /FlateDecode >> stream x}Uj1+t:`E֣uL w!8 C~?=&kg1xV%U?['mӶ4IV$ۏYJFH' zH2;S26 ד@u+ZhM+Z ꣭'բhHY8cRj|4d2kI0l2'E¨ں"¨|t hI(Ңlh%C.l]CȚB1̚akBhy0\=p.WP%X/@ҏSX{Zӑ?~ ǬWBF IUBפuB߅ @K(A~ȃFꍁHJ 2d1)mP a).&(g&09w\sC ٪|'(E6\ApEsOB-"bh6gE0Y!UyS 8Oc2,tm r|*ОIYa,GSL73&/Z.ӨgJFpjS%ܲ,^L-cd;ٗ#ɦe˕^%8.#ӳ x<ez؝y^IJulϙpT7/ endstream endobj 799 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1223 >> stream xQkPW%dVcjI#D4ڱbQjEP| bb&PbrYH j%X,m}*R;NwMgXgw=|cJQVe˙PY,AҷH m_\o7v.Qie$-_be:FS$\V~uG(Tfɗr:_+ڥT_ʓc1 5}G5ۈa*,[a"ml6)Ǹ? 'iy*/ OE/+>PUZ3w!{ogK%zK-vsWydW|H p@J5kQ-7z1"YسWVݝ}abV'FVXKmR#ՅːY3tISI;a=tU/ۥ'j]ٔ6t)+[m㸮{Hr<(Dː_8%B4CWH?6VqW WiO$͖@ LMЌn=mcg&*cfagbNlUHACc'9|iἿK~-ah>GO<,4' /26Tp^rf0{TI:%zfK:M+Gc՜k).4*A8,֕Uvy<}Dv؛p^tFgMx^\{6@gjjΠ[ KLgb.rTaA'{h%[/Zl-I -:sы._gwKz A;!dNpGA9Cs&hp9 ix:cKٞ`6;C8^L5Z(6UgsHX+QO??%S-IIΒ* vwރWIQߋ|33Pō tB1,Td Kߪ.9%k1 (2RK{':eCHyI; D~9IlJm>n\y;MLŵ>,Bä֣o}US0X endstream endobj 802 0 obj << /Length 1313 /Filter /FlateDecode >> stream xڍVYoF~ 7{hЇna[-l"<, ~sČG2>KbNg;n8'E M$_yoLpL̖zv$z~{ҌIVnmQ?#O"A( 8`PT34]jX<2 N˦yo˾Xys%Wjow +EOcll2 ^;`Wϥ?/:}lM2/>jBL U^L6#c! LRaQ6u;OU[]\E) M[ORiq"gє۾hj5:Y ~Ady#دm pX8!O`-.VyI3ִ=8<2&#;퇨A@yXimo[-VW Ir;AvAM]l]PCR}`?FY*&430 h{vtêb=i塷r " :{ZMu}k/ 1I }elP6k7*5;kNM sTB/ds1Bw1KRw 4%Z$@`\H"eÖTi Pi.?GfsĔLtQK )&@[Q U c(޻d]uhD2eq/He\GGm;c h̓_.qi^8+# `gx\:B:Xv03hB /:ɂ:֠5gW@fu$¯m 8;u'0($$0nN~NôqV+@X ˯߬y?i (͌LvsD9L͝NJr766 UYj^ eDEm;1(N9yhɟw#^U/<εN_ݓn nkz_?`c_%'a?$\ G㉻k"WD?zpކ +56)Kx2Td$`KzTts#a"#).INI%`HqpwʤgWVY6j gܿW^O =${;x?H endstream endobj 805 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/home/moreno/src/queueing/doc/qn_web_model.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 806 0 R /BBox [0 0 285 146] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 807 0 R >>/Font << /R8 808 0 R>> >> /Length 1255 /Filter /FlateDecode >> stream xWˎ7 WXE/q g{!!olӁ $R7Iiz׳aȪYo\b>=-ɖwץdOhsfU$o]1%)௳ё[y\P!_ &P* A&hXHhpTq^>/KhZ4kʂ\/5S:`eS-CKx^|a[ϿGα '%e ܁ aȻJpBV+EnI ZP jHɫA5B*@a 1y R$]]*AǵKNwd$-+:mIW}5Dt෎MdB(dh|^B,+H6EZ;rwY Rm)9ԧHsU']Ab1|sg !IWppqd >Iç 4(L$-"uhUPc|KBkc| 2d FBvSli-X B5;_:7gYP ˇ?KHlN5N22CucEϐ)_NLywcv"EOp̘PB~fځg)ء_<>IFe齃mvs9 zAz)>-{2hў叧'3K " nky?<9UqniKW endstream endobj 810 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 2472 >> stream xUkTS>!䜣ԒFфֶj-+T[Ղ@! BxE ! ĶZUlZ޵u]]w͟3{of`.p DEi+W)/ޅHR0a \WzB3Pse0v5M6 J 3^;XX= "a~qX(]RޑLI^Zð{ i¨|Mo {{{6bQX4bA^;a`{`k1Oy,aQXvuŒdN&Ne  ĿI| MKGK휏Lꆬƕв**KJ`b;$kk26 &*⣛ ̇ 啱G`徴 Q6Zŷ ~ԺɹkTppD=qه8 #}M7$Iw9\@|t0u*H@LTZ8 儱8n䲟@Zu`W|&IǨ9 Cf.aTJXR\+-S@P ~p+@.$J<&Ao^◶^(G@WIqfZzhȵ'ݩHEj~{PnE"ԵFUa>$٩O=p#\WRS mu4HWFXufu`9p-ɞQ睓7Fx<_u"CZ8C.=νw1h Qg ~GS_WU #YNCe٧1Z/ `l[kƊ.k_$p}[gѩVE]ޓR[vX UGI2Q4nKY}VZNSwlN+' K n`JQ-uuymq}qm wEE9O\<^J8~ob1 ތjI߹Bxk)@جUzx=3'r|:tZ6jAb9HGjPzu-ږ-mAiE bXoVOZkҘ*1骫j&P!|D WD^]WRasJNbM˸`Zק8SeObhqn1PdcLO~ ?@[J+R2CS.ڧ/ͱmQ`oMh]ʥBeAY⁏50\5oZO]e\e?0ᖥ9teAE^~%3@= G,icD޽o!wݏ^Jc]O}V@I!qu篰p; dP'iwj~}3 /}C{Hɥ`O"vHEִ*v:vd+!f ;Os zrӴUFhK)th YZq턾;YV|ZvȄO7Z>k ݡ27 #*,.?uq-1`^ ;@h8MRh,%qenQ }\۰Cpɀn͈($x`Gnyoo~!:Nr0ȕuܑ_7y|]nݱMZG|s'pΓ}nw9AjpKG,3wef9+Jiǒ=-dLM%M$t]]R乙|XQ(Z9 SC2Y"^џlYmN̿snT,l"Rpr+msGf9HC k5sLV`2p+ YVxH#RNN9[tpϐ9AߠU)20T7>INq?DKPػo<[{mVXe]B6Zw6ݩq{d endstream endobj 814 0 obj << /Length 1922 /Filter /FlateDecode >> stream xڝXYF~_#,#N%Sq,S䁕fW0 ۛtρ@zUboe,i ArEM~<]ɄbBQӜE).=~/tDGDJ>)V# Ϭ0EpV "n.|P|.mum"nU K/..vLڇ;7.oV,V+_!}0QTO Eg_lWJōw0fs@J =EF>%,)%/b.b嶨_M. ,0X<#9P'sB|7 &T:\Pr2ET:m? mhq8Lݐw RnWa(_Ek~=AzY@ٹ$D\?@L4w4 M[th:91ٖޚKm]~DFz߭viS57uqVѻSt*=}$Ui+0ay!X?dxʥ g1"}%;c wJ2]ەq~0p3Uf(M`Ӝ2;M!Wp#k!~)M?5U=,~i<U|h-KQHˈ NfE+3GOJӗ 2~odPG'ǿ<1}. 2B5 / j"P :ɨnli>ڎlm!tހ޼0WB8P-15K(u'TA S h_JÛ4N24@wGQ] 185s;I;N#?sDZ6ڶ#d=#.<#&IS߆œP8lrp/dX~l l{F$HL "Ѧsj> (ťiWX/#j\ȢqhSpV.F3Ru1b6ʥcOb`q'a✲ٹ;Ȧ`'P絫ƍḃ xNg=l>c~Pη1nwZ-0E94DmG$ٵ{(sFH=hBGf"y}V w{BBa>/Font << /R10 822 0 R>> >> /Length 2206 /Filter /FlateDecode >> stream xYie7 !K`wݬR$%Zʇ|ʪ4>뭻 ~z>T'?bYB)ϬַׇĔs'KH%Wr-綳'Eg-H):|c`~x~ř1+E,]]^]Grxl9=+𦝗>IL(iճ)v*);Hf CsFhN#H 4zB;4Gif\uTB;tx.F;,su +-dɢB(q,Svs)xD2VAt/%G7;fܓ2ZߙgW\xu.-je,NV>Y燗Һ9|{;j8Ms]4ӯO.#1dkWr^%S ë{䳢KLi_ esw69UD^ و_K6-&~ĖЦr1e,NLίP]XO`d-{B{_I/ԐeFi[BɩuX .mo-.~I_Th~G~D|x<Ph!W0xrHvpbqJ[3UW)yo2X "d=Z6^6p2MCb߈mT vD|\^BSUrb(ϩQ}ch7a0DZI1j &VF4èh M1*jcԠ FEl*2çNC&Tղi VB4hv 2ŧwlnY~ .E@hM٩G9@SJhN%P9h~"TBSvZ斨eh.ciu\vhPv&UQƮEc|^bݨ>aTrv|Ґc)^<ߴyEV^32g"g f&pe9 IUҺ2.׊&ɋ-Ǿu|Gڴ ܟl%">|,^MҪ=ˊ{h]>WQɰˏ ݑ?zdMǪ:Βj%nvk{Fh{a)^ip 48"~F9h~޲8<( ѭ BC[V@IP/4:Y"~B)VnB/4Tv;TR&}(XWE]MH,"cblR!d:ls6Q0ل}48${g#bmb,UoxH>,Ug{bPV/YJ:N38#4[99ahpvΉ=6z\4DbwNF_Ӡ iPqN1lz&pNx"/1M=sՇ"?Y"}Fŝi^4TC86J~NK~'۳RE!M?/3&p endstream endobj 823 0 obj << /Filter /FlateDecode /Length 505 >> stream x]1n@E{7f`l4.I.@KC)>)Ryޛ6f.VnXK}.fu|ֆ uZ?οx:uzx<> stream x353Q0P5T5P05S @, 1s L  = :yr{*rr{q;8+rDwwvvrllfp;qy(tH˽z]o۝YV|ti_o]lw[G|}}//2˽j_{ D2.WO@.P endstream endobj 826 0 obj << /Filter /FlateDecode /Length 189 >> stream x3Q0P0Q5T02S , 1s - Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAmqz3Le8r}[opGǙCBS! DC\ endstream endobj 827 0 obj << /Filter /FlateDecode /Length 170 >> stream x33T0P0Q5T052S @@c$r*XL-  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1Pw}TH'w=o5anL \ \uH endstream endobj 828 0 obj << /Filter /FlateDecode /Length 149 >> stream x323Q0P0Uе0P042S , 1s  @)Y@I'O.}O_T.pJ.}2.}g %hj,`cﭠ q)+jtQP8@VCB F= endstream endobj 829 0 obj << /Filter /FlateDecode /Length 155 >> stream x36гP0B]sc#K#C.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O=ٯ?/zn,^.WO@.nEQ endstream endobj 830 0 obj << /Filter /FlateDecode /Length 176 >> stream x33T0P0Q5P05R0VH123 !U`baT032L,ɥPRTʥTɥTƥ\r;;66 @ܼb;;.O$8*'sl_~ L\ \)J endstream endobj 831 0 obj << /Filter /FlateDecode /Length 221 >> stream x3гP0P0T5T05U0VH1230 !U`jbT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-,$uC[ u0_0RK_~Aoc_Vwm7L;;lNصki.xĠNf endstream endobj 832 0 obj << /Filter /FlateDecode /Length 228 >> stream x333U0P0Q5T0P02QH1230!U`jbT02@.'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠qAnDm@_ct?~we_UW~{Ww[]߲#Q/oٷm}GL B ` endstream endobj 833 0 obj << /Filter /FlateDecode /Length 159 >> stream x333R0P04P5P0S , 1s , XXɓKW4K?KK)YK%hl,`cﭠ q)+jtQP[ 2=F_ >! endstream endobj 834 0 obj << /Filter /FlateDecode /Length 235 >> stream x353V0P0T5T05P0VH1230 !U`biT032@X,ɥPRTʥTɥTƥ\r;;66 @ܼb;;.O }\*M-r͇j_"濗jk-:ӖUPG⠎† L9$_td^OS_ߊ>̙s%Nv $\=8M endstream endobj 835 0 obj << /Filter /FlateDecode /Length 243 >> stream x3ԳP0P0R5T"cC.=C ɹ\ `A3#  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1P }RE'Z$"H]_~Qb΂O kY^;2}c%z'ɳH:!>!Sr•[vM~;::"1`A.WO@.+U endstream endobj 836 0 obj << /Filter /FlateDecode /Length 141 >> stream x323S0P0Uе0P042S , 1s  @)Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAm|B = endstream endobj 837 0 obj << /Filter /FlateDecode /Length 248 >> stream x3P0P0Vе0T072R @c$r*,L c j2K:yr{*rUr{q;8+9.@Sc݀}o]s~Nin^1P5l+y.d4h>akK9~;M_ݛY'G]?k.dۡ76Enݺmá<:N \ \_ endstream endobj 838 0 obj << /Filter /FlateDecode /Length 207 >> stream x3P0P53Rе0,R  1s ̌ f`M ,ɥPRTʥT˥Tȥ`ȥ 47KM V8qy('r9Ħ5:o3{Id_ȽYe=P~.02pz*rI endstream endobj 839 0 obj << /Filter /FlateDecode /Length 141 >> stream x3P0Pе0V54R  1s , `= ,ɥPRTʥTʥ`ɥ`ȥ 45KM w)+갳tQP~04ppz*rg% endstream endobj 840 0 obj << /Filter /FlateDecode /Length 177 >> stream x3P0P53R55R  1s ̌ &`M D<=}JJSÁj=  ]r;;66 @ܼb;;.Od Z ׉{[?| k''t7} endstream endobj 841 0 obj << /Filter /FlateDecode /Length 224 >> stream x3P0P53R55P0V5QH1230 !U`fjT013k@1'BIQi*~8P-P!S!K4X.}7}gg7 7F[A(㜟SW bg颠`UcAهU_޿7%/eu__vݥv[o'{vs1(0qz*rR& endstream endobj 842 0 obj << /Filter /FlateDecode /Length 235 >> stream x3P0P53R55U0V5VH1230 !U`fjT052k A'BIQi*~8P-P!S!K4X.}7}gg7 7F[A(㜟SW bg颠Ṙ[s> stream x3P0Pе0V57,R  1s , f&`M D<=}JJSÁj=  ]r;;66 @ܼb;;.O8-C?oֶ! WAٷ۽wˇ9$\L/q4m?bAS! 1AS endstream endobj 844 0 obj << /Filter /FlateDecode /Length 183 >> stream x373T0P0Q5T0P5TH123!U`fbT02@.'BIQi*~8P%PS!K4X.}7}gg7 7Fhs~Nin^1Pڊ3&q{?/.-<7]۷"#AS! IN endstream endobj 845 0 obj << /Filter /FlateDecode /Length 196 >> stream x3P0B]KSCC.=C U6 *i'BIQi*~8PPS!K4X.}7}gg7 7F[A(㜟SW bg颠pC~yUU5/8ekگ/Զ?ooo D7i&620rz*rD endstream endobj 846 0 obj << /Filter /FlateDecode /Length 151 >> stream x323R0B]3C#cCC.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O3_+I$}S! C? endstream endobj 847 0 obj << /Filter /FlateDecode /Length 211 >> stream x31V0P5T5P01R0TH1230 !U`blT037i&`Y'O.}O_T.pR.}:.}gC.}h\nn@n7 .}ܼb;;.OEl3?~{pG_~˽u{e߽wotR) endstream endobj 848 0 obj << /Filter /FlateDecode /Length 255 >> stream x333T0P0R5P05S0TH123 !U`jbT02,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-@EN /8k} ok vE09|B#|¹d1(3ܲjv,6'Vۜ95nNM8t .WO@.Yz endstream endobj 849 0 obj << /Filter /FlateDecode /Length 215 >> stream x353T0P0T53U01S5TH123!U`bjT032 ,ɥPRTʥTɥTƥ`ȥ 45KM ƥSW bg颠iR> stream x353T0PP53U06R5TH123!U`dbT01,,ɥPRTʥTɥTƥ`ȥ 45KM ƥSW bg颠`4?~E{AS! 9 endstream endobj 851 0 obj << /Filter /FlateDecode /Length 216 >> stream x313Q0P0R5T01R0TH1230 !U`b`T01,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-xbࡤЖ}NF|_嶮:a^堎1]Aƞ+/ڀFgs?mw߮[Gs08pz*rh@ endstream endobj 852 0 obj << /Filter /FlateDecode /Length 219 >> stream x3гT0P0T5T02R @c$r*L C j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j Z6 ;kc~ΛlSy*j8H}9!NzMm9:ͬ \ \YH= endstream endobj 853 0 obj << /Filter /FlateDecode /Length 143 >> stream x33V0P0U53W04Q5TH1230!U`iS032L,ɥPRTʥ`ɥTť`ȥ 43KM ťSW`ig颠?pS! Q8 endstream endobj 854 0 obj << /Filter /FlateDecode /Length 230 >> stream x33ֳP0P0V5P03T0TH1230 !U`jaT02,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-HhR1?"|JU /2s29\?ʲ6={{t 8s~sHDl S endstream endobj 855 0 obj << /Filter /FlateDecode /Length 167 >> stream x3P0P57S5T0 )\z@a 1s - F`M $vU()*M*w pV0w˥{+esJsZ<]8ΐkbp4Y endstream endobj 856 0 obj << /Filter /FlateDecode /Length 218 >> stream x3P0P53R5T02QеPH1230!U`afT054`i'O.}O_T.pZ.}B.}g  47KM V8qy('W xn8bWK{/W_Vޥ.`absV_;MGGB-l#B IL endstream endobj 857 0 obj << /Filter /FlateDecode /Length 248 >> stream x3P0P53R55U02Q5QH1230!U`afT054`i'O.}O_T.pZ.}B.}g  47KM V8qy(-T#"|YqM>dD]߂}i}񫷯ߗ]GE<)ڪCt]׉s;гAS! DWD endstream endobj 858 0 obj << /Filter /FlateDecode /Length 178 >> stream x3P0P5bScc] C.=C0ɹ\ f`AS&6'BIQi*~8P-P!S!K4X.}7}gg7 7F[A(㜟SW bg颠30bo~WTT7g´Rg`rT9W endstream endobj 859 0 obj << /Filter /FlateDecode /Length 226 >> stream x3P0P53R55S0V5QH1230 !U`fjT052kf`i'O.}O_T.pZ.}B.}gC.}h\nn@n.P9?47ΎEAmcL[/Ta~5 &T7_ݿ;VÜ9{$T7(Xv $" "901(pz*rGL endstream endobj 860 0 obj << /Filter /FlateDecode /Length 160 >> stream x3P0P53R56,R  1s ̌ F`M ,ɥPRTʥT˥Tȥ`ȥ 47KM V8qy(';"Cl V1(0qz*rn, endstream endobj 861 0 obj << /Filter /FlateDecode /Length 172 >> stream x3P0Pе0V55R  1s , &`M D<=}JJSÁj=  ]r;;66 @ܼb;;.Os\t!*ˮ뿮ߌ}EE#B Rm8 endstream endobj 862 0 obj << /Filter /FlateDecode /Length 152 >> stream x3P0Pе0V53LR  1s , f . fvU()*M*w pV0w˥{+esJsZ<]6.[pH=k@ep`rTaB endstream endobj 863 0 obj << /Filter /FlateDecode /Length 189 >> stream x333Q0B]SK 2PH1230 ɹ\@i RN\ %E\@i.}0`ȥ 43KM V8qy(m2^+~`z۴/s7߱[n~0]7wUگ/߾~կp03M endstream endobj 864 0 obj << /Filter /FlateDecode /Length 140 >> stream x33W0P0Sе0P022S , 1s  - @u,'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠?>AS! > endstream endobj 865 0 obj << /Filter /FlateDecode /Length 196 >> stream x33S0P5T5T0S , 1s L- !3N\ %E\@\`)YK%hl,`c 4K9?47ΎEAm+R_࿽~^_ۯ/_~~˯US! 2HO endstream endobj 866 0 obj << /Filter /FlateDecode /Length 183 >> stream x3Q0P0U53P42S @, 1s , @u,'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠s)[e} )%;[&}`#&.WO@.wV endstream endobj 867 0 obj << /Filter /FlateDecode /Length 149 >> stream x36гP0P0Uе0P022S , 1s  - @u,'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠?6𓉷_n=|?=n endstream endobj 868 0 obj << /Filter /FlateDecode /Length 239 >> stream x333R0P0T53P05W0VH1230 !U`jfT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-,$yAƇ[|}^&uuC 1B's&."$a'=Ƕ\{a~&mm Ov endstream endobj 869 0 obj << /Filter /FlateDecode /Length 221 >> stream x333R0P0R53P"cC.=C ɹ\ `A3c  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1PY<'y>h|"| 8eRr&yo{^w=o7KO]NLlmst +KQ endstream endobj 870 0 obj << /Filter /FlateDecode /Length 218 >> stream x33V0P0Vе0P032R @c$r*Z, j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j Jd>EfO(kh47Kڗ_J߿qyĎWߔz8`AL0+Q endstream endobj 871 0 obj << /Filter /FlateDecode /Length 165 >> stream x333U0P0S5@f!0Fr.WXPL4%<=}JJSÁ*=* ]r;;66 @ܼb;;.O+-Σzo砸[V]oS8H endstream endobj 872 0 obj << /Filter /FlateDecode /Length 233 >> stream x333V0P0V53P01R @c$r*̌ j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j IMkVι=tٞzZ7߿QCxS?9|„D&> stream x363R0P0T57Q06U0VH1230 !U`lbT072 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-H:k9eC\=^BI% endstream endobj 874 0 obj << /Filter /FlateDecode /Length 220 >> stream x33V0P0S5 F& )\z@Q 1s L- &@u%<=}JJSÁ*=ʸ ]r;;66 @ܼb;;.O+OJǾ~qHf7~{{[=8_v_}x<" ,\ \[! endstream endobj 875 0 obj << /Filter /FlateDecode /Length 253 >> stream x333Q0P0V53P03T02QH1230!U`jaT02,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-XBZ#EN/S..g簛W]-?%=M~֯]m]nf[)e;yy02pz*r[Y[_ endstream endobj 876 0 obj << /Filter /FlateDecode /Length 174 >> stream x333U0P0S5T03T0VH1230 !U`jjT032̀,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-$q(/jekX_ت_~8.WO@.\H endstream endobj 877 0 obj << /Filter /FlateDecode /Length 223 >> stream x333S0P0V53P032R @c$r*̌ j2K:yr{*rUr{q;8+9.@Sc݀}o]s~Nin^1PڂK<7YEt5$q(|"'|X;/uU_w_={ϭջ>Qmn֭m8tG6AS! N endstream endobj 878 0 obj << /Filter /FlateDecode /Length 162 >> stream x313T0P0S53P012S @@c$r*4i2K:yr{*rUr{Up;8+rDMwwvvrllt29y@-vv\. j;Wp~?Y_ƹS! B8 endstream endobj 879 0 obj << /Filter /FlateDecode /Length 169 >> stream x333U0P0Sе@f! g$r*, @ @ N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1Pfq߿\-[o:ַqp \ \O endstream endobj 880 0 obj << /Filter /FlateDecode /Length 150 >> stream x37гT0P0Rе0P02S , 1s  @Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAm,Vz{G endstream endobj 881 0 obj << /Filter /FlateDecode /Length 214 >> stream x353S0P0R57T052R @c$r*̍ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j H4 T{½&U/w˾[w8h6p6z۸Ox=?, \ \zL endstream endobj 882 0 obj << /Filter /FlateDecode /Length 160 >> stream x353S0PT57R06S5TH1230!U`dnT072,,ɥPRTʥTɥTƥ\r;;66@۸sJsZ<]?c¯Ç~CB (?? endstream endobj 883 0 obj << /Filter /FlateDecode /Length 242 >> stream x353S0P0R57R05R0TH1230 !U`j`T072,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-QCI(_pܫ͏_?\[[on8ͣ1:"17G\G-ۗ˾~@qջز#Q?;;G`ásX\=ÃZ endstream endobj 884 0 obj << /Filter /FlateDecode /Length 241 >> stream x353S0P0R57R05T0TH1230 !U`biT072,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(- !~Ǘ/_h|G/_Uo[.!Q/:eq<Y[o;cz#Qfap`rTZ endstream endobj 885 0 obj << /Filter /FlateDecode /Length 183 >> stream x353S0B]s#S#]CC.=C(U7 *@<=}JJSÁ=K4X.}7}gg7 7Fhs~Nin^1Pڂk!_\Poz0H>"z _AS! 1=R endstream endobj 886 0 obj << /Filter /FlateDecode /Length 220 >> stream x353S0P0R57R0R )\z@Q 1s L @u%<=}JJSÁ*=ʸK4X.}7}gg7 7Fhs~Nin^1Po6v߷߻wjć>Qcc=۷_m >uanM\ \ \Q endstream endobj 887 0 obj << /Filter /FlateDecode /Length 106 >> stream x32U0P0W54T0R )\z@Q 1s  @9u%<=}JJSÁ*=ʸ ]ry(DŽ\ \#v endstream endobj 888 0 obj << /Filter /FlateDecode /Length 212 >> stream x353S0P0V57R05R0TH1230 !U`biT072@,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-a/8pܫ6fڭp;{c_o&زMۆCnDlHK\[ endstream endobj 891 0 obj << /Length 1870 /Filter /FlateDecode >> stream xڽY[o6~ϯ0eYDRIaaK$ 2typ%f[$]ѡdQshIQ;|Tń1*2&oW MN~~6N;<{&M'gbrv=uv5XyD9v~bu~>R>)i&&TYpTQ2cRװS/.4m2ni3~`fk)$Fvx&y49-^WyS+z*|1kZR~"{M}aORy3ۗ6yUJi-n;H,+;1q>a;hk&S1EwPRT00V-hzWޭ3\_|?/cD 3qD3/uSt 贆P58 L(9Ώ14S!dNd։F0HVV;]-(!D;jqiP$I~pB;..5r0Cy`-v ?[Q 9wB̿JMA7.N{!Ǔ_+X 0m2u/u1q[8Y5ES = !i)]z%r?̆[mW䮭3y5,bQ|iM->9PLtԜ1'ݰ`L60ΫbӫyfFWN{j RmTkqWdF=6-ۜM^у9u706 C0F c { .VgT,8NImrZZ@'Oi4V~qw n8ϑ/8aZGL8;QN$k&H5tRFUw(qJ%{YUKJ-㻛#]r@ !c^o}ł%Hڽ'dk/GvBNvFdIojdDUw fyEE?u/$*mwEոa'~0oNfiw7%(ǖ__L }{VC͊7nj4dغr&Uesf?PP> -MJq;ËCwH_Ŷ:Mn?NB,^  !U`<.(-vKw?(4;y"w)O)#h:R=r'A!>)\Гs`YqV2KX43 ˤ??wt'Q t)vT]~lh@$ 9)}jتpT>/Font << /R10 898 0 R>> >> /Length 1495 /Filter /FlateDecode >> stream xXI5&4}_ !hU9"!'q)!AQ&҄*vg& I*"'1B;j3pPN9?x~3џdJxA:=^v7O{?wII內oylux. ]q ^E`R,6= `6iz<[,x4%|6iz<[4<vgmóix6iD;Txh[2/z<[4<6DklCS40k9.`fYٿ!0T/抒ƗzEZ NZ&ꎾTKmSΗj6|:9}AN(ṸӇY{04CNnpgxsF߃2 re8_Tq<~$ 4N4pi|CZъ ڨF4$wH'>]{DCUrhC)D!g3dCy?WW*է3Z*6O\?v w"}v뗲ʸ]8{+^!waEն<eu߱$q,k^ͯ`ZtWW --=-a=%rnUvYl>XnX(GP}-RugvZLtTZ@ܧ`CvS﹑W.c=N#w*E_ ] z$<(%17}M3;g7|*XS'ʪJs.cUCA֏h +\$$;Pc6 `&41ļ)r}i +$&i~!`1'H\q )Ӛ&?@eɺ"(@"]c0nQsE;껐% gSMw0{Ǟz#]T'M֤X=LPXq 1=ה3 &V+Qq#c5$~=9=kK \ʍ'=s_lHÀܰJCj6Ŗ,֥#, 4nMKS3E$lK;Vyɪ}jD_B){^x;^> stream x]1N@E{7HfL iBCBm9PP^fs|z|ky]0N/ךr}ʟT5{56KwΛwҥvgx{;7Nm-Vtb x﷙ O}(ZOlCj!@[PjDLU&bsPl \Mƃ &_WH}+V|opj@+&_@2@\ 9|5 WI|M:]l*_gNW:t66U&u6tIM:]뜂ӵ̗Spr NW6U toC_|:] P@ }Q@r(( ( ( (=]8^IU׺?]p^q˼~R endstream endobj 901 0 obj << /Filter /FlateDecode /Length 180 >> stream x37V0P0U5P02S , 1s L &@)Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAmy^{?/.-<7]vlɡ# \ \O endstream endobj 902 0 obj << /Filter /FlateDecode /Length 205 >> stream x31׳T0P0T5P01S0RH1230 !U`bjT@-@ dtU()*M*w pV0w˥{+esJsZ<]Y`"7Of/µKmLmv@z6onnbk3+#B 1oEB endstream endobj 903 0 obj << /Filter /FlateDecode /Length 158 >> stream x323R0P0T53P02Q0RH1230 !U`dlT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-u_O"!, \ \=>@X endstream endobj 904 0 obj << /Filter /FlateDecode /Length 202 >> stream x31V0B]sc#C.=C(U7 *@<=}JJSÁ= ]fr;;66 @ܼb;;.OEl3?~{pG_~˽u{e߽wovS! HQ\ endstream endobj 905 0 obj << /Filter /FlateDecode /Length 254 >> stream x33P0P0V53W05W0RH1230T ɹ\ &`A3K  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1P X< Y9_Q?pýٗ#VG3E-M 3&3)2g]48o.'R_oߥ>\ͽPiG׶nms8թW endstream endobj 906 0 obj << /Filter /FlateDecode /Length 210 >> stream x35P0P0T53Q012S @pFr.WXP0b]0 (ɥPRTʥTɥTƥ`ȥ 45KM V8qy(_T|}&wFu5?m{a|އ{̷oow˾֯տK.&van1, \ \ rI endstream endobj 907 0 obj << /Filter /FlateDecode /Length 152 >> stream x35P0P0W53Q062S @, 1s L f 9Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAmh9&B 9b endstream endobj 908 0 obj << /Filter /FlateDecode /Length 217 >> stream x313V0P0T5P01T0RH1230 !U`b`T01 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-xbPa^. ̗5_~k)'(9J&!p,3ޖ]mms&mmbP`rTDX endstream endobj 909 0 obj << /Filter /FlateDecode /Length 214 >> stream x3гP0B] s#C.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O-[؄[5G ̱e[]_ Mة<5mOLOi'zw=Io݈fbP`rTH endstream endobj 910 0 obj << /Filter /FlateDecode /Length 139 >> stream x33V0P0Q53S01S , 1s , b ff@ Y@9'O.}O_T.pK.}*.}gC.}h\nn@n.P9?47XΎEAm B .8m endstream endobj 911 0 obj << /Filter /FlateDecode /Length 229 >> stream x33ֳP0P0R53W01R @c$r*Z, # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j ڤT5> stream x333Q0B]3SK]CC.=C(U7 @=`)'O.}O_T.p4t pV0w˥{w)+*tQP'evڭۣחۦ{ݜ׮ͭU`t/&׿4jWtCB qNX endstream endobj 913 0 obj << /Filter /FlateDecode /Length 183 >> stream x3V0P0S53T4R5TH1230!U`afT`,ɥPRTʥTɥT`ȥ 45KM ƥSW bg颠s)[e} )%;@(M0F6 .WO@.9V endstream endobj 914 0 obj << /Filter /FlateDecode /Length 143 >> stream x33W0P0Uе0T02V5TH1230!U`haT@=@ etU()*M*w pV0w˥{mw)+jtQPxĠ>2 endstream endobj 915 0 obj << /Filter /FlateDecode /Length 222 >> stream x33V0P0U53T03Q02VH1230!U`jiT02L,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(\!]~W|/?SC_]=fޥ_7U:Ї6q1(0qz*r[[` endstream endobj 916 0 obj << /Filter /FlateDecode /Length 176 >> stream x333Q0P0Uе0T0T5TH1230!U`jbT02L,ɥPRTʥTɥTƥ`ȥ 45KM ƥSW bg颠sY yTslW񃡁S! Z$S endstream endobj 917 0 obj << /Filter /FlateDecode /Length 152 >> stream x36гP0P0Uе0T02V5TH1230!U`haT@=@ etU()*M*w pV0w˥{mw)+jtQP[/l`hrT{= endstream endobj 918 0 obj << /Filter /FlateDecode /Length 162 >> stream x363R0B]sSc#C.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O ;p\> stream x333V0P0R53T0P0TH1230 !U`jfT032@,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-sC@F< UCK{%KqMoׯwض=ӎo;:";;1Mm#B nL! endstream endobj 920 0 obj << /Filter /FlateDecode /Length 170 >> stream x333Q0P0U53T03P5TH1230!U`jj*2@.'BIQi*~8P%PS!K4X.}7}gg7 7Fhs~Nin^1Pq߿\Q=>ʾ[V]oS8dH endstream endobj 921 0 obj << /Filter /FlateDecode /Length 174 >> stream x333Q0P0S5 F )\z@A 1s LM fF@5%<=}JJSÁ*=ʸ ]r;;66 @ܼb;;.Owx$.sE]~WU_~_;Ǡ H$ endstream endobj 922 0 obj << /Filter /FlateDecode /Length 161 >> stream x363W0B] CcS]CC.=C(U7 *X@<=}JJSÁ= ]fr;;66@sJsZ<]-9 ->|AS! \J' endstream endobj 923 0 obj << /Filter /FlateDecode /Length 236 >> stream x333T0P0R53T02R @@c$r*̌ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j .3 I~-{˗/l'P\uѵ "y xi2e]S'@ϡq;bL}nƭiCB L endstream endobj 924 0 obj << /Filter /FlateDecode /Length 236 >> stream x333R0P0V53T03P0RH1230 !U`jnT032@,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-\'5OCY:Zef?kF=MM?o?C > stream x313T0P0S53T01R5TH123!U`lfT`,ɥPRTʥTɥT`ȥ 45KM ƥSW bg颠s 'f?|cP`rTB@ endstream endobj 926 0 obj << /Filter /FlateDecode /Length 219 >> stream x333T0P0V53T"#C.= ɹ\ `A3c  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1PY<'y>h|"| 8eRr&>{{l"^kLnp0b.WO@.ARz endstream endobj 927 0 obj << /Filter /FlateDecode /Length 229 >> stream x0ճT0B]3 S]CC.=C(U7 *Z@<=}JJSÁ= ]fr;;66@sJsZ<]ι"Xo_v_+_o_no_߯WQ׵VzǠ4Vb endstream endobj 928 0 obj << /Filter /FlateDecode /Length 222 >> stream x333U0P0V53T03Q0RH1230 !U`fhT032@X,tU()*M*w pVr\r;;66 @ܼb;;.Oyn>jHQENv]_8}_K}߭nozm۲G֭];t07&֯  \ \ΡQ endstream endobj 929 0 obj << /Filter /FlateDecode /Length 196 >> stream x373Q0P0Wе0T07T5TH1230!U`fbT02́,ɥPRTʥTɥTƥ`ȥ 45KM ƥSW bg颠qhd)'G?KCׯ,=z= \ \8fN endstream endobj 930 0 obj << /Filter /FlateDecode /Length 161 >> stream x3P0P53T56U )\z@a 1s ̌ F`M ,ɥPRTʥT˥Tȥ`ȥ 47KM V8qy(';"Cl V_1(0qz*roE, endstream endobj 931 0 obj << /Filter /FlateDecode /Length 236 >> stream x3P0P53T55S0Q5QH1230 !U`fjT052kf`i'O.}O_T.pZ.}B.}gC.}h\nn@n.P9?47ΎEAm'" _w’sY*nk}YW޲/s|a#tu}սkltllt"BB ͧVP endstream endobj 932 0 obj << /Filter /FlateDecode /Length 334 >> stream x3P0P5T5T0T5RH1230 !U`f`T077k (ɥPRTʥT˥Tȥ`ȥ 47KM V8qy(,8!܄Rv yxDm uH 2I<1m<$*R缝EH9,㞳4Bv*fx$sb=9`Ϧ.WO@.+i endstream endobj 933 0 obj << /Filter /FlateDecode /Length 225 >> stream x3P0P53T55S0Q5QH1230 !U`fjT052kf`i'O.}O_T.pZ.}B.}gC.}h\nn@n.P9?47ΎEAmcL[/Ta~5 &T7Kݿ;Vm=bn]vk̜\=> stream x3P0Pе0R53W0TеTH1230 !U`alT00kf`i'O.}O_T.pZ.}B.}gC.}h\nn@n.P9?47ΎEAm5Ȑϭz2Ƿg1ݰmáM'R\=I endstream endobj 935 0 obj << /Filter /FlateDecode /Length 219 >> stream x353V0P5T5P05S @, 1s L  = :yr{*rr{q;8+rDwwvvrllfp;qy(tH˽z]o~ݶ;6wݭmӾztoҍ[U}*uϯf__e{վ[7R~/`aprT)Q@ endstream endobj 936 0 obj << /Filter /FlateDecode /Length 188 >> stream x3V0P0Q5T1S , 1s - Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAmq3,m-RM$yRٷo(\SlbbP`rT ?Z endstream endobj 937 0 obj << /Filter /FlateDecode /Length 171 >> stream x3T0P0Q5T052S , 1s L, @ Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAm^wг̥o$ۻ0@&.WO@.I\I{ endstream endobj 938 0 obj << /Filter /FlateDecode /Length 149 >> stream x323Q0P0Uе0P042S , 1s  @)Y@I'O.}O_T.pJ.}2.}g %hj,`cﭠ q)+jtQP8@VCB F= endstream endobj 939 0 obj << /Filter /FlateDecode /Length 155 >> stream x36гP0B]sc#K#C.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O=ٯ?/zn,^.WO@.nEQ endstream endobj 940 0 obj << /Filter /FlateDecode /Length 175 >> stream x3T0P0Q5P05R0VH1230 !U`baT032L,ɥPRTʥTɥTƥ\r;;66 @ܼb;;.O$8*'sl_~ L\ \JZ endstream endobj 941 0 obj << /Filter /FlateDecode /Length 221 >> stream x33W0P0T5T05U0VH1230 !U`jbT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-,$uC[ u0_0RK_c_Vwm7L;;lNصki.xĠNs endstream endobj 942 0 obj << /Filter /FlateDecode /Length 227 >> stream x333U0P0Q5T0P02QH1230!U`jbT02@.'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠qAnDm@_ct?~we_U+¿ȥwMϾc0=Mַq>\oHXĠja endstream endobj 943 0 obj << /Filter /FlateDecode /Length 158 >> stream x333T0P04P5P0S @@c$r*YA C.'BIQi*~8P)PS!K4X.}7}gg7 7F[A(㜟SW bg颠?0e{:AS! _> endstream endobj 944 0 obj << /Filter /FlateDecode /Length 235 >> stream x353R0P0T5T05P0VH1230 !U`biT032@X,ɥPRTʥTɥTƥ\r;;66 @ܼb;;.O }\*M-r͇j_"濗jk-:ӖUPG⠎† L9$_td^OS3vg̹]vk \ \CMB endstream endobj 945 0 obj << /Filter /FlateDecode /Length 244 >> stream x33W0P0T5T05W0VH1230 !U`jfT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-'z`CskZ:Hh"/Kw7&inzy9 19oogzc0ݴcffVF.WO@.kS endstream endobj 946 0 obj << /Filter /FlateDecode /Length 141 >> stream x323U0P0Uе0P042S , 1s  @)Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAm|B = endstream endobj 947 0 obj << /Filter /FlateDecode /Length 250 >> stream x37׳T0P0Vе0T072R @c$r*,L c j2K:yr{*rUr{q;8+9.@Sc݀}o]s~Nin^1P5l+y.d4h>akK^W &ׂ/MY'G]?k.dۡhMѢ[nmp07NSCB _H endstream endobj 948 0 obj << /Filter /FlateDecode /Length 238 >> stream x353S0P0R57T052R @c$r*̍ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j H4 T_"/_a↢ck>Iz"uz#nvv6nk3 \ \kU endstream endobj 949 0 obj << /Filter /FlateDecode /Length 184 >> stream x353S0P0V57T052S , 1s L @1Y@I'O.}O_T.pJ.}2.}g  45KM V8qy(-> stream x5LP յp&K{ a"Ƙ`M4|4j(z=I"hrkt+3Td֊HlF=u'./J\quΔ~ͫDS,qZ.D " endstream endobj 951 0 obj << /Filter /FlateDecode /Length 215 >> stream x353V0P0T55Q05T0RH1230 !U`j`T052 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-\ !~RI/hro2}]?O"\zݥ]w+:w2lHV.WO@.cI endstream endobj 952 0 obj << /Filter /FlateDecode /Length 215 >> stream x353S0P0R57T052R @c$r*̍ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j H4 T{½&U/w_e-ۻFT4{b>  )\=]K endstream endobj 953 0 obj << /Filter /FlateDecode /Length 157 >> stream x353S0PP57T062S , 1s  @Y@I'O.}O_T.pJ.}2.}g  45KM V8qy(-pέbDŽ_߿.WO@.i?| endstream endobj 954 0 obj << /Filter /FlateDecode /Length 241 >> stream x353S0P0R57T052R @c$r*̍ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j qz0?E}WV}ۥEnHeo"בde/_r?Pis'H1p.WO@.Z endstream endobj 955 0 obj << /Filter /FlateDecode /Length 239 >> stream x353S0P0V57T05R0RH1230 !U`biT072@,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(- { ˗/_ Ppo{}_U];ևKo}Hhp}bDxdŘHxDX\=Z< endstream endobj 956 0 obj << /Filter /FlateDecode /Length 188 >> stream x353S0P0T57T052S , 1s L @Y@I'O.}O_T.pJ.}2.}g  45KM V8qy(-&,Ͽ3!b~~L \ \eS endstream endobj 957 0 obj << /Filter /FlateDecode /Length 218 >> stream x353S0P0R57T052S , 1s L @Y@I'O.}O_T.pJ.}2.}g  45KM V8qy(fk}{oߨO|ؾ<6>ܓ}??v%> stream x32U0P0W54P02S , 1s  @9Y@I'O.}O_T.pJ.}2.}gC.}h\. 1!B #F endstream endobj 959 0 obj << /Filter /FlateDecode /Length 214 >> stream x353S0P0R57T052R @c$r*X̍ 570K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j 8s(|g ?_??|w?m0}6-_wun٥7u^l&ƣ;[~ endstream endobj 962 0 obj << /Length 1007 /Filter /FlateDecode >> stream xڍUYo6~DKH>@ 4}e*KM;CR>Rc3C OxbYbVIu0I ~𨗁bvvsw g2˓S}.ٍi&$4S*'_;nNEAL(k bLۓ\o;BsTେLZ RPn-^'?/wLT%K"obt q[reF"eZn HmstST  ܹCҖ$SqeB0d􏴐 IUv(۩Gʐ?4c@c)ja]Qq|FwZ^M0 >pǻgA:BЂU{ 纩XlXSf uPu?jp2 p3)dqIy΃Spٍ*Y&^:KKP4!#oHRՑ~6B)Qf,wm\#-s;u!(q n=r!acY~[C9[*D{b)҂Đu`"rb@Hom"%|qp-kxzMT6GK .j7tuh弹o x]aU endstream endobj 968 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/home/moreno/src/queueing/doc/qn_closed_multi_cs.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 969 0 R /BBox [0 0 201 148] /Resources << /ProcSet [ /PDF /Text ] /ExtGState << /R7 970 0 R >>/Font << /R8 971 0 R>> >> /Length 1258 /Filter /FlateDecode >> stream xWK5- :.}%")IvM J#%{kz&=ì&e_=I}|ZN۠]{DžB:[Z'\Q|&*N))iFg79\2UbhsN 6@)Rl!ѽˡa|Zz2ƫHaDV#&*:m~gBFhlb,tU -^ GoC6+ۙ) F{H@ie0U;mX k̽ȽIdP*GPLyZ%;bTGf,I,U͉,ϩ\^n"ؕ1!Q1]i' U͙ҮR}{z} O䡆ТaSjQvc`NE=+jBNP[y OOri6z`_Z *ԃO/wF|ˇ Mqʡɲib_XӛNzpBy[t endstream endobj 973 0 obj << /Filter /FlateDecode /Subtype /Type1C /Length 1873 >> stream xT{PSW$,d`T][-E\+e|R#BC_P B$@ȕ69!% J VGjRweۙs;{vf}1o|RRfߡq:ȇ^)ff"ym "GQ:Ǹ8#wVxw*@.Z:+܌?,Kek3hsC+Kfh>a[rH [1l ǖcX[^cñb:[\D\qƹQbnw+o;>!!bBd ?n83((AZ(hj[jupmwB!$d{9ȭʵP(qwCh ݡKѬo~e@7<΍4͡sQ41BO3f)RSVk : tGblw>1^xj 4)6n贝`eqHXVot [B]A%Z3Ga9,2hj55D&ns|G|=7%f (TiYyWW5BM?TYc ]BOO̰vz3>Ӝ E;j2MZJV}uq |iECe# Eihu:m @G詢 &%pKK!ٔ,VG[l̵\mD$]P"Q0U#9 <[{l @eQWrJuUgΉI fҨ>_}DAf 8&Yq^_P0QZWbAJ6fv s'9on;pr<]BHAօo]\ĐyJ#b >f<Bt+XG"}`1WktSZZmf`*<̖gDWoJ9!;Rj-i氝W_HCb6/[`KE2=|7˓ϙFS*:x`~zGtM>4F\.` ģ漪%i'G22gώ0&;solb&|A2CU~sn>qC=Ё-u26| +v#¿ FK-zjx0iNlՈ8p/JZݡ>g> stream xڍUMs0Wp3AF_ [ݺΤMkwz@lŦ1NߕV$zgz<,ǂ,R!h&u*'6'?LEȏtTb 7C:$_3 X\~o6voy|m%j1a_D"K!UJWge|'?^[#Y,aW"4΋;1! hrFR*vE51)1 ֏vf_0Xm n߅[w ,MLZCהu6H%vuk@*ruj-. £nnx}YJ!w:3I*(,YU[]°W5Oyyx(Z[-|,-,2vVҡat Th],ea]~k6!#M]kIEV`d~FN?]ՠXRգ:]^L^QKY{1+$\wGIg$N+ģ :!?~hʄH/XA#ޣR71B`މ^58$׾`6A,,Mwl,7:`BlK6 nmXG{z =f\C_K_]IU;\xѳ#«5̓keC#x)~$#@_c]~sVM$o<ܒ aPBᎼ y7҅K _'bX-)ÿ`="fb{ endstream endobj 981 0 obj << /Length 1086 /Filter /FlateDecode >> stream xڍWMo8W(T h"M@6VkԵ)_3J%1#rp@$Q&#L=|ظ_śF E&3_# 켖.~ed:3$yYІíw8Kv"xXuM/x:oxlag#OHJJ!Cm3f:i,16D!5S=%*7aZA2'<ڐo:J@ D! hNsRVGˬ@ѠF<ܗ5D6`g`tK'8NǤtT!zpjMha^!daW$茔դ\&ʼnm5SW%f~U*weCxt%j+ ː*'6MJe8Ml`:8TyxAVtkw(7Gci}B&9U63CEIbcycJj bpfuulrF ^v}\BW@ pUAtD7B#(ۑX j hV/ߌ| dE7FHtPcmjwqH+/&Lr"'GE@wय़z^jO^=&^0__M jR#=#8>7*)ͣtk>~oriS7?]׌.Q"DƷ)_NZԱmY9e`-('3)֣4RVA:%V w ڻ2YRC`x &==[Ⱥ߳Tg+5 'tғ:b_Hח҅d4H"UJ'hEOi:< c? endstream endobj 985 0 obj << /Length 49 /Filter /FlateDecode >> stream x3T0BCKscc=K \.hQeUgbl*OS endstream endobj 999 0 obj << /Length 3070 /Filter /FlateDecode >> stream xڥY[o8~0e RxS&i:udg1 MȒ+m9$eˎ|߹ё!#ybM/F b{g7/N.Qbf>&IF#M~yfI2S95Q0* JH(~()>4s[rj\ba7&2~a*+b"g׼ߎ*WEJ6ҩX?:~9"ʊ JʬxhƷG4j~VTG1ڮmhmLU$I r #Q,(<2lH&yU婨r{u5oqF7mV[{^奵5,͑Fݲ 8/)TDVQ t}:bA2[y'F Z-.WDM SEuqO|;Ĝp4lΣ߈$"ҾI-6&h˓dVIUߝ+K5,Bw:`GPu|'}`)"8je2 ,",zgà 4fs_[[6аV9Ym>-&o[{;7B2 "X".6ORځ*qM|tV&hfr_`[ϫzGR"+dmUsWպo]?4]6C`[܂#ep\xaSAKDvx6W.55ʳv5nm ~ _&Y-`{HlAC鞓?o4Y.dE6ͫ&*lD&C$gmrWh$\=qQ5v.>Mֽr)-9RuBxt6`(U}ۨڽuӂ׃ʥNۙ#ބ;OpG*bO)o#j%%RbOpagJ@H)7$="S%Q!FCKHIA!ݽl6Msla!3sL"॓{l+ 2/'7"ܛn_[S$ܨ*5pC;T `O7:wnANg2M4mZ6- <o&!]maaG^S#O5d Xcu&zr&:{^M.pفnˀH&aD8Sׇ{O ҥǓk *y!uПs~DYtucd߾=^@YBΧ^Y.g.(ym27~ŋb^țBBAMs+}XWuY'Wn""+@D#p ]nzq;wҩxR)BMV^*Mbe7\ LJU#:dQpJvUQnƉ[W~qObH#?ssɭ5wNݥ7Э ij6Z:CJ&LA:A!*'|t?4)<MnE!AR Q*< -ѸQ8DI,@z( > *4ies kUbZ&o {5|Htm(1IVfwv%hJ6o# ^ U y> stream xڽZ[w6~ϯ4qOMikm}eb#*IM?~g0DҤٓ|3bKgFI;[Q3b;/CK:6},?ۙ.Ɓ_.۞w8HPP :.IcUrK#,Ws (p]D9~"r-&* u/4^ͲvPϩJ^^mYQ4,ڞhzxeU_X b S495keحbʩl55ޜ>UYaڽu8m9)eѷ(W0uY?(e]&HĊ\TG&t$i>wxF ?uitU g.bjl.zVщ3Lb8b.A8HX@%4Sc%ݴ4MylhXVSHDҰ˦~uzz[H_H }_f N( -e-?vtYR'LFDHeOUvfd clqpmE!]UʉD>XuæLZabhNVuU7\ѕܡ"/K_e_j~S|&> _pמS: &B I%ܑsQ7$0d$hz31 n|p2z*z^Oް#tS,_M~狲iHћ*[fklgiaAw&ZF Lche EH"8 T7aYM4Ʋzpta(s7ыMR5|_p Qr>}4_p BD+|l,:[B#o |#̔ ͱX(Cqy8r*6'݆ev6pY5nMJ8D >eYtV ZoG} c[33.IE+91Tx82WpZG9}ޕ n83.цSfC{ƇJNbW;d;bu\EE\SvFO5_W]|ԫÄq`$I8ƙG d #%۸CЄHX, X%vc}QG?z\}BRF~|N-*1)R8bc@ 5v#>JܘIujibSͬNa$0PdC_C2)P`G̤18Fp|?o©%̦$ tS*UMaYMcDi}֞JϏaGv̊u>y@<۲|=ŭޖjY7hx<0?PŦ0mU,# H(I0M.gp#b@J*! p b\O ұSwIjcӖgj_DSZ='Wk8q6y0b,solyq,s86/3ߊuTw@<!X~`/}g)C>y`,;p4Vp>OCF %.MUH{lf6s8ePF\R0}?Ÿ9oniɚ5Mݓ|:ה!Cm8,;uV޶hghx0t1o!r*3$da2RHS<1N==SLώ H: J),v勪wqVn0<@u!!RGix!}$)ۻyImazQ䋦rL=B}c7Sn38N=tQǢ;cp 0B`|E %}:?\\j<1넿_*H( N@#V!Dshͯ}(ɰ0Q>^x Bv?LTpe|{:?\ q+ZU:~Py$ŸI&w @!3 LO$ *TA `cl=80$7S-i(p~,d F J{J`Е$@o"+۟I0oAe^L?]%;r<w+847vgN~zF.hQ,o2hXFNB^]owE9Ƴu/rh\zsW$ckzIA~hCqbvIL"hwa ! endstream endobj 1034 0 obj << /Length 338 /Filter /FlateDecode >> stream xڍIk0:JP3ڕcW(-!pϯd;mڦ,3i{A8DО4zBڟ ;GECD*JJWJQc\kCqUWQa\zzދAvS|i)i*g\v@[cMj>-'{ EŸ*5.MEUSt[6`_|dqp{QۂӬ= {}&m]3`CD@h*'q=iA8|4(W3'^!=>;> stream x[koH_o`a5,dn$w8A@LY8ojJ+<"0l6OWWWfBQ|o(o*\ER(XhP6E VldTK*`#jm/*Wej|a . C˱- hx])La/Uhg ڈ gU80Lqb^p3zJ^lR]'E%=D 6h̩H"I$bb$"P#!2 5DD8cYlљp$4vɢgc:&(> "{NDJ1v\44@@ )Ta /~OSpU `wW ՇԷ%(–0T iOCov& YGlV%2u0b8Ψqk% c}.F"zP!MP+Maw!PTA~׺n85RPќrihڮ-Z9 ]NXoo@d@muAWpk޷U泣Q3/|E]tQHýɼihO1V?+'v/gGkf?GY?9,Ia15ܚͼ؅-M{KMQ}icU?zYq6fEQxo'MzvRO*>ysPUxSœzW7 7?m w=۬?Tehv4~,0Ѵ犽pѡ&v)i^(>a^״ 4X?[3^5,`j^|QOƣGӏXo9q|'FhjtU/qͶ_XY_s :2ۿ/U=GkmV%>odJ:M<;>-Y2mBcG]\4Xˈ2!zWb߭Wx8mdk6Pb:sV5$V?=~`߀M+W}xHu{$ɔ 6_: 't| 7\7| mĕ \ ueL o#>:]w[8J[u't #W3pu-2vHpewZWui(?8m|hzuXϚ۹7cXqe5nS7-zPQ L7cAhƲ&#UѡQ5bmYo"% J6#]ܺa\n3.#@4\F0Qhry61,Sr@ec `.ge>#`g}Fi&0w3ð=# t7@2g V:gP22RBFBFH43Ef6!#`&f .bFkRŌ@bSç<4pJ9V uIJb4 CFQŨsTBj%ՔzKEfSթ .?Par܃ܔܥܶ44'4084AI4RZ4ck4t|44444ɴ4ڴnf/$[5 f*q%EXwn҈ &#?%:.~xQzEfbyܢs+-*<ܢsV[^ynfEەV[_ynaEǕV[<7SW[Yyn1vŸ疁2s@(e]|eLh"e2};xn(2 eL/edLi[ԣݾV`mLaxJEF5r@u^bٴCu<;?$Z\Iq_׀Z`Nk`IK/_yq9 xu ԧC6s6"> stream x3T0BCKscc=K \.hQeUgbl*OS endstream endobj 1045 0 obj << /Length 2784 /Filter /FlateDecode >> stream xڍ]6=oJzOIoҠ^qރV-"Eڽ"Cr83WU4 KYWA  y^9VqQv,C:_&[WIY|畈M03wUFq.nͷ]R.˓aȂ{'Oiwi;(ή>BʀE$q?;z-~v:)g굇Ӎm^J7ͣU? ;;5+)< 7ovvv%!JaI~IȒ&ܬr & 3~: e6 2l[؋̳孱CoAXHFݎ/&B ,f֭SGݒpЦj3 VCD6dCTat3Avc^W5XA_SR$ c 8x8h`8aP0!ao(;\)A^<wpzؒaȃ0H,wCir# ?LZb2TjQӢ"->vv}ie`ਂͧS`e"W[m;ղtW/|5lc/νSFdC-. kHC- <ցWOwgбB%x{@¬,0#V3II"؏U_ɪ32A.y48q<@cVO(|ک}u/s!ؑ]l2x2Nv`dѼ:KC42f"49a@*'7"A *D }yiWGVV+o#I+wIҸ0IesB2!$=xVOsUӁ|1V1xBq3+;Ŋmƣ<ǡJe?|@]I4}BM(t7  <A'iN,J4¸a(m7ՌLz龧pb4d')\> o" ~%FrtSkȜX|/ 3velw4Kx$ IC">+=|"3W 9kѵAE2t,+##πɳ SHݸ2V1afz+Q4kNL2u`kNI"*=e,hQxo"$H0.9b &Yt|V?3@&")Cg{eVKo;.jiP7zI M z('VSY{Zcdpo5s6dr&eI'U+iy*ŧDh=^fIwQ9fl:v^qy43pH9-fPyy" yx+KɊx"⑩+ةd,  hE'8j%&{q3M8]` xnbs+>FriTks]*"ߗ_{=@.?`rҸ%tjplf1d#<ucW?V湫E9|zՀ*2SpoOv)wʈI ߛ'/(:6;{J`\tE"\no:р;H o%fPUpv., MX:jot;)t/,m<]q쪕%;绒5_ g#; R^RdTqS<9PhzӣI sf.iJr Te[`ED\ |<}c V8j^W(Vwu+{l>86#5I/_: ?PΊJé\4Ji8S$a^j8z1fvFGV́R_j'lovɨD)B`o" wwU=@rdj $Ceƅ%k_ss'HTJ=gDtUkJN~m.ha/xɭR<8".<22/nn0ai|#Q+kJ)ZOfAvI o!l +%{xn̔G"8@ *XMRT\\4[S cp*';(B,j0D_  f(72Un(8 t=I/]Zz9Ne"KNDSb.rr4>; L[w%|w EEj`!j[l<vFL>Yny0Nj!lB߲Q{c}&:+H}S[?+ endstream endobj 1048 0 obj << /Length 2521 /Filter /FlateDecode >> stream xڍ]s8}~O* sUs5nAAfKv*UAjZn9ZpSj[$< V<ӛH6`/t",~JZ;ȳ٦-$"|)ݓ7xGB8srC{G;iLpr$okyyMH7vZ(yyV+6pY]AHดw#퇯*|N xd@;Cinͨg0֧5/\8 qlHonz's4aN|eP͟U-_'NϽ zga"Ws. S{ wvXRmTT ܃:zt"a Qvy9 0d~RH \S8 u/ދp(:b+ :`A3sa:Y[3'0=1tzb\O Gxv09cQIK]!"e;.2aSܜxli,мVQ:Ff/HA<"^à8P,2 ,jj5Ð5 5zAaVO i ?ld9p+tazGc1VIe!Qя3gaZН 唍DzLJoXC9K3}0APbrYcԝ7c'Pg y@"4bރ(PM` H]L%MYq^K"8v8+b|P_d2@F XvEB|Ll֬{!쳨$R8d|-::O)F"W0 0dҰ,.p-eZoe'X&hgV2h?P[Bf2X8Ɛzmr\Ͼ8AwJT>jڄjΕtEB#O4#M> uJ!vH%(q{_9y_3Ĵ^^5\jn ,h+^]ϙ+c:379P{ wm5Vf8W~:_"H0, 1M[7" 'ۘ+ 0L/a!`W:9??n+V3`SO&$8P݆l[<ăglj0tI6 H_?N#ѿZ1>[#͟kHf$ĩaWgZOY\l4 eUMj^W#H`'=- Ҡ=SFJ'6e"-{@g ۛ/a@L 5;jo(uV6_?fDq]);G̟>ȫ7wn܊ l]\RhX>0Աs}N> stream xڍY[oܺ~ϯ0ˑWJj4'Ah K\]3 R3ù\g."<.Y(o"«g-I.Lx=,.8.vY`~(xG|߼ă8x/wo_aLo^_^wA^gog)Ƙ>Mۣ%QP7n-q4okl9]c%`f켄c?'TJ~ѳD{ Dz^$`<ҞQF#$,X;vt/L4l5iC[4<΂ T|/>(N@+GofwV0*wӸžkHTSbiT :b~{Hlg{uYHcRLBƠWVuzRQl]_Cg96Y|74 @\uSMC}!b8 e94qTHwB9uBdHL.Nb+CAQ&O0uNVHl.qi0+4:|{^C;N7-ʱZu8 9eR,Ճ8m--(Q!f:ZXv85W'4hr~g07w8 24?`YETܑE-cŠTdyCҨ4W4yΆIe ),{ UCMʲZ>p)K@ )џp#7 GripdEIf %H\0QeW|cpR8 ֧+cJ+pwkid+IZ;jt{˨sJ`6-DX=SW^PXY)\< ӀkV%X: &%ZI~*;a?Q7RlD8E[(m/JM蟐goaHhI.Hq;&GY Q@v:xBd%'&itJ?ͶGlT_4<@_m\X|h $t LPJ[$p *oF⊑o!Ѭfxv1) RM$XwU(X?i Ce<8e^N=t,tҜs"He{JN^Yu̢r5Zm%';mzHx~;o5ƶ:v"9OY|<x +(n-PUɷ7Z.5LK"_?.sUUe0@'M4esH}y FDl[w! fx@<8pT%lS1AAJZ5+6;)X4x*)iUZc61f)L“xS0;_X՛z3V~!Hgh3}3%ǠX{< DLзUv~;u6pc} IpJ$f"y|Z4_1΍{<,로ZoPzE5H͍;),Ҕbnau$Q ۓFɣ67/ޮ?i0[HN5ךɏ,T|gubw^N菫$8;,J$֜= ȏpB̖O =Tֶ~ޓx$y+'v)E|ﯗ$ ]ܛB O:̬dGW(N\kApS#G*(FBixf1/' 0*=#x`3h@Tg){ lxUP@o6|RRc>7LBOM+ ~> stream xڍˎ>_aed`ei3.AAh=ԋvw>,e6xM~ .q`˲6OSWT?e} AdlwzȒ71URPJ5鶻$ϣmRDCT6ɣ_f^V2^#W;AhD}ӢVZAe4R6L#:bǞQϽ;Y9Z/g8hJ{1㣩M{LX)ifk:WQy Vcj459yaUv@+QV(gjQzH>=[n0 $O8'PMjJ7Z3|p!=-_19:,ǡ?SPd=U!vw8[ YkmA]'PGːz+&mqԖn  YgWxԠJ*1KXo*3-Qtj;FPZϓښ^AˑGˑ0~ ܶhhm:5v_SqFz4)%qR-]?&H0̍1,[aYɎAZ:F,̻)vkv%1"auʚUPR&w %?'yd $0,LCYdR< Bћ5`ʬWHuX+p(ᅮ貈i6 `^U7\OQ G= Ef:{`aMϞ"N yy#7!KtKj`͕">/?[kB/G/ !w 5o\WQԽ&Y@;Ҕ#2hwZEoxMgޥI879g(Kn?r̽Hq朂e0S9pD^%ICExʲz9=EP&o=VtF۷cH~5m.E,BZ`\iz&L8 ixG3Y0tzw/QM@Q#6ȮpܔAʫ-tD?W/žiyVim7Z|$LXت؊U!~ &+Lc~fju`JkO+8f0Vc @YZAk/hGbw̵g Z%X/ YaeU(LP2a7{x:)utYZC$"1RvM RoC}z%Z_R]tBaP,:IޝY|5^8Gi=_a):LQIDNܙWh }K֗}ZF33>s칼b#@ $,ggbuӘ2 ᅑ%TDБ$1Y5Uf_<1יw0 ^-zý>Cj.`UG DW7$4Wi % 7NnӺ$ex>;5̚HZrɁ7Nn1 iKG HPj:NGF&5BC}uck.oz7\$3ߙK2=u0;_e$d4x Qo0$=911 [lF;4JS'aҋ{}ֈB튷ŏT2[( N*yCr֙h8'jj 1- 8BЙ؊GTi@>Eic`0^l-'[I 2b 6mwOA{w)i[)qzӫ, Q-"\]>[4`4Gb{zPŲz\>ܕq:p.kKi|1z׮LV8_]9OeՏ|qӘKL$땕2O뒎T^ [ML2^; endstream endobj 1061 0 obj << /Length 2973 /Filter /FlateDecode >> stream xڍZ[ۺ~ϯXI Įu9A 8H6EOV..)ew;7R- "r8Ùow;vwEnYyWuovD5OwM,|`<˯y~ﶇ!{8DMRFMȢO~ S˗ _8Kpχ7's[bݾ̶q~CW!Oe4LxC.50WT7S/dlPwqݗ&Np\:/q#v446pbtnǰlDzrAF&4? hPDC/w`&S 8{qܪ]Ƽz2ldsa%"m <{3_PJ%ڬ]1cbb6O._ۃrz;5.VѴb&~i<0'  RY G)#a :Y'-|,%H8>Y~(>f3 <>ۮмáK[G&ize#77v|*$Z$Tqɍh 3N&K&ː ǽvqW{VKc% =olPK}Hvp^ʣR"bXRp" >>W p 'A7q=aeeT: ֆ;pU΂iv~~6a6d+Cv4FWL$|%\)٨)[-rN {vQnDfzz2q\)߂[&z;Ne鄕"v_Xziϧ'i C^ͣDG%qz)߲aM:GrXNЛ)1%ͥ*"i!f015 4̂N)q+> stream xڍYYo~_ȓ ;}ͅ v7 恖cKJEj+;,bWß:THc.&}:pӟ)w>cWpY=4EU|Ҳ:E\έp $?%_E)u<NevTi>t}w*EOfvKhvSN5Ϣidj;zZe ^IMf ^m<ԸgBX4e3еJ*gǻĆ5*q|ee];wev2j(]K2N$ u,$=֏6lj={tRNQ{@H$Z2@]ty(eGPW|Eƙ;2⳼2MjQKߋ,vxEJlll{Y c9悉zj?pkǖP~:QU ޡU*AI0#O#l+Lw6q M(DB-eR&m [7^/׾}|ɉ/)HL@Gv1?g̔|?~ xc"Ւ}6 pJ%&0 O3跛#lvNޯB?jG7"WS DigS!rZv&iYŠE33iD$xaCpi-4\s ٧}VCbwu؇x1eɲl|n]Se΋wq4eqT9Y).R*|vz@Uwg,Q;wN {t'>!Z \۟w淆t.h8[) 4}\vL &.Vgk{ʵ8IM32B>G DӵH7f ,{92%Gb{'G6xq%97Y(AA~_3# bŒĎ.)5&E>R c^rG2oԈJxKpi8/HֲP'P.R//mzطL&T%ʋD#k A]<'I ٰ°`u^2Ȗk{[;'@E3i_o`;WMa&Ӓkra̢W0EО\[N84 P:^Y)WͲ8C 5݃& haê+ƌdOؾ]pU%9l C+ Czʙr'=&h' UL8ّkKO˔QB= i79a{ƒ/ CR&6!0|ZY/EF h-%J[$`) jb*pn?a<4:[mU3z /X?_BمŁ[n+N}Ə4=Ujq^ ꮅ`6+ltS=oOVPnДa=Wh[t8 12 fRh^qyodwݽ45ao5L=nnUCY-*ݦc+ӵ #I'Sl0r vT [_[,LlqEq(XV b/XNTq%ɒ$E LO{*f&s[EÎ(>#Vنn :/L:tS5k&)e.ZL42X\Kt|tk\M >.{@x)|D"'j2J[[[%_ah b^+Cq; MO o u}ꀱN>)MO&j+gj%LZ(Tȅ;}UTfNerG UCP|r)`…$D')wm5 uGlVT t*S3Yk~ؤ&܍=dǝQxJB2HRGҷpui \֌_XzTK)^ [!-÷27>n)BQW5ؐ% eK*a$lurY\k1V#O)傀/G- QDߓlta_4NGĵ{=5N~<1(ijR˻brLau^ˍa@w,.sLo2A&{6Y \)oG ˊjkZ,zgk olK}F Ch1Nj 'eM{//ic̱?gk~>ÇZF; J6b_Hwoը6  iVA endstream endobj 1069 0 obj << /Length 2721 /Filter /FlateDecode >> stream xڍYKoϯ0rwԣ՝=y7 {29MX-Rxߧ^([, XdH_U?}uPWem:SDW 0n"Eq/u__'\7>mdY><ϷwL>mhy$PRr?knouz۩ΝM^p{jdɱLp HgRwokKRldY׌i&g9@%W y l li~`U2ȸVzcV+g!>:GoZ<]Omlkyh DBzi9Ywg;/cH#b ;&> |fT&Kdb/r|γRe kȌ50َ33dqAWQk|X"?Se/Pn8ґgk&beb}B_7d 7yk7g]b9,10a/|常 g=1p8zwY/,kEvl v=V!`#d>wPg|KFQf#gQ 4Ou.KQz88?m70Ҥ G-2Cc9}K5 w8llce -D~f&ǎ_dtb :#Ĩf> ,H?H Hg?d/L@eƳ+XXkx rH|tLqg, (]iXb 6Hк`0eK+uƎkW}C49c { sɵ:VHha v#_):ةa&mza#Z`֜gܛ[ d;s.7n {'^Z9)^[r;e70YY/E2[aL=ʌqܗKꂅ7+œ3.M$._LXYZ@6z-hco8JK:2`q$O` E|Q\.)B^b#ۓpݘ.U\B2ZvAy`CQOn u %s)#e%j+ -#l B8ϕf<ƥO=g_ß^6kJ3VC:Kr+,8_Ge998A i\g%[NGs%۩فeK~|m( rx0ћ;3N]̣$E,3L0!ON/{\TbK,EʸPɱF"DS2 CL}C㳣Wq o|\K>n n-s5:Osكg C n^CpPrËXv!*eٙUkfJ{йa3_R ||g aH% ̹H0"4 lZc鴊4?w\9/D",vIe hJ*u yuQLJN.2)L]rYvdR#4S a)gaN)Vz ajtOze}ܰg-DY#5!#\".,=Ѝw9GOSܟ;:%/ilZ؆P? c0L}1)'G%^s%|1鮔2`43O% W<8)؉c-pb'^u\2OW9ֿX>/1LCG=goG@}KsfdK ߅cecq|3VŪy2/ѐS|.C6UżnlS0m~C=ODmh~Q{{pa8f.d֋^Yh8Et 1TA׎3 <_s*'5y*^:BqlK%k(y-T!|* CZD$(20 FZ^V/.TM** wЯ &}<ci>ZT|}Zj~3t VZ\ &[Z* C(,DK0䌱-Um<\p ?$ endstream endobj 1073 0 obj << /Length 2830 /Filter /FlateDecode >> stream xڍ˒۸RU—D$=MQ$z b4 +rQGw(QnIEP ^ &+70(GQDA`_ a9llj^@7!M>̓n-/e~|S7++&qV_?6-R\62ϓIGA28i aY2CRF`$6>l5P)^HsE'ke7P?YM3^k3ls(Ռx.yfQ|bLlOBw!X9va_&<-*I*w#^'~hƶ"eV0\{MKTުp 4&/z7;GE ZYOn7^ұyd ~nA^'e- (E-'kz='9fԿ6$KYc)$\2!`$yv>Y WT`K$|%ёʞ}Lv+oZ  L(2 (p–D +",zEtyHTOfׇtV4K^."Mcg 0R<<1Yn ww<+r0ys)XqΏ_f..DyU,B vz _{rC.MOښ9g)Yv6 h 9^P}rUoR-bǨ_Qԇ#W-I!8~BtX>$bUɿ yQh%Dc!24+ =C";N%1FOg5I@ufl'\}Jɭzc `p=xQ+4 HVl9-E ꛂYctHd}c[U%v "0 QC6@-v77mRLUj LX&I-2ATh K,G..ػ+I&RM!!_XJa~ZM~Ȃ>'{Po [ +Gymĵ^dtΚsGc^@9轆5G=|)ݧzlRDq"ƹm7z" +ja({:ً[d{% f>ю^@\;Hz >+OCQ} Ώ+pZ}` |#kbEC4xaM,{J+$N ]ry=T"(e,z&GB!嶏kO+U/'e1EfZ2c-t4W%\f4C$!;b'Y+%-X+  D@ Om`q"qzNdd~Ng8q2@hgqZ8 ) WބHq=n10ݐLנ- =jcܞR)xiF( V5<5ⷣdrd* xSW8ddn٤î_Z3Dt8|gQ VZR|]UX{7B WM8erԙFP&;(M<X(:!YD}B9 `dxa z ].Gש zsvBJQ456r5xF`(\YO3[\-6xZiI&K O\ub^'A^X`I :;"Qw%?R„i@Pzf(m9mrCA¦tu"q1EVǚìdRrDѣxr՗ck2͢*M+2]M!M ޵VΩ,Xx4xob&UvJZ˨jwM\Zqk7TKm|=Tɺo{Nzs}aQhWAI7t@i;N` V<~AkI@aL2Xϗ[[A^\bh_x*4lWK ΅_LR:zyn1VN obҼb?f@TW)}b;Qy-l8 1s| endstream endobj 1077 0 obj << /Length 2858 /Filter /FlateDecode >> stream xڍ]oܸ=¸+JZiշ\ (z}%>();_]ZpΪMiz_f}=WJv 0zxߗqn!_v".Mgd7|z?_x 7~}sSʒLoWo 9b+ݫ4[>Ҷя%y;fo>NvNwO'cڜd6)~ri ;Qdf~U6t֣.!Vd8b1TzYVSȣoHw_0`d0a* }3;x,ߧ[YgZPr$/@,g~2YX܇"2Ԛ| V"*Ģ[7ל{񷎱m<{?lݵ5Cxrh uDWCS?x#?G05- [D̢rZ ,ͦ#*r=3u@3*ЌpVW'{=d*.Sdj g+80pBM0^L2ˀO Pҙcp ΌAw:I vX/ `u!vbk})F0"əȻ#RZFgc]+oJ,Ŏp0T;K4f]0h03>bw*u>Hlڵ! :rY?6򈻟e7@;/_wI.eJ<* NOn) ]y5}{Iː25ʔŽomOvY# )dS3II$؊ VZ՟q'vdb//D?Zma>Op2&NM^۠@|}!r !g18 xu^^%^$> نyCzԃ?=0,t YLI*HNgmvzpd;f#i UUT U #b8 p@$Ohm١*'2dikk|75gv v[[ dd]]nwỊz\iO8' @=,&^DXtH@G/(2HGEM0aI/-UTTEU!)'&S!\<*0PBu5CS@D{ 6i J8,Ts>׆HGЍOOj&d3+]T&KP`>i'LPI(H_9Y)ҐDBVjI.xkaa a9QQNB?h}d59pb*-÷WtQ_:'VE!Y+gٞ_!yI[%gf:nϱ%8n|_vm0Bdlaa"˰I pCS2hmxr)WHWȞ? p OV;hy42>$yPuw4*y)ogh$<0Dy^z5k,7?C*=520CY6Zԃ癔t-0KJ+A*%%(b^c%YzŒ~`2BG_Q (Tcci2aQH OGo8PEG9"3~hAVII`2d&UnC0m;Co1}cUuT}<űf3K.ߑG3[APR <\d*A\NF4/OnLeb %\.Q+|Q !pm5Zq hiZܜK7 f= WX9Iqg>v|e)8#sx&%_,/_~2en𰡗\8D(⦩ugih8 U> 0C N8@̅P^PWt\'J$'C, *N7.0z PoӀdώGiw|ߨEl: 26|$}JƐS$l!zf. \&ԕ˒,'A?$KB_zay@$a UPs;|~ob@3vJB i(-*N\7;we &wgGU՜UsP[jx<ўX=A?L#yPaG,Iౄ:DJ?.L~]mH`7#н6`Iw/ʸnNֿ4G|xr$͟NaEG%Z7sZPZ:o?Obo5ު˖Ї| endstream endobj 1082 0 obj << /Length 2597 /Filter /FlateDecode >> stream xڍY[s:~_:/K2r|Ljg1U6xlo9jZݭLSwndY=?-?){ǖSb0SfobN]k 7M@ quNI'6 (zû)u}rh~lE" UEE[&?gqTyƼc"9iNH$Nş,%(+︭j ܬID}cn^$+TgU~i}dy8L#rL!*fn rب*qtjuMtbx/x_@0 JPd GF^Wl(W@ԫa+WՒDzb>sxC\H ƒU mS5еKB0`p7sZsDF͡D8>@orvm^GmaB-mI4hk`YW"n-qpw {%"O뒂2V=o zꗲZel=&!ѪRqRL hHfV  *8/ XYFmr"(m n0.QP\"O"*ٙx3Y0+nD3UV#ƷGS(=ǓF!ND*WnlWoC!?];'Υf qӫ?UOW7<->%{W("mXq"KkTpzN@M}W^fLgbZ޳?}y!FD 5jBkp<℡e> stream xڽY_o8RQl}rn׋$Ud*K%P9g̏qّ^$w57q՗ 9XmVYВ:9{g>unzfqMmh̗XLZQ0wUPo9_·=зo4nw533v}mZ.P7Xk ;d/Gٔ<# Le-9|K]}r,N[3y~l YBZSKeE>.^Xqr@q(Q{>SdE cmYrgky*"9ϒK³E ^98*P? XcTH'HL3Lװ#2LLM SiFPKHy n(Fe l&qt(m-2P zEGr&YBB]Z./Xqĭ0@֦R[+&Kp5cy23eƾ/ECT 7)Sw_85nO $Bh/cI7EyN~-,Hb?6.]Y ÞL/4aFHmf:) o(s)?n/d>_ ڽ[7pXo+yѾAK *ۦZĔgPF*}ʌ4oݬ$C*qrs"gP[8bmS,Pdc(sC;Ԗli*pYnrCM"6H72fL,rHqץY]OSql^w]VzSy7'pG : | @OR1:a4w6d}w:-:^3[j(-m4N YHԹ)7REmX u*_S]KLGDa ~HEw;+~+oTViU{ί!<6v6bxf'j5-WOh=#s]gF郎ͱ=U_ >/nX-ܹgf͌wwsH`zre4xod\p-8}2wդ}fJ&Bioۀq^"0gD9ٷ 9ԞL~q]CXy.S6Mp8boj{չRDF W\VB|Y^skJYT;F_ NswRRN Ny6SNUXI4EAy-bb~)[/F9=;b1WG8p/gH0 atxj>pq"W Ogʏkxn39{fS]i?##אL8

mxg<+dH1va;UW29mΘY&4(WVz/>pxvFݶւ֙~*TOOĢP OS O~hH3 ԭ gϊ\w0!0560Ψ~ 35rDO/^R@!>NR_ 3@)Xi)W'  > stream x3T0BCKscc=K \.hQeUgbl*OS endstream endobj 1249 0 obj << /Length 5651 /Filter /FlateDecode >> stream xK7}dG W=&KykE8,\vf$d/X~£TeVJc[j#2$P()YګWnm ׉_ xźW\iΙ1XU\o'-i-'V\ eoUq/kWwT @U8Cqղފk&67; Bxw]L}&θ4lG^_|wEE۰˫ZFA^'C@.vBVJ(!@7&#ע[\z\ Iij r;n&jGs8iU FF6Uͤx\iVut>/ךMnz˖զYOϗnWtj @Qf{4^*04r6B6֝f*x1:ߛkgu|8ܞg.)xtvF&@,[iB C ͸I${k\4L{ ܥkriHVæ@Ѻ/ע] `pg4ݟ/o}8_wiFwLt)tHTD(% %DQprk JFEVd'_veFUÐ} aEL#Gc傂`t iڎii|J#s+gf1s[f_ 5_B(8Y٣9loRX4rT6F.\.(FKT6m\F:Tb_C!tT l(s2v*@ov˻mkPCOn J/Aqɚ{,fbs0wY;"9#ܵ5Js 굹v#ɠo9594\q"c`Y3 ϻ[C`RZvг}37(BCb Yu Dr(Pr/WtM^iWljFFp"YH55r|5C>2λyub>M\UzzB&5N.\Z  /O \\X$剑 '.O\X$剐%k3J7%5C)^Do0U94ܓHZȅA(8w0$Vժ2F=ݻ;;!go~7YCyἧ)@N#Ǽ#dw)Xjm3D}|oFF6߂3g3w[ ,/}2|DaeIj*P4rTFA]Wf*?yNZWP fߜRx+ɴ֟yq#k79X*\ċ*K.9"9H#NOjMjo,#tq",Ȫ&DrH%>& K/_\\~pBB$!W)I6nnng6#o~Jk 5'NIxo& cm>bՇW0n7`~&B?f(\D$\j8 ; ;\"hԠF9\XaaU 5"~ﻆZzѲz:v dUx=ZO;tMˆfMzc;Qj5vڏiTƆF F6`DZ *%5v5wہ ;@;\ib̡ 4la`Bϻ}3[HGLB:1p XQ_+*[%aZztM5ZN%{k\5\P.Uud}yr5Ӻ5.\&Oiٻ Y_'.b`o PYtd}yr4ZR.@1Uqrr) 8@ BB#Dz#. 8V6ppH F.\.7DpoPprKljљDsfdr?;U3(K9x}HrV.~Bkw.G>teRCFMh>|HG6ujփ۝=awsuI]D1s7';&U8IPS9éL\4rL%B kTIeP<>˗]8asyZ_nchfmO0 ||98)*hG$9J.\s>"8Pp5Cs>*pra· )~F$9J.\s>"8Pp5YBs>*pra· Hs>\'@Bլd M0BɅK|D.]᱐Fc!Bc鴻p G񴻼Bn f>Ro:U94 QpZ"8.9A4rT-B5EN5ުiUe*Rٙ;*d4&ՠBhl~9\j<5/׉$*KhfP53=:Qr褸di`o N:E%{k\ T⁃s .\ya .\B33H{=Pr5B[#88w } "9AɅ˅ k, \\ȱȅ˅#( ]. h87xXoIn~\Rv>4#;p.Qqg+AGTb>%4Ovs ey8l,sNIkDR1 6Y3^35Cwp6^5d1?ԇ~M[C̕v&q 4l1lT_&̡kD6Ԉ6wW4j(1j:r4l1l T_̡k, u!U!B; *B ;A"5 5s $la55ZjգZݽku ?H8~ Af66w0~q@å񃄍.4j?0jpi a`s ;\?H8~ Af696_J̯js)_;`<ޞF7ݰYg=~˜7j35jZ}U-h<D- Tso[". e55FeMi9]?suYjS'o2&h g9fLByq1xR%91э~Rv&:ZÉN"\$hpoox]ϙn*RJUb&+M*N2eo?4_pi au?ʔo$5S94n|D)3Ԭ1StrUങ;9ԙQ_6Fl^'.GK"9X|FGc%^A48_k|A_W3v(~Ƀ>Mh aѨbEjO7s|0r0m(jGs8iLHcyŪmPXVNQ8 pxOץ ӨC |AߡCx7᥺u\=e `(dA(,ÛCz:\C? PD {@1'G$b 2T81 t6*W}Wu$'9"M#H>TҬ:Q Ĩem뉻ө}n!qnk`:~a35оF~O섅bZUbUeA) K4r\ȥK|JK!A4TZLcSD0; h4hA@qH|pJ* 8voM9e>tԟfy[1e@M` p uBP?4Љ=Ty.KO(FsXiQШFEQIpO7ޝn{b4n/?Ex.#Bņob#XcK  E (iAq~[x//MV_t`%8{gNG+ݓ^ٍ#1ul\tD#rb;ӹ հ:lJOr^]JnNkSv^3h۫fFiUKZͪ~$-FsXZi-"uVAr.kPÔTm4LT tBD|ta :H JDÎȴ6O{f@#.1A4f*RV9OHTgdZu- (xHKUh#͕D(ꨴL@uM![VsI%Z$UJUh"͑UM(s= V9k._n=sPYBVv"J#F f.e3K /櫣[ ;g}ntObuEJWÛZX|SnbTɅUk3Pd^.TXuTɅKmŴTK6uQ5ȹK*v[%Ke~I"9X%X1am5.\inE !bi:UA]JN`}i且KR2A \D  XKo }\Fš*|8ub=OTÚ8p \.Z25TK4 UZ"[%4ۇ@KL 4)pDɅKhô8p E6]xy] |d'n*1ܣ5jvFp!ԦL-K<Mo@&٣58N$4˦a$)6f5w_ a6L1l\~nR3HYqb` F F>!( endstream endobj 1037 0 obj << /Type /ObjStm /N 100 /First 989 /Length 2155 /Filter /FlateDecode >> stream xڽZn\ }W1HT tpQ$ tw4MvKj3N=s{}G:x(z$`qx|S6BG-Z$> T1RꆦJa(} ݲ|E:UˉYŁ!mtgPS16<{EKBY a,FnY_Tg-a@٬^5ǥC A3! i8,h w<]\-x$yDTז|-TbsҞIMֿqAydtJnQbi-V Nq̐$,M?_],~Z][^ߋI>YXN/=x_m8ٳxǓZ,}VJ6_eOTRCuOΞh<D$vg[b;Zҋ篿&';tv:ίգ{Jm/Wo_.-xiZZ~N]o/O1﩯 _է˷˫u|O/vxf{M}:qǷݫt7~ep^!1HJudrUdWԸ&UA{SJnL?xi{F9U a0wV`5{|#|]`KyDT%#|{{{<ߕnp=Zժ۾?V۞}oX#۞|oz7ovmqr5–`RŞ]Zϟ?F[qjycKXsF/s57p펵J-ۍ:Q#sosjuÓg/jZ;ײkrTSdZ#Ns6XoKQZ0Zx1 ¨apddddddddddd d d d d d d d d d d d d d d d d d d d 5k @\r 59999999999%%%%%%%%%%5555555555[ @n9"Z @nr={ @ BhB 14A bhC 14A bhC 14A bhC 14Ahpyu'hj.+\-N {yS=zJV@;xލ8MNUf,5{rRR=R1w3w =xv=I, rLan9#)N)N݈8irnd)NkPi=lqNp2']t'rsh833qD[N ᬝY,'i,Y;f= 2OU쨎fnm)88HN-ڱ^uNLV-~N68cm8g:WS3+v ϰRJ.[6LVȻ3֞ aRe}Ls-7VM(8O!F!ia68cm'8g[+oR L&f߭m-Յ=4k-Wfg:yi4rZMsL L3rhsSe94)^r?(ƉTw->м{Hqg$y[E~iA6ytrf;N;TyZdi\u8qj>ytnjy|MrS7%aK%arNzK0(m3iMcO}YV䉥8jQ$S5Ԩ|yaߦ%we7Ÿ-A endstream endobj 1297 0 obj << /Length 2812 /Filter /FlateDecode >> stream xsW1ï;\Ln[M>P2#H};{qH'3HC`XgjHZefWϪ_qoų/z+V-]x;aޚſ.:eiܭ֛ݵݳ?_DIG3ںVF1.U|^KnݿjX +3} gK;Nݻ~!i̾$@ eFb#FdpÝՍdn'BYrlFP'g.;sp dpo==# DK%{krvԲn~]`^i!kFZ ބ৐*B@#G) d'[RpQ۞6W4qrwxϫhUs^L6-|*df?1z!scsFVP'g. %{ %TIdo3ê@Džg.TkF F\N,4Dp.(x2ȱ dW]`BZ]1_JF<7U9,t*%K#Gbd YY^FEK+rۂnUô~la uӛtS݀[L6ƺr' _*jgkR:JwDvZ>~$Q`t޵##F\NG"8h]C/jQš֟ڼ:;_YߝK[Z'Y领}0ÞFp,FaG.e͇흍ipG>9}-хC#Fl0#N19F !(MilSHC~a D4D#G eb',ô]wN8%E+7ח۰\\8HZ'99`3q9HȶHHׄ=+pK!`ȏ| 26vo(Ԡ@:r8qg cduh`)cu+iP?I `G*7x- c  OUBHVSסE-9\5ҙBF\NT"8(]C/Q)RIPdAz;=n>Ӗ?OxpөG*㝑ݨ?kS=܎nT3#a}'q/Hm陻6)O(;46l`ϔ9 H6caimF(uodiT=*SHpߝIm.W >l7]:Nq33wRԑ+U9,tmȃ8rrB4p'\M}P(BUF~/mIW-|,VS0sXi/v Q;adD`܃ e>lICyVTNjۑ)M9X'DcȹKN!PpDKnAgARxjQ2U9,twQA$ J% E3P:QҨ(beݍyQ;VǼ 17;Zee?qlPC:!M'X]" )B!Պ ކ&WZnV桼Ohy {$?eԸp(NHcܕկhi/C.bz B~ `B"Nt6@#tȹK<(8s#j'4/\V⎶/nI __u'?wz8m~H p$y BvtDOHUJ|PQPC1áH'7PШ](b Ob+^fBrZ_yrg1^~a @"@F, .C8_Ap&[35yds[6Ļ"8d \""'Y! ݉pQ.Q|;5B`tQN' endstream endobj 1252 0 obj << /Type /ObjStm /N 100 /First 1001 /Length 2161 /Filter /FlateDecode >> stream xڵA )tl/zH`Hj0b>8΢H} gi^vfߐ")JYC 9s짇R쏚qF\%TW(HW84%!';tpXL:np~ -d=Bnl=7=ԄBTɝ Rk-.ZP*YҚPQ=$UcI,7H+d}[Գ1 2R<ޥq덻50 yM*0&E^  y=,soXXE:Z*ٯPyعKxtqʸC% ,^e0RL^Iphqj $~1JjAz=zЄSP3Z9hZ hPUk1yp֪A,Af0mm>롙\J  h.PUlU`ΦC78Mkm$n*E dHD Vuy7b>TԬK٢"rBx$x y^WN\SᔸlM&4m)[7Ql"pj]F݋w}|twy凧_~zO? AzwSxWjp`a"1M 6x.oϏoeC) |s)M= ̿GVE;GC:\#-,J-QrGhđ]e]LҒ8毴d|m+ҵCIB =oLʱ`)31ƎdL+&YJTL8|YZ9}cF<hE3!Iyy43E#}L=$L=aE3QN"fw҃i&`9Iծ Y"3 ύ.\s)ssc91eN=7sa~Kt:v9o~ǜtc[g1g3ob Sư> +kQX*y& crWf$r_yVFW;eYy +0SJ«<'.`CBUY%mUG6mttëeKu!"'RfmܠSYxEbrjԢ^H'-ǽ#Kε'H9%oo<̍ᚣhºu.gI#8I::tMJcgWv &gL+g_M ldƾ$-(;)\u7W"ۍ)$~+XEwBE$c>%\ow}taNNgp1g*v|zUT3]LSP=\$'#mz:a={ܘWE~Hh /t$J|n]9!֍r endstream endobj 1362 0 obj << /Length 2394 /Filter /FlateDecode >> stream xMsA{cTrʦtK QHj=??C`HzzUO\u?rZӯO]d @_?WkW ruueV—^/+YEfV %9dߕ덐~/ݗ+6?FhW0nL^h/PU/s1"A/uPu㷥o=˕|^PPE~CT}ʣR}8%Nnr^$x*%: !tktz%Xؔ"3*ye\BM/ ߖ\t KJFj(WF)eK2䅌nh5<4gH ( 8#I,Je __v<}H]e($8&(؉F@Bax֌SC*J9ΈMFP,ۗ& \g,)eT ^/7IOzPi p,ʐxC< 郰z ғx$wÑI%g4cIb3yb23nw#SPJ9-MgY^rR%XLB;e_3P PNʘHOIFwcz_d3ererZ ^rQ%/d|.G.q92룔>d }𒳏*y%nH\9RC2J9-=eT &\nHΔʕQipF'e𒳌*y!CI[d7C.RNccyKdtNXNnH6aҞv/ڲPNšj@4yCL`*{).n?oVRNRɕ}T ^ en>QipRJF7&=O{x~ܵZӈRM#oQXdFfz'(c{s{VRNr闙}T })QipR>𒳏*>lI=\g1 ('Fca&OX^ 폶ٜLm(8)Kn6J^J(cg>nk7#뛐LVrMr ^r6Q%/L8)\0y]25+2,nfrQ%/dX)Ecҟur1r%LCLrރ~nqxmMW|!G03i:Z)h%'Hm(48)PԈJq> N8Gj+G)qIK8DGysXy305ˢ, fR#*eaǃV`CYw?dIt`Xԉ8~9vt}TI5L=q5ҔO"ǐ\'/)ԈJqx# >ыHm(48)}ԈJq8%M;.!+XufjP%l'::~l2q2QipR35q O{pn̅`srZ FuQJKQVh5c㘏qiRN{锗T1:8|k^>K4K)iRT6&am^>K4K))zF/U"EP/rcPNJMg\fAJKV`ay}m?g?rijZFaċ.q8 퀋mp>fÙ:͵Ri,px QcF.U"e\^چs [WW~K% AWSVh endstream endobj 1299 0 obj << /Type /ObjStm /N 100 /First 1005 /Length 2212 /Filter /FlateDecode >> stream xڵZMoW\8d}vc80>$1|pBB d4{F@"6`xbXI8I$l>@L>R1Pb Z}jB>YKh'$rQsD+2ViqFG )\|*x1M(վ()@_QrB}E@:G@8>3J QN8ت+nV A_-k Dh_)r}^ I؋ԅHr0W(`IF9Xvs`.F[NiN>,XQ VUl}+Z(uXV(A9vMB%C%E}/9K(f}R|/6WZ+J" ⾢JL)T6|K& k {jq3I s@4y-4O)4 (Zm@ga u<Ɣ34rɧc~R_v Lnc4 5CS3G3rarnFbY}蘭 \`oܝ>?>ÿN?=>r>%x 0]m,u[(cx&>ӟ?>M ?p'IEGWS69_Y(6R879+9ݮnorI͐VRĉ49t{&vp✵)G8 gjΊѭ fVZm9r85OE[Mʒ&-[5+R$)!-IEb+ͲshL\qDv,'. t儃('E%+'sy.VJQ e^ʱr! NCEWNi휕W9tكnE9C[.280Χ!`6`!Dd'"+'r[|ʓdTREFc2Nkʇ;Kv>`TFdNPku4UF;׭2N,6`JJ$I| )υَ&󤳯8!+$tp7f7e/\)H`xo۴|G)-jʸrB[|qyY;ލd,S|EK>ygX 8X'yoƎ=aDY&,cC)S3 N?B5>I;;D<]>ށ {>ߝo^F'_~{_Y} }"'v%~q/Z211111(cPǠ-<@9<@9<@L2 d4i @L2dNHr [W8.D+'aBi/ol8Œ/6$Q[^v[d1և7>t?!w*\>B|ȼKףsm7f!n\h&'qLɮ)M}VveCoӕn[&' 'y)t9PE˶ $R%DȀϝ,9ߦ+N+,K/4CZuTN{}IOTdk;gڝ=?0EwmLO:_m퐗.=/߹'_ҥ׾q VnvR=Yy8{DK_TV>ʞs4U|.vEkT \_V}rhĶzN\;cY=;{ ޥ f|Bfr'DfVyD6K<,̸wtEI7WpfK{"c+iK&ZBKȐg?0 endstream endobj 1367 0 obj << /Length 49 /Filter /FlateDecode >> stream x3T0BCKscc=K \.hQeUgbl*OS endstream endobj 1388 0 obj << /Length1 2141 /Length2 15183 /Length3 0 /Length 16457 /Filter /FlateDecode >> stream xڍP]ٶ Cpwqww  ݂ˣ={꽢 7|9\rbez!;#3=3@DV KNbl \ dag/GLN b `f0s0s01XΑ jjaeH`E=-̝?G15ow  klhlh P3:{T|x0 )_RvxLS?A ߱>3:LL?.&(oC w[MGmhcauqXY5Vꤜ ?@Ih`llϬ#WkǬ-l vN]*zf&X,cc V?53kX9GAOM4=F[;GsS;GؿΓ(0 !N08(XR#)r##ȠXJ#b0TGv?]}d/qdC~}?tv?6$66:gFGoGsEv.k/o'G@Y|,%Z ?|? F??l?^dRTgGqm>ގj GiNZlc q0.\AoGx?~:;+c~@cإy;c@j!<73{)K.OP?27zWwĨn^=[BZ۞^c`'1' ~ӫ{:xYvJ8p!*=I*[ Sl>J5Rǯx<(sҙin5{H:$Sk%qZ S6-a4ւgIQ,ΰˁ}qs_pH)`;ND#v3NwV3PPA{HWg[<(ivtvv2"= M*_7R 'jvee>>s.RO9dɋZ7@oVp>Pּdȸ#WxgXRm`ko^~[ nF~\+Uk>KbPb,F}ڶQ xc1QnՂ1쮬$Hφ)R4-jEu ƕjs0?cRpaJ Z%'(x\Ѹ KbGv5iMLճ^D9 -}%5P|+ Ӣ5_!T*tH ,M5pier᫵-Vr1V;ދ*%$@5(G;oa3٨i@I& ֳeۋ>4$n/ž4),Jtq:TDͱ|KM^>L,̃W9FztNbcvpH{@Äs}L(tYfld`˷3\L%%p?IX΍ɫ.r3Q"נm&tE?d\s)$e9}h]8'l'JK]W-my@IRcn ȳ]&C:gKuj!ziuEr0:_1&?F>+T籽ep!#9%Fa5诹vju&Q0os(7Dt(q<ǏB9Cf*wC52܊|7a#mG4?J :Cx@HqIXtƓ1vj^ ע1bC>euwML 7[FݴN}j%{s#Dʀ ]L3R(tuGSȧLSS]GԔH,"An+EޔCt{L@Q;a6wt[oT h_#Y.W)PV.۞UMqqa8k)=^M8]}a PN ژyv]Ge2% Ԟ{C|7h(z\0UU(jF̂g2i 0⻇5C[Ɨf2m܈ZWz84°UN0._^[3@MdH '[zB#ϲpQ-ŨI&}FE: 16 8:nZCP\pY3~r1s">/E3dG+kHӉEWɦ͇ǖW+5`9Ri[]77d)=mȸЁ-3nIE]Pװ쌠!`z-iBt^;{)+%{)b 9vu0нz,VLhJn R7ɍg[>ZsMpv'}ޥ]lGz< XN$|kU"dN-Fc0U}iarVÙd!ɣJ49`^j| "ױ QXX86dtq0ρafP#^ϟTN5Ez2剻͡Gx!=Xk<=3 uQ1"a๏0IMj+YO7m3$FNiQr2$.k)fZ3V"kԒ@U~]YܖCH@ _)޲O po ̦=[Ř63oʐ5$b D9.[:Dtlla;>ǘhy#_{m**T֨<'I=A]8鰟qBԈî$xi\۬ia&5ܸZs DLh/D8[m!a7"`^Ŕ~'yGC/E],ui ȟL|\a?}W?G;J $J~JlΞ 0w%r*3U(U:K W4Ҹ[}*Җ53RDl9& ">5džSrP!`AJM@hQ< qCX늟*ײ9 i i|9.'C8פ m\榽`g EOTD]V߾ʏ xYWewAj{ 1bd*/샊DAtnJKůA PC_)D%VKF3 3<:L94?8mOO6toԓ¦9c[6ѧ XFfJ0U[I-z95h} tT+T*mc5#¶3!^pz䡣ShւD#rqdHk`M]oԯNKAPJNi~dL3A3$r>K[օwm֏2_<`2.Xno FUC^Qs-; ˧MrKA:tJbM;?ԊlprOG; $Y/XcB+_pCA5Ek7k9NS֐m[oNa=Ƚ9掉.b!~*ct20etk6ц)JϪCj&ӯ9FitSQgG$>Zzvy+"5=ݡk;t:\AE^j^O4]#a2,B2ݢEq򏄱JnBD:Np`Fb^M͑$\i{2wgTw-Kj Õ(؉ԅIzetѨ q%䋩|ǦȤԞpqC=?8JFV}H^a1:PRLXA庝"B'+pb1V/^,E?4埲mLN{_/WyZ$է+:/ 9$p͹ yLgX.R_Kbm/vLp+6g?6tn 7w4´J*ls\HTl^p೛aC~<wĎOcGu<ϊ2RrVzjf_%vL>T8yS6yF=Y(aWfЈf ]ާqsf[\3?-ݝfsl.lbM#`F&H{thBlŐ!d&%yM|a#JDK_|x'J^ m]nTk۸TǚStɻ؟$ʆ ֲM4Ty~͜ն>w)ZƭuQGƏu+uԢl Q>ՕV{[%z)O䐒 MWVMAyFCkѾ9̶O=^-.8zb0=uόBV\^F-čPD$dɬ,f ƾAjH;GB6L5iM~AC,~¸BP[a86lXZ&|^~!F3h:3D" *F~j*?bp -*2 s"w,FLv.tgHX$yBv95@‚PФk-O5gLٌ5CӖOacd!ωU:Ŕ@MTǾ"p\6iN͐>収GA4f`ݤZeYqSR0&ۼ&u`*%pas FI̕h }ԍB*Nn"dUtOmJM^;=#1i"rO|PS5[8S-hf" CexCio]0mO8f 9.1 PCm5kcp^ ( CzC8*##{/b}WV1zSЂiTj,(lzO8?L0c897 1.D˱@2؆Q'/Qr(, `rC!z`= [HTa1pN4|JxFlK oڶw.fWE2pIW\\:iOʴU<㓱Iv o*;c8Hq ;Z;/e0p*X Ţ$X7>C5n%GՑn Q-;RnѥfD4?hW4 ȼUYj' JEgEa@E巊ȸZ ؀QCHl\}UQ zDey6.~u %jQ%b(+DEp~96։lf$@7EhS-Y뼮E& @뱣p5P@T5Ȃ*Yʖ6yc5kH\|Jyh (; hCMv| ,R޸\޷#20 ɡeN*pA:uv\ |"aV8`5}X\ŌMàj<GYĚ1mQ'7\% zc]93ʛEao~yeeGBwݔeGѕv~܁Ѵە* %,fonZYS5(_٦6.L:>E&ǡ*\&1Z Zg837nN u @yic,̭PnfxbѮThzY1ݧAO]YQSI wa`ϕ5Ǯ11uҥ\tL|wp0 Uo|}(= 6&PizUĦ.%C!3CX Ξ@(2!Mœķ%,x"8:pe mMbG|$iۆnt@@vR=y9S]ǺSD \K\f7ԫY]]r2-8پKstDB?QsxWf#oϒzPFsaƇB~WnPS7,ܹ3na?\R?cʅEs9OV^)IQgk%, prfއ* 7#U5Α) 6Θ0oliD[@G5 4w8z) wT"ߍiF6'#휇o!: ŵ1L2;;?+5Sk0|HĔ J%5sUw _LzG9tT,ا!CӸz>u%lѼK p%@*G8Hg_̡xqTka$Z7WV6+bDv*u0IY1AhM7 UD۬8êJ,=/Yf-^'B(0 a9>b}a!j5w<9{H/]nq;SG}L۸cC8]U2(OLkVRb3 o|~0yʚ(- OsbhHq<f1#C)*YP!rl &og92!FWO;Z н(%%ܱyN(1ՙK,awXbHj~L_ȱqs>_)Vhwj#4nHvhq(/j-AIOWhJ6̑e$#ST _ l^n(Ardk(h:-ιNWzk{n7¥ # MJIu#lCq>@RD/xc"4^fk{W= :".V^}V X: BL0:fcmG*84WEG}~^UFsKfn7`rŝ5IDmmjR 59g@OV7ځs H+&H7P/ݰ۷{l$zaMgVltTyPϮ5DYO|ZW- 4s+mRyYle]F]WFHJ{S6tjQ%Vx`EUH7Rll{Q)mK9 Џ(\-ttOTE/7qП]bUG%oCm8&f%*˻AcWW7z^X#x @khOCYGyZ4ہz%0Lt^>{! YeL"@I@tM, U6qɞ+%g"usRGg%^ &#%+|G#\DSxXxݣaIvK_ ]!.U 2<}> L)IW( #*0-H>w F»01ߖ:S9XJ&bg.+V|c4#/lGyiEf`¾gN"}h](LQ,قB{1HJS H u2sǎ?m4ES2jsXj&q\W7+FÒ"sԁ{lٯlkӡkwcV-kMa[9_=<^[11Ɇ5N KNjRVGFʴ [X21g+jm=Sz}f O}<#@,rb~gllX PQvZ/{=]JiOb" n̤fIT],6)EfS P!`ckP T Tgs,= lZȐ[|ßmE`;IT5\.nT^Ã%+9x_:6t {DV" Fo>jQL٩Y?E=m1Ζ9مD=ӨETM1ዋZ"-ki94/`be<HJLǝ8FP*a[4 _H_r9Zu~AO#㺮  b=u _2?[Mז~XTO qN.yd4=_9i+KB>vV(1a8e|"˩}B 4LJR٬u~S}t-!1:fN ^?A+vYBuUg<)mxˈ Ӓx]p@XiH4ocɿ.N\M&ۚO][:~̃Łg>Dgq gh'O&L88*-JQWd$Akܱ3~=Țs95#@qz&$ƝL,н/@LuƓp@I 43ev#1ӉQҜ(ڃP㧄2e( V0F\:!N{~8L܀Ѻi NE4}\ 4U72%Ύ P6'÷6"0&,HkXQsM\wOhnp;9O&|q*T41_KI K4DR'O^ok`2hqa}m RVa;_:MwFh &ұb۽YrQ4퇴Ks߂':uOG.}eᇼ\8`yWV8ѐj+a}\p0Uk CPs;DnV9ik;k21AJȅ"w1u[z eFz/lGP ,td D~1Q ^]3:UA.ӣfqGqcI#s dS_?2ҪQ!f;a٭C}pO V T}7)m$ |#~6 f9Yi:J$X3N E'&KM.b{jg8=R>]kLuw:o48v5H:v J|>M%p^PG Ҷ&J=e-AEz ˙MCe=U}G( I%}ufne5TU⨨dcH-ᷙjH|SBђ<ު7:[n4CsY~({ݚ,Wg&iʍgQ)wS0₴kyG[?qQϠ, Zd؋ A4o,Բn^a B(w'XQwüph2}9  'ՅC[@5 에~MüalE&kM?/eJ]SvYAk=PbN .pvFOWCnY%mV \wX h=?m>ቖ.UOR9<0#l_N&Y fScc 4m%B]2(ORኈ6S?+wiN k>W/j 2wl|= Ru,kߩ2:j.Lm*epFa9< ʢJs:ER4=HJQ99ZG<}(u7oe;x&44Z $y:vC]dkbP=5CC#A]5|_D>'Հ,g7.1V|g++|g%,|uksHUk"%)o(QU_f_MҺZr8'\'oiM1ǩ灢10X {gU2*CLI3֣?2`R?b{Whd8$[#Kwj4j\_ ¢uzն&âp{t͂lhNfV1G7Qx1Q++fgzեtYr {{A\&#`SR:/MBXýG5i0:K*˥'p6Mw=TWA\tQʎXEOZnI:s:>M`LAVRN~K:S:öӄ&]ؗ;9 1qu2)H; Ј:OG?.BR K+vP?AYezO+Bpφcbvw{@M1܍y^0gKk"/;l|v+ߗ7/G.-f;n d6+Rᕙ/qg1Oezݩ'%6\ O+QT0X:~w:x^=XH_axAZsURX %W/J_PҔw1$z-Y+薊6ߌrhSZwi(e`jh3%EOH!WׁI y*s:tX-JR 9xȦ& HXDh^Ԣ wnVd߄t󟋗Xժ綫Uz΍N^QVW&k/מyCZ<#`yi QsQȲ TFC ~%yf.c;EcdpXC 5³eryzrP᧞B6>0tr2 T-0nG:gR:w#lfx澐jeӓ1wJ#RIhk.e[R--@{>(**E(;JSO׻'PuP߯\eBgmOSo gOg8zdғ7! 5[=Υ8JDRC;T+uBABz*KGqg#4(OKBې{_9p.ҙ)dLwwUx*} VƉ>:L H p?"c|ԬtoͶ0>d25۫@*j!cjya~f-gRZ?au[bt!dyZ#- @OO2:t;% SnP뎊ê:?K|ۭW<_l ^S:<췓~`A焤#&4] 0jK'~jo4^jo*Gk\&#%YˇDYCJ&I]9j9i~rD,#*F282 endstream endobj 1390 0 obj << /Length1 2279 /Length2 16654 /Length3 0 /Length 17990 /Filter /FlateDecode >> stream xڌPJ - www]Cp ݝwݜ}ޢj_?~HAN(fgLD `b02322ÒX8[Ktt#cMQ b `b0s3qp32h 1t0lNdvfu@iL`W8@halh 5t6|T46([='%=7-t:MI- bnAX0:}ؚʒ2y{2;9&zw_,llhllgcohaak0dݝi&9Z;}ZX}8uC"C9;Z;;;YX4,jk"lgcuv? GǾ{0pllC&0qgPppJc Ϛ: P/{;{ )+ `ba 0Y 4?1~LƿMcLl=4%ei-F!!;w `coC'Vw]= T%g1@Aadc4`< 7eۑ; m,=1.@._WuWW$ ?Ih`llE*9Yv[}<N3/oIQ[c;n3;c^L)09>La:Qv6_K;Aq'AqDK?`C?`CdG=?QO}ԓ/q~SCG=?QOTЇv?ыE}T/q} GFQ!3?z?!ÇS DesqG?? }H67xx|Y?z~~~ȵLdf?i#b?x!]Lju?"?};}S`Kf9Saa"N.o~KF=^g`}&'mkߨhL0edp]}g%(^i4X͆T'{ =GxE=%2mtL%T-Ĩs r^v@*X,h]p-GUaArxnsMDtW#*!oӒeS!zn_e*LIDD.~'wӏM]wIc/V7;bSb|O"kҲ3nIU}szRO7.G/\H6s!̂9'eS*t_aQe2gB`Na{(ZqJż4f>pfHdb9Ga.R{vdSzg߻B7 =Ena6Bąqi c2|W2\@T-t6_su4/(T~ ܋UyBj {9-J \ZZ6Xva5qÁ:6r i{gw98:82K I+kg1H_@)G(V RzLk^ SDR_qJ8AF~R NA/t_%M^sE)x9|J3WtiNYaBm56u"uq_kgpOYc,Y ?29V^sc =mVtn.lr)W@UA.%5BA&pzTi qPpyh%|+~ URApa%gӡL΅}Ja~hIbqI*=q>?3ιjs(p3^/>ȕ\[_G\C*%n O޺kdQ%pƧjRw1?:ut5rѱ[?Wf,[S7ύqk7s%5˴>.i}}-@m3Ic*fxѢvD"*N\Bqy:N+8@z8l0#U'x fޒqj~%3H@tF^C/-Y;VIkA_5ഃl41 kz!LKA*/I%P@Z]4BN#qΈ`"?,Z$<,962]4o~' (E\YМ:{.f$$ dE˥ !3;HẐM'9xLv%МKɘw'c IDpz:Ip1T'MQ@Etqc/I> u.K"GqT)t##(]a(Mm+"ܱC/ja ^#q5)W@I~߅p*Ng>.2ɲKeߥ;gڮvC8=^WWq9T{EBYrIpa,~3kN}Y"XmJ *c5P?O^n*7Vno{:m](մd4j0ϏQ2f>|D:S)OZCZC Кco-dWb,8/fȅمy>KJXE u]L6~h<ǀӟN3˘| 5{r]ĘbNOm qve:\9,;YY%o!0*ozVµHdoTSdb i~sZg+y!E£*AeeT7٠άZj s6{j + Tf o-Wdt`R?sMU48qC0#U!ޛs\pNxrqmY8f(Đ }ˁ6wjѿo+kφZT}3Ɇ4$ez(H7ҎcQ8kktm[B]ә,m*9>/u/a1˃:e30OiЈ݈K,:_ /AsRHnO9e)5|K@~QxR` $K˵MWڳN Ivk.7h(T[Ji̕#@.A2o[}h}%9Wjn7׵6VԷ9H! (;piZ^^}7gZ0=df&m~qF;s?NTsrp6 F>EdYR9f,zhѯÏnvnU򝐸Lzi"zF#8dkO1Ӷn{=nIisN}Fo!S`!33ôC_xW]uD(ːy\mLHMYH>PM0Z]Ip718\-m92uOznkA}^QyV#B%5MޅIپ+UҥVsf,r͙R>]_ӎcD͉SJʋV^y=[.VQ#9;T[z5WFO dC0.vԳ\^Nym4Db xHP#Tu 6)g[) 8R_amY:8&-x;J1uH(̄&se(̉זt|:P+zc} A.H!J<=Wۍ'iϡ *0 2xr\u⾼4 Om]#\e͓C3dpҾ<.r$8lI{+ZBU{dMN;MáܸHFue[dP7߾lx<Ւ}^ߌM߱,.B4b.^YeJRZce9aB0YzS!z_XyU@/nF'AD/ 6I#]?RD7ۙ/0х\uaY"e/i&Ϳt+Inʨ4a>1{ҙCAUA|5tuұ~Sz$b>u’@I#O WrxCuɖ D%cd.m?-pS~/ ,aGbJH8FeW=5AC= ݪ::]!8u.{>]3ic|lU,p0Gs?ѭKr%oDb/=ӄ]Ѓ*Hgh3 vd|=v< p\-SiB׏57-"o]ߑjm߈r-"3R?y eȯ-+#ZY(Qs#&O\@KbIH0x\ B~ T׫RJgM_zwUJDNS[-;V)yl%7s9[g7'//˭A\18߃r"d|_r#BYsfaZΟ}PCE:%{Р@M>Uz2AC g5!*‚_dF/R*guHnF/L-y7r ݙZ/[f\łk+D^9l%E)NT{{V0X|R\""@5g'53PTCsQX=(GxwtZ} fum^Ei) |؁á`~!كve 3CWgU,Dsn&m2=mu>*1`3T/7Q ̃p*GAC (!C4i~cBF5n.!*@ZQ}R?kTp>i"9E'O"[x9cU׭T´Np4U!ZއfQ77xUA_3I*+s2֬P2.S5I] Fo(u. |8aۑ)zmi pԝ wF-.f )m4;ڰusfH0wԚQmGXs]i*>}_@kȧ_Z]ˀ%;-ŮtX]@^yvqsȡ==JG!P%S78^$?[<t\yu3'$I$s'OPo7jAg*4 ^SxK1 FKI$ڃXb[r[Tox3MFgr@lĆ1+@SS/(kA,bka#g ~8zzόR\a )Y#zcϯ̈́O{ = =$lL1nR!JCς!OIԲw:, Ĥg46zi m GbI<Ё]vwҍ)]^4k!zREYSf]\~驪4' GLOoVthwd!Jaϛ;}s`CגY7#Z/L@Aol$4UPKVpͫ)zn WC?7Wd4-HgA*6WY cĮ7$L5k9T `5CmgLsl52q̈́%P\7I!5} AtkY4~2DB),H^Rd}|n -=]U):4yտCdgy!6jŘ*ځfDYr| hBʑz7F"5EftQPtS^}jPÖͲ+e%޷91oqF116pXovoӇU^5Qlr~Gaw9yfj$=,`5̴#F%gճH`%{yFnYՍ$T}sA`! Z%1FXexymb[cT 4$߀e`laShM.M pG@yE'H-vnU4c?7P3 L[&b "x|}C\ {˨.f9@S=($q;)oك8|zO/P ">GJ9b(e˥)6s4S>^I3k@:iJ( dv8o,6wǞMo$ӑ> "x+*~T" F lMv@LvB_Y݋U˥Q BuWGg!Zo7B(/#𩘬)UZ%zv QB/ڷp=.SN`PwsUdԧV3T#"ֱT"~HY8CrW|`>fŵR!\o@ #zsU)5]O  IsǃaRAR)->]fly7X ]爷",a/8 ǫ ̲RzU$f!c sI}fc~(ć VT"*!a/>63*Rʾz]k|#]{︳,"ޠq=W_p$_Fc4ZmF|ߦOy9dpA~\1+8J.[Pz@[-Jɜx@J¼ň &Y4`:9\܊8VrR_kDA' B6zHƗcۦ,72pԁl&n:԰lQWTD1\,q~ _KGN+o;24:6td@"VaGULo+ֹ:5]n A8d0~j!G PU(Y=)osAqXX\##V3z%e^VȊ/wH>èݪfu;hc+׫&O%"/Fҕۡa^ՔIM&FlѝʧM,G+8O Z\0HL00yV/|_U&k qsa|;ӱ.I v Sw o?N /b /Jw͡(JxRZݽ)2=Iu{c: ̩8}GZ̢ϖwͲ=! 9šH*q':$53Qd>;)On`;bRX|#a5^R_]lV%bS5$U` F~AUnbD.dJ^>ۊ UQ ;*-HLC3Zr Jp LN~1+\cV b뾵e]~8(K>L\эFO[=M~05C<Ȯc'F:=WC"HZF Zv;c7}Ay !. DcI^?T 䮪?OQf=#a =Nث)A^ a7]e'Rs#B m$Kb_UVOD! :58gk`B6EDfg໐7TUuNmFRqaYju|OR"m,CO(±_,Y^[PӚ nYgY."?qx~-_h0xmvB?E D\ݾNmb3<]7ϖG6?f_x;)#zwl{s0wPȗid؁s]PzmN3K)&AcR7*~*_N~ HŸ_UW~.b?TA)[a(\c*iIiv".h,5^G6X"9n(@{'ECMԅ_37D+˕fc [E \t"0R6 wl!{#GX=PG-')Tũϰ"^ް*84Uz}lU:Vf ]OT>T9 ܋HlOثӀ'icǾՁU .lIcv9V HoDʧ᭶> Z:w7NEe)#7p!<ÂHgXgZJu <{䠾?dF Jm1e ܊oa\D" vcπkK;ɻ - ^ @gs8xđ^lτp{ L7msp`<N?LBL eo6\!K=u/W蒋x^~A'{\:^޻zN,mm4z O;?o~e~(kh8.0,7( ?LZ &HϾ1΢(IڦI+ U/7 t8Lw˺5$}]nș V$K=7.#0O/g%H !j)j&pNƒԛ[=1AEiWpIو $SȈp%3@XɮnkWTԾ .yHPF-Ŧt(17|x 7 \}VTRLVZ]fH\ͨʰ΍|3oؒ{>S>P[V$XPX 7i%1mOt쁓)~W^xcv|t)&"wZm > *L"94TҰ30&eu^_ f:܈sbotͺS~I+6)KV3T%^0mzz_ǟ|O㷥T7qtR*/Gl',޴rFmFT1epY;5&yV*n٣pVPO?U `3Bp?}ϵZܰoVU BO@^C1X$-[qlXN CYهevTʭ1Q F /E*GSs{?0CGr$UZpLqa* -vq!1mj{A8vUn [#~x.,:N+K2<8,$sGfq /6Ve%I}]r6:q3KqiΕ8y&HJY9x%(u;تdOe&i̾];cv$C~V ̗пT?ۣܿ$>mѥRqbI\:3V^y5%Al*ƚoUδVоVJ'g baml(ثd3s2 hA9X{HzsK ֟BGͬKSLSa8[q m_ @B ;Y qs2n.偒3Sri|o F"Hw%?zFqzS\FA O;J+dh9O .BF)KZ5p$$C.=Mᶡץ_eC.rPu8XR;YX>RI4U&_xAɵ/ C`iԹțF׍~g9Mc=Gfa"tz`<-[}xRÅv:6OlLvoi{RMh[/72-bZCpX yƫ"qojMt ,Ty]ݢuVy{mϛ=^c7iֱÓo)X#`#Y,VzgpA4>HؤqE?^u~YrBA7I].O9<+PQGLrPJZ bD0ks6$RS%&ɰǫy`1.XUKҍD2Ѝg_r (|.6<& ܷbAhx5]V !ax<&yÖ`4?1,jIKIL6#Eʩ]d:E>Z̯ mҡ4XɎ}a>$t#m&Vq0ulI 2||g3-iǁ񨞙),lK{Yݑuc29> stream xڍvT[. ] CHww 1"!R -%-HKsZYkֳotma`Ȫyܼ|LLz3?vl&0! 69Qx8PX+G\ Թ*0(I; j sv!6 (@pW9ta60_)X%W1///n;7 n/ :`w0l ErE qЅ!@p0 CC<`8:@WY '+W"` @vg0@SAAx' wu@AZg?w8qőWm\\P; puNP?+; [W}(,Ͻ =`o_|\_{~0W= p|ppW@ bX!Pߛv^a0?1,_ed`?.>/( (;W#+C`?ߨX6si t3^A^/W#g?p?@}򸗮~ aoWC🳫x7ݏ4+@ZßӮk֜!Pvpyy 0^@wIy נ @p8W?Dڂ2 C܇`p_g*ెln6޿l`; oDP7]v~?N`C>E+Kl9B]A>cbwd7 E~ߴ3(?\w_~k_~_~kMz {+EC)"r/xAqk??^`Ml߇\TISyqm>̴io32;t~&6E.z*5OwX\f3Yߧ=^,j.=-7'FvWn"xZ/zkz}9U)W~YH$Su9;ё7gOwt*8 LV/|;(SӠ}gNWy4W\f>N^#ELG >b]!3(/Mh{p(Wi*&5j$g C^PI1p9#ߴ0p<oF aU+Z4 2& ,[羥…F^/{p"/왧I8 {W'khh6r0s V11*V6~^y*Xk` ,ҳl2Xw۳bD儖H2+$M^"36:[|' ]04Z *&s 6~ B?*&Et g;k^%+7i}&Shf#59VeY"}r sbVGIR5)"#AS͗ېBl:S-,'hV|u۶X%0O}ϕ"J|g~ Gǩv"߰:]-CL>  ,񅭗 qV`Q*jn hgWlڶN5컸j!@v͚loA?zaom9ʥͣKahޡ]S&Ia6~E5`IKƈ䙴 tnY]I-1AE=s+]0M _ dU]=i54p0gֹ+ вͲNNxT`F>_2`,QG KT4tH]u19rG.j<;kR,Qk;يr^!y fTL8~LRGzU2?ؑ  F>E=ofO+_:6U<,=;`b3X/Ù51ѻJ#?,Y)Ow:E)Og(P3SK<&aVWޤBn]7G΋b*ZL||ӆ&CJ.XKn'1$YkdOҾgD LH'J).Pj~9S,S.W\/oQ񑝓, &iH^E7E"N %!xED7e^Q oj4 Z v+# Y*j+2QM,@Q@fî.v7ŅNGsW͹6ӿȶA0[>]Q6}WuRogrQ=ڏ']Mc I} )xgdlÓ!c ~~=ƙ\i{14>V/%]h)Bӑ~ALMi rWķ$ZjmgBg_:{_-92塓u<_+Z]+5t|!<Ԑ K/:~18Όyi+z}IxRY.gBw?:ɜ^lI'7Haug87$X{ _hÅŢ2"+^{}]=͒~hJU P^IAذ$oht5" h1sך/c? EQT=Mh}mqz:I3e_+eUqAb,f}ySt ɶ-ҫ#m+ċxbMzShBvnip*o^-~zrMw{G~/LP"HĠsq>u51ih~Xel)O?{a4XrfsugW=n'Dى0[px3{[uQڎPJf6DXe&o4|0ΙPA"Aĥ/d9x}Cp]J3O{wj|xK]ԯbF^bzݦK=vRAx}$>WᤶĽ^bQ u .☧|8 O{wͭ,JL"Zf;'^/BDD_>e+4Ia4 2c=WmиX哅rhz ¥SvM$ 0.Glгt>-glZgkVcEŸUܽ`]H͋%ߧXK},C֍uYڞKT^-B?e$s<Į~X!TOm1fIy^Hb`By|X"GKzgtn9l"W5{$lEQNJV/͞_S`5gekn!)tbuQxҬFLb?!0t!+ƃcEo;?QOVag>Ğϸst[8E HGkl9y hWv+ZHV؛ވ$).nc4){'\!X8[p-1*Z582Z(Uv99Ct m-kTNBlPWGfr|nq4m^:#VQكsutPB'2ɼTBĶ3K/0Z?-C^͆uLu۞ƭi=i-UL;Mt \OqND}_2s}k0N3k|fYA\ L [`u@6_skY7gɻ54yms :\饯0͚f SXvɬ,iBt 5ՙ XBC,Oֻ2e{I& E:Oƽ{}a0O)gɇ/e갨Skr['=]/h \@cn8Ѻ>PгA3,ZCDmQٜ\Rfۉ@H{a]V|*AQNTOr ", N2aNm)z~UNt< nۏ?ӀN|UcscADmtbC@)<<xb!(J ,M\y136./:w~ddsuӆ‰oUK(%HĊX)weXsSn]z(b**Sk seIJ9̪_2V܋:١%a[o+@vI9:`% >Ƚ؏/2S7ĩv7Yd0MSJRs7V78Iz0;f;{|A&?c{ng*{3$+e[+~_*A :^9}.l,JzFmᷱI<s̳0KZd](c⡵u'wNk}3FiD혂\!Zsu\ DU MyKqf-~S)0`e2(eq_Sc}~/Q#GAo%a$Ãtuuvy>܇yK&l :~m)OP:O0;||}2ҳΐrUX./[!Ɨ`{ၧjVerƇ\RK)/~M=A&Bh%O8j(l2lIbN!G"q"$cqL&$o,/JA~]q(\WN2:܄5:ǩxw2xGkdjq@Y"?ZLRd14x~_5}uqKm3\}LTQc8MGq+.Q(9Y]JrGhQwZ9N.pc"7|v7"7&kFߨB.3Vmw1#vZh-֌6 -ruZtVVl2cKPrsjp&)*}-qMm!\)'sNBPY|is:=$@];p)#3@\h7GobśҸ4C;8,a*hTnDTBvzA:t9p!~]l;9eڙ7Il\6]`ɕrـ.5IgƐ|G%"vH" 9i}:iBP #Mψ7YOSs 3,?YZR2VCztuNjO_}:8n?'3nK1*.qIc??)cu9lfٰ?zKadťi@G:[|w[' )咞kGʸ ZV쏦^j5m l8V82JCY<&?SD<ϩuw׊ɬ/6kX.f[gr0fl6E cHycp'9>=[#E=n )ST3)zY.z\J/W?aa\,z7RSc/?RSd]RdPJL=xOD9㰙62=:>XK;+޶]dD?1R"v1܅'T:n_J r/+ Y ]JIW l=XIhxbdKPnH=žU&)f}:^oxqjfIEA(js誝E\E#8g",ؒ)-JO(x5E>)QT-}7mOpI(~7StEdeV$zD,m[ZeMcv}~";pWszs͇C{p:EYxTl$Lyd ĵ(k'^zBTH/c!ntqc!xžz80>S#TgRo'8RU?Cn剧r TQKiu @ΰݰːnu򈚗 h&ӌ{|,\x~V6 ˞R|e]@~q%uGdɩuwA$pUDgAnoyeXNJݵ?8+-<]27~TlZXI6GR bN}ՎdOrQzA|g{РAen?_(TҚ x_)ӜVvj3p'N;CWuGd~{W =q$61fhZZZ gev^.%S+hןͺԛ| PmfĹxyBP%¢VPYKSeX;5hs[Sd7`Bpڠ[O0I|q!k2iMϲĠSݒG%9^:o}͖N89t /tHzց⋿GlGZc 4 azʅU)߿ĠiLcLErgpސfkx7jaс3:JO=Y۵C7ё".lE5btLB*Ց WwP3T{b#S0t?-Zp^_0XEQaاhh>mK&txE?FRSI]ԱV50rx8-4>et6~k'yw*Kv4P zd\i= Nl|.<sߏTP.T\~Lrj`L rU&TǸ(*"Yh:D8t6}U}q'_x Uj?'Q(㜅/sW.#H!vWHk)T^ҪgYq $% 'R񋡱s,J0 N.:H_dt`<# (i:&'2Qkqs0"J*tOQd'y}_I7Z#<!KQϬa8Xy]qj<6sHD3YGnBr !Djq (率A.wo<yJ cd1@2Nkꀟ>K)w K&GC8Ml哾Ssq:*t)wh~x+x}5$ Ew֬$҇goiB9Ώ: ?Xt-J}._ Q*C̈́LۢU-ѽ1/HXf{jVG \ I&j(i!k bi@k!izeYg[?q8]#&iqhp\)_tL*aIEh7(j+"BYW׽ψLp,=R'OctTq1mIv2}- wlUxK;̭:B=c:RE6C"cWN_渭M~_AdP|? "o-6AiV"b?L/F+rwf>JmcC endstream endobj 1394 0 obj << /Length1 2119 /Length2 16235 /Length3 0 /Length 17520 /Filter /FlateDecode >> stream xڌtk F;ll۶nƶFcqcv=c|cdsiu]k;dD ʴ&vF@1;[gZF:.$# L;,ΖŽ@CG-@ `dbdb`010p'Α bjaH`Ʉ=-̝?x00rr:Zd ́6Ɔe;c 1wv碧wss3qs4㣤Y8N@GW ௖r6FKP1pC0X[m>R\lMv @h`}8F:w_,lN64675ZXb2t4C[ > ] - >nT~t-읝,2,jk"lgcuvK#=}Vvn^A&abOjkẇ `e`g`@wcsT<;2eog0hca r2t]>^t/edX;fhf?F_>~Lǟ𿯘^DYAMF-)$def22X8>[G:+ikj_z??]=J] Ϥ02a<NU$bm_?~C kG|}, Ukwe&.6+lf#MB/;D_c/_ gma Ts|[flq >V ?uۙ}LlCGGC؏@/Ə55=z:[;G>S;Gؿ.@/_ @/ 8E z?@/1%>?O>>">?OS}iq~0hA >N#\"ֿk WOoQQY ~o>FOG+X~/dnmhcdG_'C͟Noݟ>C# zvp? )@YcGǏm-In@cy;c ˺A\7I &B=hix%r~F1=n9!쵅kz;ZB3BO ^xH- yB\% =0&fdH_~'KwuԔf`ql)9 `ٲ ܎ OK'zwF^Ar ؽ qFaV[G|)q=NG2G86NP'wesuKDnnhxb.[aJ<ėp֗f!cr J*4XciojE:ER`l<[ΉO#Y7Wж/5(;ԘG>Y+wL*|+Am~(UCPEw^,o]]BKՑP<7W Gj=l6K7uel|*=;lXO7PeGA߰‰+n *@cM@Jr?cN u0úG={`9WT7#y=>5F77@u=wr\]38ePZPrϘ\( ϱVhC`}!#4ԕ's%OH'uLv"ϙFM$ꟴ uUDz-ӕ#|驟vv0ȫ;+u79YDj+&MDM~&,*EH\4O$1T+Ԟ?14Q=X3n|Fl$Z'ɃxÎL[x.,_gHZolHu8isw eƾ~^yLU3mnx\ؒJx)dinW1yXOFhY:?NJa3%M.P `9,Lx>^/6i OPnޒF~`1ߕsІOT"eMҌF*OSe^f`2Y|jV[7܊2a]I `lRpOeEn edɣo 4Muϰد/UI ;wGS|ʋXMBQ!9/p\8Ip1c\WBz[fZgfWV"bb6ÎDaO,[t ÙZ d{8} [X8ÕP|[ϖ淚ApwWN41Z #t"FO+E%#g!C–,+9;HǴwKA P:}1EU a{ >aN!6E$lKcc1$7GԎ6`(iSyh_ۥ9. q߬ȫYoGK~Үhihdk3[bZi v5= ũeldCT$m<2/N+v̄޺jݴ=\VU*ωs!tCS~y&w^0eswŇs "{Z6JJ~ѬsdYu^Pܙ Hiߖv ՄCIM8ke2nZ뇚`*Im *ڏi cg=)e>tn%;WE=;9n#0M, Z.oF<T#qhh(I@ Y~z HR +1qsb[ϩ('Ŏo[Otk5`עe`'ɻ1UHGӤEBp2\-Br?qIF6]'$ZL WZd͛vi*U5B/{ =Zm3=4J@Ymo=}.. 5V_9l=o3M三w|!K;R0Zpŋ~D{sؐ{g v,@@cTɨpu~_7 m&,*DڃYV 9S[YTJf7:U.4۲,}au~8KA>ÊlGa,i`k[jy'_" 5NjI|\Z+dp^WڵȰ&e s"zN<ןm?0&ۯUuF L܃փ;]\41}HVeJ/RJ5ON uljBףּGW9\jKd Φ;v,7yzVo9`4Ā-oU%DXԕY@AAF[󯜚O^˃TϓU4Ǔ-`taJ9>SԼ .3Bj"*u\\|#0PQk-Ij# ` w]3U*wvn֝N.'}E#% yDΙ6닸r(%*K |l3i/e7'= |b_Z:ASºE|O>\370tgHQLJv5ʌV0{{}- Aݵ; jʘ L+]W.SUpguwC1:B `֙17g8#Wg]uéD\A"q2pɎfK'~ǸDm I[KDM;"03$_ޯsjẍ́/W<&t8M /p}lefѭ#\HBPCؤTlqOHD0 1DiR{7I5Ɲo5jq-+ >yd819؜g.nzUie @S">euo+i.;XVPAh; x>`Zũ"A( O{;ІI7vyhUUq4wHwlZšԑkgt3Ue12HZx8}ng5ڌ#|&4Ӻϟs(BFLk(V'E%!Ri#}kox]DS)Ex-kG%w֟B&䔇"f_QBV焣r7#jyWc 3*)tW䀸Y '%pzR1P | yWEq32멯 uH`H홻@4U*!@ rep CvTNxEwV%FJqQL?C1|K|d/6=)j W+y{^"5dp1A~ :Ed^J&"s0 jۊ)Ur_98l!&ͣ+ŷ{:, ڍ ck1a`QPAu C~N(ɥ}ѦjMr8.$M⴫*XnakYRE|ڡ!tIٻMHtLzY|n^σqhV׽m"r w{+uJ[T)N3#U}ME>kh,I`uB&ºs\| oFTQ4  5 Nf5A}"]2_Rett%@Υߑ6+/l1 @xf9S+b~XʿF3dD6dz?K #lHÍuxl*CJ&Ke#`7A֎~J听jR._t0kyy$KB|eYP! =K+vR^IZPz]>48l)Fܸv}:-H #IEakܩt1 GLPOiQC" 'QAsgI^oog $-ZՌͳuɗVZ  G@pDQBbogȺ'ˤ<0Az g8gew8icR£wev3⹍וQ a8zh>MZn.ٕ T ' Y"N(Qc%-Cy?-{$P1&@?zFc(8| j $/z,S},i ֔c6шi I!qNƫte.8&fE @lPEhB֐Ó'pJw6 ژ<)ꓤ-o'}'x/Q%r3;fITם#[]Pip?:Moďo,U8ᕄg hpE1e}3 M=5:Q1 :ͺ}1~,JiaVh|=74]*8 h ) %k^}D01bD`N ώ5Wݜџ8RgV[ٔ%.\aVK*荤JZB6(]F}H ] HpXTtL72Kw9b/h.}:?'Z_Z'ilPO>1K޾`~v\ݳO??U9Kpqkk]ָL= \WM[Z3y7>zP NIJm==~4PaTD7t*<JYjxI-wNP&Bo$&1> !O45@)*1e!CXX-MY*ح|XYJUUQ 8F%ҫ v~vD⛎I5l,LhWVXY73^SEb,JA+qd'~I6˭<j/Y<RcCL4T\xihq&]*՘ f͐àz }:ǠtĉWK6NYV]:YjU2w@c|(҅UzA1<%n+-Bx[AKߤVcQijψMX[bib=xE]!Hq;yw9*A1W8AJtd[BC?e#9ws/9VqE%cX56sM('t%7 *s4JRdhK0$a6(#^*g*OEK*am1LeEO|wA:DRy3t>GGĴT )Tʼn˙So$rwA_dMRCRCz¹r5BzTpY@0fza%OUs!68zϯ}ÊmFT7:ki^F݁{pR\G=A7V֨ğ%:ebskWU tj5 v vsq=nœtVnz [ klY-w)/dوOG5xʄ8>Q#fɣ<% AAٴ7Aѕ (U}0}H]Y[ޟE;ېha}яYJI|۠$ L[Hs}ty"F_9W[, }}v!,W.絇8LmP/M/rZ1ixGs'$W[X_e^8¾:S_dKƎ=NH)A $d'HElWKKNE9:v bJ+nELiz,yPllW-*U/5`'luLc0d] 19R%ϔ6GG,]+͝q=9 )s ݵָ0 %]eŭ),ԟKQ8kyDh@39PZ.(߅ S_@o -C|{K=%9s {AX>c`.߫KN&\+kyz+cs?&BeՍWFwOQ.C6sV6 oVTn~8Jepak\yR_Xny /@[!X7 ^i|'+":~u(v%~~!#0β3Ґ7ベC9k˭Ըy Kg8ơ*S˷K܉d:)[ zܫj:6}~!ٻS;. !"E\h-=r;sdi)'&Ky5uvp" fpJ .:|0Q/OhY>Jo:}2z[ecӝF\ڢ Mtt*u^C{0Z4sle&ka.s7¡mPϔ98_=r])6I_ i :9)i.x8⥘fm8-UYR87Hf_!w9v؅O;p磗ϵ<ȅ u5d=!G|3Ʃ7A£E!>cbdC8LSTY Lt;3-o7dX mÞNً[սp {sl0Y>$KU^j@3ǂu84ոиͲը|}.GT'JqU^K=)&# [xphR2 Z2ws"+j)^88B-Q?aA(c4 ͏YH=Қ6,nVQD=oC[ QYoW$y@5sC!gwF,c\K|nb舿&3*.gk!„L9\kda]Æ.{wvTYU׺SCo%jbQ VLR%jN<-,Rkq*W%t-b~zhg8ijME4n§LѸK]nM8#:5UNiB&/10^OAU1I?[i̱QE+0Yu(EX:,oQ@̽$k'ʦ M\_׈9o'BJ'+}ioh  E4d8afߊhN;%7 iWI=cӿyЩv%33W9sP2)k+S"oE٨H$*/jk%@당䉕S]T8RaYwȃW-<Myp|ycmdfX5=l9X7q' 1jm1fT u1=7_5Q;'Fy6l./A)xZnjo] q DtׇR$D ?jeRvt. oEOVCjrQL87-jՙKܥk>0ٻV M&ӳm d2 ^`N$/O-qSp=fĂ֛Jf8O-'0:?.lI=ښjӀ@ ~k%{KU,+).=ģpt`ύ˔ݯ,hoƮӔmBto (U9d[rY-jZCە#G2jۖ 3{?*h/e,&簜 *9 ^\d[NǠ] 3tk^1ׄ柈H;j3^}9[4F1Cߚ&YO'xPV.߉ix1୔bp-.|^Frd3eԘ+y1Or joQw$&;z B^FFW$x t3w%A;*if)F;DL'>Ö=S)E@MK5S՗" w)pbR%:i֕ƎJ]0S"_/7=7wo::xB$l\z$贆bRvTאf = CC'`}r% 212U5/L5K1FVS7OH)[how~#y3+v;𡉍EfYB91Aj1pe+|PIR7R /ުbF[n۸jY'$B]8\ ZH1Ka4u#HqXo 1 LWWX]P/b$WzsA:GP!_Nqr}+WޚjĨ,+ZcX?}ZA\H##l&UK_v3~Z9*5. uyPO'$NxV2P8}a}~AJ7~"TG<(.(<=ҒERݼo7\'$¥؛-A9׷bRhnrg1;Ƈ;BNQ&+#u]ƳO[DGG,B+nBy&rβv[:-A0q{*t rfب4_]Rd+3~d)yՔz!,~E^0Lv`l&'%w$ehsdiMC\܉td&?baz # |7M+=#cdYc[xƘ]E-rqXx dmr9vo Ʊ'Gȍp%9͖6~y.Z"y 2$2kN$HձijO}K'%T %Ҍ4?5Ŝ Q H[*v](헤^V(29d 6)H8;BFo^Q/J-EvɌ}?A<}t6뿪sL XLEe終lb#EqKӱ'[L`Q`I)5,1HM*URdZb<DS:cãa j pQr5B!t mxB *ZNsea ʼnE\J>v:0x,N[|Eo?X#ɸ־Wvmg$  <נٙ݃a m׹ jZ6 ¦ň\\<+ZGdyL0ŐΗzmcHtb/4+'Jsį`'(dtg:czUBg7deǛnnB`I^{:wUbD8hVlx:Fu荰r zwUʝ^ā~Z6(ՑiE>]AƉ_4ڼjX)ZR4*3<{szo bEhzZ&5-e~ڎ(fu}LkY*tq!+Z.=Rc)x=ΝK'LڣdL7ip_|x˿ّӟ?,~\K3 D(tq!kwZ*DpnְZD=b[Tu:+|1ЦZL04QW?LqۡQ> xG fz+ 'ĥ?2ݙ};`aűB3S~ 9#7.f/`c>47^'VIDػ(^pLs {ʿPhyFإ@2!qP(o%Ï5MH, &v LRl]Ȫ-_Tƀg/y5E8 ~oǺv,Y3 bt}wÖ,^|Po`ִKn=Smo/ :Xf} ʪֲS.@E'=w?PL>ez?*QgB*r̝z}w"b82 Hv0 PoM%Gn0da!{XɽrwEYh!eO Tu| 1c-U-ڪ'ӻv|#v)p,O)/F2SRt_[Yvv-/\. EaR˙\ŀ~1N]NYݕ voegf@x34*PBfkf 8݀ո}wEu9%Dmb,qozrJs)$CLP&M(?epqҥCK0|u/,aKM~ q{̱w$jG_>k/mYWԓ{pʝV%!/Ȏ_'+|iVl~GBVV.ٹR: TY$1~z0Nչk? rz;2NLBu8aj^^rMelʁ`zϧyc -- ࣡S4/=2|hZʐщ}L@7 `*ygI)f|o}e@ T6`xҵf߁NLfﯻR?@ 8ʿibm V|6=E>Iqwv“͙]EóQ/ KalJIdpqe׬sy@OM /7w#Z ِ\x.A2erw7Wfz{׈5tKj; SmgԿ] kGjn(rVh=l >0*=( Mxv{}RARY(%1aLNb~@b|}e̘8kUHM,!C^p,,ɜQ?D;t>TNž屹N.gHY,PM5M5\§-]3gx٘xfg (KW8߯^69><tf`{m>h-zB˪:m~}Xa'V !x2f"_:q?kh˶$z_Ќz]f<2l`x^/V>tIv0^:"1-^&X&6lP?%;ZA۪kؔv{젾zZy2z k"ʦ6z_|(grH{1%i⇦}}\{n#2[IE'hVsx]:-/Sɧ%PX~ᛞ/N6] B >61굕c}shVsZkk\Tx\$z!D $S[O uz4,ߘjp32$\LDJ2m)+juR~B!-Dy^Nmm+AF=biɜlHMD>v¾DUjg]!gg9DLb<  32 y3e dWYy&(NX MĈH<2kz֒{>; a ,%*ЃbC~|7^$~J\{jt], ͺ/.2ڂp6 WݮR7 :9rHjHB:wv#+ID*/SXv DZ3~;԰n7[,.7ZlL{41zn] kiPXOy]-,F4#fl\%8F94H (nsN*s*ACI ϊ0ko 4WdeJHo\&cVKҐ3&Le vi!I KjEs2\]B>0>?~nɜn \Z-o.2zdz Dٴ4l ycCu39^}4 Y ^T{iMd\)Rguu/mtVD{Ž矫`~nlF'Qi[!PqמI%RRoҶORG\ endstream endobj 1396 0 obj << /Length1 1487 /Length2 7401 /Length3 0 /Length 8407 /Filter /FlateDecode >> stream xڍuTo6!4ұ4,"]Ȳ"4HH7R ]"ݍH};Ξkk~oįAAp?P@H   rpPпH.*P S@ťBBa!!wi* P$! B# JIIN(@a`B9B]'A#EG .YGUZPK@;s`(G! uB(tA.п ra?#= 00Dx!Pwt6@ u9re*NWwÜ=um7C~AH: 9Ѐ߭J_`w+ )9(  BOG>#~[08 T vsbB" vu+wˍpأi@`P =~;!(': cX dVw{Ă5yOPY ń@!aq!?`!o&//p!܀,@K WVBbB`[So2UHw\`>!@@^CMvW ywTB-i~? Ba(Z8g@~bYBBCo15DkOD PRgjp0k ww!zhK D)[A8N9-jrZZA, z.bAW\Hg?{YV N#2aNua?kWeq ࣺF}O4Κ*WTqz3g~o~fufg7?0GNXI0MSKݻ1cI; F$&8)%wԔeiS1H=^4D5]tI]zjUK0ѫto!+(25>UQꇳė[/4(TtY iT h.̜hH ^;"D:C%rGY#b sA#ԧS8 η;re;V>d l/`@}ڬL.:Lo6L%ɰw__&lm3Zȝ:(HVHEJ%%$S/& 4*$%8dFF\yDpPfک;E+>`΍ P!b@aK:6tkz &]-ȠJ&JCذp4qd;A>l,j0 ʠa1&vNY3CAji(uvUs}+5;l:*V9ˣĥ%܋˔ViQsBBvRWkm_%e,d*!Cbg.K(~K }] \~*YCݣ#9/,i0Dy~.rJekm/3TL+]9o3dJN .~||^~nv_PWi~݁ல\QIt{ I9{1ƵH"Ӕ-EBj oEP'O9|qx,_]쾾Ѐk:/hpWܮi pc΀e%GFk9ǡҶ/Z,5% eFL/n"E"(Uw?JG/UbDHnԹAʹй6 dPf>|ְSG/@r#oo6NP aaSV(ɤ&Q{&om<_<.Y|X-nJIũUcQco;4rbCAϣFOrz$LxMv` #\c]HcRь|VuǴ[;$"$wmsحi{jl`;-)>`^wN`(,\ \s{2t/ޢ Y8\L5B<;30P=ܼob]z'ڢ/D7$28dQNSѽii  _ϔt#PAvc|؈<SGϛ\+RgUw.xzRHlG`I]-'m-3AUjcGO@&`Jvޡ{n;5q]&-\fnK%UMJŒc5~ry'E9ezOm ),*k8grIswޯRsYPCmI|d)|JhyړD8µ](#n~H3#X6ƕ"U j틯T1b[bVP,ZI'akE|9amF}_ʟܵFE3t(ֶFZ:cJ/ەxM䏩o@znMpITV,,+ZZTWݦK|b9Y3)b+ }FIȭ'oq[BXU։*ݥVX#^_/5XܸHGI{g;L[w$HZ>`y]&6?&Rq d*|Ȍʰ Ld7Ɉ{@{B4D}Z%GB[w73W2! {x RdЋk88? }:@wJTLO+.Ir؊wY^o8ibTI-+Wu6îZB\Ti_j/MlI<:<ɱ39~}2Mub|^{5 XRW?֒"#<4L ;,Y(g@ԾگS1 J+QB8cf42M &$G 6Z`q407z>R]2jF“9Y=7ĊW=YI*< ̚$*bVA, Fl Oa󃲆a?3ջbەAN{'_'-1}q㙃fVMU8+Wd0a#2} xS |M95Tbs~@XwP/36&#OO&R*ϽǓqE5ދYTqx8JF)am#"j*J7żST|?WJ3]Oo3?uqj /khҧl[C{OrKX>5&-9:JZ >e)ƜS1i&|ɚH?[>E'xWi bP-ۻDwoIpI\l-R%;HS+5OmK⢰^|g"JNh>L- x"%ādspϸaA -oY~~(̻űA%@+~+hֈww:z\Wx?QbנP}5sz`=-hrd[*|!T^\)fC|&gk0Z;Dmaz=1be?'tw{9E='ě>A2!ۙa /`"LG*#شL#B5{NJ^ <2@NYi?406:lxN ~q@*jf8Up~%I }ۖЂØѲG*P} vAQoc^GثucmL2&Cw$ZNu !&|zQQ>qbvKcl{f\HEg\N܊ɺnj4ñ$;Y%apgU/PHĈR#`23=\-[ϛ:66Pط9g֠|9z8:$=msN-ᔩ rn&/&IFhZ*kKTHSZ\O}XOe ; L_/&XĽQ_zK. l/ [ַ- 6Ua PmZ)u_­4QؑjN݃~J"r e*dS5_dwKDSmnVsnLS,5G٢7qMpǙŕ?FqI/n2u@/M5TҚV͚- V;d&jňk1~V/ya~"pgԄH SmwiZ(PI&lԥ|yJW:7"$]o8U.[{Ӛ:aE%.kX}Tُ^l0.`k̻^:k7 8Վ,u41XfsBxz0⳵kc|쫴I|Eay4]FE jEX,/'nvrC:wi>`<õ{sl01H"gP2m2Y LZ67#7wCZ|Ow)ky97t;% qޭTF'p =M$vs>TlaӣGrJ%]vIvڨ֏h>\.u6>Dwy kJ{'Y,F zB#$ܻq s4o'IH!_IkC|Fotl'cU\)t×5^DD#Zrw_ H _:zHpjQU JVJ`_FVnH4|+vX܄Ƃ7ndk`tz(垐ic5b,U $`KV?Vt=Cn|p䇮n't$}|P/B}nRdZ'l*[x{Σ޻؛1:YPV{M'8 &E:\ k'֘poҼ\1y%I#w+Y"nMCx &ϡTh1ǖJ8-Z18F tx{#?/~Āح>0=zE]kRi&QGl 7\͜O=Er#Isˉ#+nI>K5U4sAWN5W[­BՑb"WYUw4^2-.[=ۮǿgKxn(cU[oN(7wQ5hhh>UHʡJ/FĭN[1jT\H˲@||Ez/ cTEo>\}V?taSY6ég_fja!L7u~>]NV;ObSǧTbv}DQcgH{w~ꮓ4~e5^va8$F@֌J0ܱվ7 齼yϖgJ4{@6?g혹=̗ھ_:hRp.FmkwpjKVT.N="e 6~ۦ`sk7׺/3rm[&1 'U@f걓;w$/m?$;'ʁh#1ShŨ^X>7$Uq~k{( q*Y(L'V[T󖅴=] SG:ӰKyvl'E8Q PTWZ}3 7+ zm9q4Ϗ6n^q8Owg%!lϽ+zӑp +2NJIo^o]%*,Q*Bq,Rytݡ2Ș OismC6z ѓDdz:פOt|n $VL)}ّNJbj賭$1wseg3$]cFEaJ/a_?:N'&l2(r)ce&\JJPk^n")1lrY~,x}gQƌi~!Dmu=ʃFD $<4T抉εIrs kaGQ $Cgaar`V`dX&V0ҠKB&AE~bdd>o ;yKX#+^IRb39v$BrD)b~:$G9c;9576̝{ Cvǿ(nk7?ۑypyӑ.Y}{VO(?(nGиKZ>+܂D4m`7 N7 I'05)$[gΗPʞ%a' tz@$//f{Ovimܞ?3< 7$4_dA+s@^wt{6k+f9E}\UB[V7sXWy, W?U\§lTn߭)n endstream endobj 1398 0 obj << /Length1 1415 /Length2 6463 /Length3 0 /Length 7429 /Filter /FlateDecode >> stream xڍtT.RJI"]Cww7H 14ҝR"-t 4!)ݡ {׺wZ|{gww?Ġ%k +p.^n@^SSUs|xLLA@ #} 8 <^!1^a1  s(60_@>x#-A/R`pCapd 9skͼ@!ϳ_0WSm<ܐm& ٿ{ma6jB[U^\#G'|\#89y,kɹ"^/|[8WڶN;GLy4MԄg&G'VփCC W־Gȟk6ŋZXOUo5iD 6P~sNY5JzH]%^W%J@I7mG 5pE~J|ϽW-!jNO,]_7Rvi('??,3T=|<D;. `'D{u'1}'j~|H|ni73~YWx2G!vf"~TX7:Zr5g%C1fx;*N$=8ɟs(.1̘G\{2L~(T))hO$9H懚R(eR }|@9xRʳN)* w)d :Q6~)(M9l>mu\V|!'љڄI << 'ss%"_L5eUA!/ɛX3V* 'lYԲD72Uas_,ۮ}0dí=Y*(}L X?yӟNbbRo}zԨEmzZ11jC=GMI,I[n *_`b&\,ˋ 8/ RpOKDWbH!] 9U\p2)@DMRCVf &kFKvws #lj[SSТ/Ml/q1mjm w$:AyV[;)UQwlQcpr4.u~\(?`•[-վl!)nVLv[4 )iQR %C\>VN k$P@ծgMp#"*g-Q:g S_N}]\D9k4e7:->i |#ጙ'XN uk:>AEvi]Qn$Ai Uũ/*-֦&K5|&CL'.ZDE=+^>O9s1#o7k=OGXV>,O׻uqݞ\Z%R0USStD 3ō:FzScS?l"&eW. wН.2`=b|ĚPCT%5(;(!|`eӚݠ:J.{ӪMk\B+0@6. :+I߯vxJZ 2!#uL$f׉krBqv{Βv,0j2qyhhqJˢpJGKhCr,C]~G6NEkY{|H5aTo]${W.BB _z(4\ӝ9O+\Nt&EX ıYU{e;>w@5J#o*JO CdLt꟧nKA>'Tg40|SWu%rjx"]W,op:7߯A2hNDXw $c88͎v<N)ݶ$r^Œ4ng"B`+łXb\9@Eu|zI>$WEfL7ʈp-1nXsI?wslDY78#KpzpGjU.۝"gS}{h1Kggmb;z虶 ЗnØAw6͆9Kw҅\Cz!aAI!BqɻSI9Կ9Apt͙#(˦9[M?ԭ+[3ْ Nu>VZM~v]#:ۤYZRSώgFR:7:ɞ>"0ħ0Y5Jǹ7#1Dy>g|{NrT(ng6`Mto| JsmN! XW3CeFtLe]ے6ͦچٝj3ҍ4Ћb#O&P*Tl R?(RS4lF7]ZJ$f}4Ӱ_J,O"h), ݷCW9f );L{q 8 [?2HEio gS=+We{+\羝q~E3$CEr/?6V|T*,gX˒cB/~gG؀@/!Fv)/Lr ]_i$4^b"Ŷ }_`ܢga7mYU":4Uo ϒKte%}KO{ #Qa$~缊`;V.ߡS -"f|)j[fdAZcOUPFlj#- iڹẖe:cv%6gFj4`啙'_Mi/oc.j2cV)*\ā\T=&gLP0߃F|F1 WW<00bz348aԩm;WoIu3zxȩ3/FV? e0?5 $7`nY^CS*S9>㕯0EëCX>),YkY.͟?c Eb`%glImH Z,&ls +_f-l8zwsxAg:wLu $Hq4Ga&.?T"Ya'#Jl64V(x-|-]ǘ nNG͉窎.HpbXиuusYA< C^w> GљdΥ /57ܾxiM}^zH99wMLnBr"wiqaR11_NFֲ/M%Q(s?CjywGZREU. 3a7[cH۹Gű8+%lCgd 7f˦\bt/+;e_~I8 ^A-{8D^sWX|bqn;pFͫMzY+G>o̜v־G5"=Ƙ^ʎ: K)tU=YS7-M[wі"sDJէJhk.m(iR;ع>]*εmywu$Qq"a/K쫰\oY6B,+#zJ9ѭ)L8xn diuYY⣎k 2YG?ޮ1KxFaI~J"DWVJ jۋQڈ}.+0Gn3"7>T4N0~FѶ098t>6bNoL4ߺ|<'ʖ@ܫ;Bs5֜ɳՁ_**x('o"E0%ps2לA0:MfI'l f(k&,\o̗JP0!0Xg] CMYܠ|ݣ>Z[m:Jf!jG1[K# }SJq-{] o>|8}p"$1\50} gԥ+NQnl5(5fUU!լqzv\]9] >T$?vu %lQ`\ۚāTI)--/h[Q0J7~`UDBߔ^)Z$QFC?cɍxW̨&W'ZLʁ.gDUe<~5ـ>U^~j}ifԳp_,8`])'坃]%kR̷L'cY8rC|>I~I+U{JPMBZtNu8~1̉Xr#ZPEb2F͐ ^Az>ٔB28/i>U#|OqMծw? *H4%7rM"_g+-8;&"Ct|| nrf*1}T'=ŭ 33T{%fc}M]Er;ζջ'u'8ݱ\PSTkP[/g +VA7I:kDz+t\Z/q𮏻 ?`,OZ \bL9ϼ)UlA73AߥJ>R (ơ"{4{jm$N_y tcRf:I;S/Σn0켊HW02AyJAVRuZ,{r :Xڴh1]KdP#\'%>k(YϦamw&GJRg[č(f #Eƣ0|Y"fI6ٶQHlBlC ?ŎTnقKw1JKu.14ٯX'܈8z;es>5_{|)eU} @Fѳ>6^~SDpZ%fɎrJtaВ+ʖ-I(clRq*/콙MWItz\ݴThMUH뮎 ~tcf7Wzf q{Ge~H}"™yvZ,0̻-pPGy" -9ʒ*ㆳ LZ զqha ڢt_I}u%?*bƑ)I'iEe5qFz2Kμ~(SzsDž܏>FqYbǧgȓED 8GVCW$ !{=l1&Y|I;1ul@W˴ceݞs.Ebw㌯-a2QupF!*T6{ ?p1:*S}XVb=|!Yq$CMZ$PWҸ?<[9@RRZNA:ʨ#^="N`E^HHM*F)gNv,W@ͭ{o95u``׆ *m}}~ H~[M\ifbT Í؂ҝz&c>^@B0J9t(Xk@Bڪw{1g .lLy=353(l~P`} vm_[ YJ> Mۈuk[ذ/{GN2+FĒj@ VRO͒/ dT7|45.۴9u)Oрo^d8NBۼE-ƸPOQn1PEu퀗>h# KFQYEϑ=<6V#;SWѻ8i?9I0w /N's#h=ba_7؈OsYkK'hA endstream endobj 1400 0 obj << /Length1 1733 /Length2 10668 /Length3 0 /Length 11784 /Filter /FlateDecode >> stream xڍT- Aww ]KK5[w n!XpGf̽{vծ:Uv}MI(bjg 32她,,L,,lj 5/3 dg/#j7l2Vv++7 ?D;G>  :!Pٻ;-@cB `f# bt@Mv& RX|̮LF6NLv悴 Wt:M( frӮjgv5r^ k)z8@UZh,'XXNWD ?LLllA35()v3lM^\@FƯ?*7H(^='G=؉ dEi^oYTh vB]8hzN/`55݄=-(-Մppj?ͯx{^z̀?NF.@o#VV) 0lj_r谼jޫLl1_f1I) ?;'*jdd0qXYYܯEW,JۚXYS_k9hLU@?"ed1yb! &-H7dU{]j\Zy)`E53#+ ǟv$ hX)?Wd Ts~FuL^Nel?_됰53wl\#GG#wѿ"N'낚P6x`f{\\fߦ?FܜfYo`V^ ^߈7zج,fSAZ d7dc0[; 60^?W3 /z?_j$ml anPXׁ݀&sv&5U";c0')Zlc>)8̌%ٯ Y?/<Ժs\3H4'1{!"CmL}WDVԼOՋg!ޕ X[&U8CWhSdAV3/LJ ٗjKS=eOk}OVI2-o>#}2l$>-V[gI]h~`Bq~67 %ua;PYjogD?SU4O *pfޣ bx&QR磞<X{ԁ"i|QƑ )aāY!A_兼aPV+k 1-P)$-ҕYBy+Ma^]GZcM2ǏܱT7pTow]n x>/63Q"w m`{}e?xqXvTv2i )ʦ(.5'RJ<=-cro2>+_xK#\2F$qo-m rTdz(iA4LnFPr+sayQ1sR(6tl V!OwK|m>y:XB^6kKsFN,2R4]FjW^jPi-Sr[Kf\rIMa$jl>|zUvyc-S1Gga.L+h A[S:u}ksh\-T`'iS; O,kBl:u+\'r"O C񣔅^S|8U]vonyuӷ47(A<YX4L*ڑW mUfB{n{h$ml ݈+68/m6ǃ{IJ"77y34(EŜAlgDxPb8ӆ0n+k}K/QAf\VШQKoY܎.mlSϠX U.m\5@r(Fnp9ee)GS,o@_NsQ=/VxsiE&ݟsx_br +p(<%P^6a8$b3k]ّ;G0>8Z#s%$Wڶ1[K'nĺN v\"ZF5$V"obڛ-10f S+6q^Iα^JBu!>E̓3 (;¹!DO([- )cd)umWjbt<(O$M 8\xA6,Yu;@]I1I1K; ='wuE'A5E7a=mP*swyh׼8A%MrfPS6`y~SQCFf8DX~KLUDŽ:bDId<[s_{? %^)ޞ9?/q%M]?).kYD'^@)5n,SA}GT COU%Kۭ {mHU5azfQXaySr@ԢWm\܈iG+:!}Uop6 ~<[1aLM!պ5+Mj 4@P^^/d`~ :Q8uqpFiohW&*~n!'mo 8S`T92W@|ٶّY?uAr )qKO# Ac b6#RJ36&7O[g ȯ ^G4pFhR)d嵓`X|u'CG -ƩՎ쁖Qa t'e.md1Nj|$I#!鰑|gTB$y?[}jLc5&9@˧#=9#"b5]͆7M:J,lvguAAwxKG4؆v~QñuXFWX#Ϧgs袁 )}6[dޔqzY-Wo cۇRԨL8!j±o䍅iM"bI6YAG‘L Nsͱ'fzD 29SbhgqbZ+4q{6j%G}eہ?k9V5o{Wp\ɯ#G K/pѫ͇܆GwBNo!w k!w?Q2`?f-[&Խ1b)z\aCVr=D)ϧ@YU1cB;@syGD] ;:'d_\ROm 0k{–8;+|?B:i9RJ"Jʎubݠԁ+=O$TXOY Jj͜(Kb1@UN"'vgp BXnɛu uh:=qY׍2TdagoTM/ yp؈'ZZ}?]UddF4<=o!XtYTCEY't|&\YNR꒏bN\CxدaUp-h8>qIIey֐Is>T6MTj9Šޕ"ZodQƓx}qJ \"$_{ס>@X,Ix,dׁQ?@\ezʯը0nS2>W1SSYvpnktecޔb)$h+YCDbyfNCI5TD(`|NBݸ;$sZ[.ǰ[ !9,rpcY 2$l0h=N]ϚCqF{A栠U Ye*uXfY~/O@Iwʄ˽H; ̖[Pմ0<CKjE,h*tp#wuP-%4_?S&+oRvT=pFQFaKh[ '4UM>Π3HݭjCQy8fH؝緋Rlw&b;*. {wMqPwܚǖO͵ZwbUjN5Gf@#ǂZr'ld}a|[>X+ Ndɪ.H"Mmܖ-wCyR b7z(N2qS'};Vsw9~4 C,G?oaw]rӼS{κ8fyu:vh8ݒ^G"UN3`rO(M6V*ѩJp! "(0e::ǮEdn$t 20Y|vL{w&}; o-fV`#c'j\ |)wxH r?9Xd;32PNdX)1^wI*-zB`1O_ ?X77e?\.jݠ!Vo-08ɬ z "ABwV},N^Ķ3BBu<1tA=Z5X  k2%*eQ e,|D(x|(9}XKH zm3rgp9ÕE"@>Q!QSf+EHp"*Z饃8Ḳ: >9(0^,:Z"so:oT.f's(DxjP 7((9K00Dkٙ]0wMj G$2c.yY~KL'?bqǕ°XH@YR@q_J-' Iߛ"ݒxz6>&φv<i?qbE7qIiCHx p{x4T0"+yZ 4ptg7JƌR~nõX< *FX9BvVޓ3Uв-~oDֵer3*`AjLK9YXϏsU)ҷvףt:ڞ(D-o_/uvg kUf{u33bw}|AMV< C+Su}*$[|ΛoB6A)v¼^hC-W@ dB|xhooh B=uƖQCj`;7*e=^sv3S&Yul]6\`0ǀNU_w<}D}dVbr31 d91ƭ3xqE}-۴:}اʗm%} u1G'k*fL?1nj/-MTSLɋktɺNz>`չ vxJ9<}.cxlZO֗;R&ꇀP -J:⪳ؾ6 k# ԩA caҪ4 >Yl,5z|i6d#X.mOlӏrHOOT WPK]5Ǻ^N ?M$|aH<6dn&Zc:amb:2c&Sƪ͐z>IStxn~ P4Uꡒ짰/X}dTD.J u!LyyVdo3г2TۓK!* 7)+;gW=#8@8EM07nKȡ_XQ5%se69.^[f?ӰF;ʕv `b#s㻺ƅ:.vg(𵔰?:;R̴Q!d $,v XɏUR64U]'!78yQ#_O!TO4cTbf !*7GQHA)DȷWȂ 'OgwBXVi2^8XA \ʝ?n[]UTbg-8g-t8<9ȎvYCz-r|SB,=|!=69ٙ=BdKHR;TuxthK0LT ּ5 dݣ$ŭwޭ9CZv+IcOە,'Yl:-Ioj<36Ri6[%z$z-Z?la©uQB۱cV D^=-Qa4嵍߇= e B^wt՜ 5CO7Q%7xPFg{VJO8Efm~! O"a Bƴ+TE0@.֜+_(H"Nfu} ˓Т?Rؖy$ |LrЇIa?<~&\8R 읰jrν8 Tzn7Ed}l7Sj5bи +TN6](KüIm=\!&?Z9:6ѐ90l 3#Rt-r,wWEZ.K+Sy9 tfK Ж ~cj2'1gr<*O,ޙ:4Bٕl7C"Ҵr=MxaeHZZ4dv IYG&5̋.T{?,D ݌!HtS3h@<fz 毛tCZyvb,FAjA*xzK%ׯ5fgy:QJ;Hoq⣌c\q#5WSY>?\"U*68~Nl+_Kw|jlRxD*Mcc]rOX"Cĭca:cL5#F8S*`r̟D~A=;!A̻/3ĀAm2 :ΘD*0eg4~8: ~BɾK[}iԃR/إMl ES4r#)gYV.ZڻLijwxljO ZGWx<Vg?f-ʗDM48C?}y+ۂE@vE0Lw~6!٨ux=I r.'JU #H,i}Ђ¹ZXЂ pٵp-/b/^;ƪ{],PĴX .4ynT\~3}LυeO\WEI3B׊ #oB>l0uop?R/4yHkEJq7``RJ-FؒUxn4*Le)L\no j7f :+1Pn&ņ!Qƶd&ښV2#b@Nc1= f]v4m{ ӎ'2DAiRO++R) V7kNwiy14Yz~_Mq_ ?֢sO40||n h$?:go7L5xE8h-pkK\ݦMN0[W (Qm[Te;M0;-O?ARVVs{VqI?op 0K!D;)N-*$= 9V| f^܍]1#ϨiʣƺF8!fdVm\{o ~A88KlD6>[%]4 {keV6]ˠpl$R172sI~ 5P,}$V~" .AH3w4F'߽;T yhÙTz租h3vpTgؕk3`l_ӭ]W0C9Hq奘a<!%,Ơ/Ҷ8Wj3sݤl%M gN؃T *L1Q;4^XϽMzx0"N(xJuFV4L`<:5g0z[G=+ %h@ddT|Y/q/[Rw#}GOȳk ,MQ-ѿ>T)M yWSo~DP#ź0@jV:sFkO}l7e@"W,t5fGiٌ+ZVa`o.E*"g9݅ʅ@f&%M(PBœ5S9z.=Rs0K ‘SQ%6 ;=or_%NmYIOZv: Ek ۳kK4 ׃AYHe[|:>Kff.nz[zJIaznwކRp<**,8wum@ࡨqg)م1&v w&FJragz%Q r.'$?C&p!aXHG~w :=D\P#L7,~I>^Kdp))ierQ7<;SRx; )WלP ^=}'7turW: u'j曧k2 fhTJF u T__<&d6=PpDfbM]/|J+A!Hݤidl^Klyp+027­νZ7*c 0CPT/&4'|1"_Wrp\CUh#>]´N"8gԉcJޱr⥹ bV, Lυ߬I$޶N M˟qhb*,IntLF] 0dP> stream xڍtTk6] "  0 0 0CIt#RҡH(! Ht|=;kz׎g_Ƭ- @0$7?8@^SSU ''fE:A، n(& @Dia5w' 88@O?p7q h0MG}?'_LLt3 @= @B*!aDzzzEx@777,a݆!^ w);~[ޯ1xA,?0WK7T^MaQ݈࿡wN@o_MXؿ ›= uxvV#Kɽ1"~f,=RdSZIɞU/WWtВs=]^T-tͤedu"甞 q3JT9FWn}(: $`>}6boz=)JDڴ;kJ5ŌvWomlS?[uY1LdQh?K&Y|?OqI=vKW;d>62;ྊ%Գ7ZGG;]{s{qv53 dk~$ -RxtH;zU Dŝ?/ To[绬bYCgpb80{h~ooΩ4>`yf(?:xLW47DGxjrq[7>:AG^M-D=EeˍSB\`D TS#_W $jIwA:Q@D=XF |KhҎFdдfoT&1s83*dVmHh],|Nn#Wdb_x:IMR].zևe?cVQC6L5`9VBR,<X}0|Yf y.If#ڷF{w7yh K"n\ΜvaB %c2R!'Bz ԩ0d%pq9ثb $Zi`(ҾDMDOaׅ$%\cO'&RLF]{ۍoZ;1aɛhSCv9k+,;M;~Cl'RL?Lgܠ[ \"^ ͏=Zqw4MV+꧎`MŽ6 ڌ/J'WؿY{^ ^=%<4zjA ͓( h ;䑴"+RWy٥l( f1{RI6<[7\~߈ٞa,Nz9ZQE!~`ƛMM(|ǹDO_+$7u<^'drOkyp%Qek]*WSU|5ł#jgIBTv%^ˇ>)'.; jEX{n Yc[&4@b;_X@t]0R]1vC<&i2mfdml@/!IScFĭZhB0\yJg>qULw89rYO8H ,"5z姵z.QDc@2a3Aߚ?˫ӭ vDA C.PYq+Jnk )W1/րZqe-fFQ%uqMwЌ qmoAgw6LN1 &铵}}@No[RĊҚ.J)^$=wUfe,m#.Xy $ jZx~j?!&~~x:/΋ɥ[}qs6Ӂ>ÎRW'nm;).m7AI_#t<ޥթsNl- 04 yk%eDI4s OEܕkGp4 Y?إmSS^_pwc.WnUQP,Q-oHήXڣjwT3}6Q뗟їk)eGm3pU4X\YT/gF>H} N-&LZ17V ʥ+[kKyY*UZTCѹE!~8\za[*r䜼RjS-XP<,H LMR,ԘqRk4$7=YLy )%hHn ']6=.#Jm ܬex#ODY\5m_U .g;Uݯ;@4n3 E2eּkjE寧>lp8ƹI3ľ^S*Ci=N&qSŢpvWcŧh+CKQS6(hZ&SṖ~=O}eaBi'Ԥz}H3'|>A>L)e7SKD/7=C'$ԵTD咱yYq\JbBA7 /z*b4AEdm_rҪev%ť(ơC1@oF8ʪ>*J.>|Šݤ@$ޘ)5u \PoJXl/ܾpuM3-V|kLM @aᨺ6?'pPT+߬׹j4J3#*̔\'xOOtM3TJ4 ܾFWQYwEFaZĤ(R,PsY?veCIh*Q~LITЊn7>S7}?9ܭ{Hۤ")36tBh:zanMFӮeWAlq-86Šy162?g\:ԁ!+ )!Z]]mAIn!~Dǃj־^.ݪ)HrgY4ܦt Egw _ eOPY7_D?1Gn.yYF3h#˨a*KUU,;h.V۔ʔrU-kby!j(2YE:60\Yջ4ozI !e{g OtO0CYo-YDzym/=s4aWFSo7p7Q@= v~Lc5sї<+ ^/<0FZseօ`i1|'b5eEǹz8$ݮQ2Mi) GnK hlD(To%hLd;$1E,Xη77^(;ygkڕܒ&hm?҄k,E̥ܶ1urL{nD[;il"kzrB]>=/%ĆR^bђʸ:6Q FRev7i/=)\:W%7trax@=DE8iR%Tx״I?L;277̺*!o-@ ~,9;zM͚^';[m?{ 5f^~|Sӝߪ8I쉲-[h1+9 ZrUЪ΋ IQ>&-9i+I29$2qFNCl2K)GS&*\I|5_Ml6nw{ Q%lGY9&Zrݳ@+c ' VUgO{\%|Q3ٮ߂4}6?(t Nt`O8t8dY+zbɶUPh^yG(Jů~ךe#ۘѡ~}gBs3z ? w/eΐYZ=Qh&N4{ H5 ?s]1^^^ı,:%T!q=.͛n4pB暏)^|lX :6~Q簁^PsCJ}"k&| Y=(5=Qq_K%tǓ%M5[QΟ~i(Q0>6<}<aI -Ff;3'BςXq-4_X%ύc7>V㖤,cS&Q ۙX{7 $&|rŜkrҎvhF3<"eC`R<Ri &7Tu'_+ݮXU/]>zJT5|X^f*g_f1f*PQ[퉻^Z.^9gvHi# (Z78F5u3DZi1^ZNyD "1m EDnBs# SRO4|@-F:lҖ /'D9ƒ@1M S&Q^a:v"a'pA NKZSfL?]{J?8vFH<g*'u2ZO@0eN`q VMG{Xޕ@idrӇVKPt_.@iL]G#]Je0}nVmDq_\(vN>ZVSXeFF1jhzi%214@\CyHY.p,Zߑ̵~H.Fq] VvÈoHPZڋĂՎq0QIl/=KGdRB]0/S>K#$&O`Njtݔ._MHz4‚j0B-:?6|Ebf|[4"s,gmq̥Mړc?5n[$5Pɂ ›u*'TNy%s\ggv} _iL*췽zN@Ly1Ĥ΅s M&dD}䕾rЂtD_x;,JG*^p:M-xBb$5+իT2sP+HKZӃu|9r|1t_FSK"KBăVkZuH/}bUoIZ3~[w*c ^${4v"VOORE(E*4;ٖ8Ca ?ƫ #j݆asLa)pG>e~ endstream endobj 1404 0 obj << /Length1 2765 /Length2 24020 /Length3 0 /Length 25554 /Filter /FlateDecode >> stream xڌP\ "%xpwwwwwqwwIpr;3M2{UUMk9MNJ/l`pwgf`ʫ03XXլ\m5.V<:]A21cW=@ `aab01q fneg8]E,,]Ai@eJ ` lt25Z@MmV@Wtuuad`0sappxXZT.@gwWc;ߕ1,\:z; )fotT@63/gcSS;Gc{/+{ -(!J07ehl7v756 ! 0Oy.V. .VJdeq{3Q;; /~bV@SP۽?WfnVNn@iL@"2 +t=M-Wrd%U02n@??E3+SW wth7 =fӯ_eTVVPRu""z6&= ;גq7?47wpԦ1vg9jc)8zLLϫ m/! 7[ۿTvV^t3VhffҮƠCV.V@3%+WS˿o+*9XzA?:iڀ.K]Sۛ::1v@_4 2l ? (olZz9Z49? ۶@(,fj?~9;G *¶V1#NX;jA܀.=-_BWVuG_{5f5? jo ' ޙ 괋wZˈ҃(4h? K {AMMwmn03םo? ulSZ"z9jќd20?^p$^MhW# C<ɍ Y)ΣWk_Hܮ^5,S}z^P yI,6 +=, ڹۙ7hD2 ~1>:,ޫj,.8d8:?F&)|De/x6e#ѥУ0W[D7|qYlgGIRڀaLYbHpn.zen=0myiu{?mxJP.?b>A| fqKȕet2QNM4 ݒ''(0> \&&.SߋXʺsy[4WKVqptkqʼ2J,R/"[ dlҒ=UCz^ -;QuA"!a7f[7"Eb78Cs?fw(J GAn5ĽT,z+#,\=]_+ !M 1e5d}LSJ&ZY;9wM8oJHtܼǦNnx+ݜWs 4 iR^^>[b$݇c;iN4FŠ 6-˰"cwY:"Ym^Tȑ=,L)UJdd6t;fCQw8#,I&2#8tn,knSs"f8hZh'_;J{eLo7-]+)Kc{Վ<ZrD Ɩoƅ 5Y<̦w5E\?3}u';$\dw(YT> J[u;;~Snj l[:qܹ @* ŖgW(?Β+?HqjURۜώ"33&U]Q' ^JJrP4FiG0뉌?{2mȕYry5UEʰNDo3my|;H%?F} QYpիjPD%@A}n:Eu? kG#U]Hfhh84۲rn* 8M|} 7+V8tgAkg*hXXm-1emJ mro&=aiiG}7puS=$nseCcE|h.-Pv.P+Ժ7(aM(FN93!M@ Zu<퀉c`8j\P2+ցBnid$*EŬ +V.90l~= !Y;\ ATU]K&S1čeɳzljF[N#.6'y.f ]0TbBr^ZNGO4-IxUvѕDL4lÕdɺ@*BaDSf.7+7E+so-9L]Qq4% }+MY[',4VzqÕ<59S)r> Ρ6̲qwZsz*'H\,Xd!4:YstnX'FrM}>OܷW?; |YIm/!D'kXT(),fN;{ 0 fdz7c3r|oڢ#6:x`M5*q!4~"> |Dq>1l|r"1 <EX6Dj彭aE"Qr;1ACDR0i`;%O@L0Ox% 0PIXE6HuROLX8eZD\!O#-K=1]tF%]xTȸ90(?yUQ[DZwhDvy~5̙e/~wq R/Ѻ lo1o(HB?plgNY Zjx툫tAe+\,â6Ђ=fs2JP7,RӶ}rT aز:,8#šYs`o} QuB#@ҁmcB8ny^4ugx}}]%c /*%AO72_~`x b;֌[:dFt›gj+'ʜ `MwJu* ܉fUWb'A"$/}dKu1]GK ResT`|FR,/GJ%Wn4MWŨu\@c&?'-Ƒ%?0-n<&|LY Tf^M7Z"*Yi:x䕴%Kg'x )| &qu} .#A!'aHL:"e3s%~[`ib:w&jɶ"o)Om>#n0 -m &*E  =(S"_o[Kkߕq0W64-F)q9Trɸ܇MFs?ᢁmd}JsyI"-MgF޺yrb(EWءX"(ރڱˀ-F\ RxE˔A|-'5]Bؙpi1RL#m4S]A;5.OkX/BT5SJ<l|!sZORx31G#EH̆mǻJ.72իOn~N=]^ϫxwt9{VS1Qnw,z=as&b!jZgwXgP_-n(sW\֕1ze#fd~Jb~д{eܖd%}BgF SM7G-ov΄KXͅ׵Q*Wwz.&ώдQ ~,¨B]Q0 -ƹug^aUe?™ɖkxX %+nAxF9 {J~mFa+.4$$KBWhюm{;/` Xv  A8&œ[y-`1k<h)Rz,h}D<+ ؘ1{R8!]Ϸ{gP0.i}muJ>}Gh:!r<5}+!6J;]r)lvn7{@sYfyrkZh \b:\Qxo9|=Z^e47lZ,l%Riyi]Nr@ڌ'W?Np S\JgA4T s1> \߻>pKk]4/͘z~E_,?.NFdI9CB#ʉܹMX ufD@1(| H[m gB.{*6e*W}tqʛ۞wfrstX./Nz ݀[F!+uBdg/ XSiZȷxznh47k,u|ׯ6(L"$.$o*\^o0 ǫrgLeA^OX"+"2kԓeFWF﹊kA85MЭ[g]u((t %Vz_/fF':xN$+"ju2}᫠nМjc3ok[fXAm 5IOfL^GQsBA!F X=ss:_znN0ݳ+&R=7Rc@D[9i='! G!"ni&?:=L3V%! sȑłJ%ߩs ~R/x:@t0&-l^|o 4PD$^R3nWy"bas+7M='мl֮[,n\'aNYBLW,JK,%î̓/UU/8#2tDp?ig~JWƧޥŃ&xiYД| ܉Bˊ*;w]HW,ތj;&}T4dh芻j0 bmBpw)fҢxFzöoG#3dpiFdqW5 UwF$)CzzW}?cYRzWMx9D_+1&.06(a+ LOio`pp& tiǬc2,s⨺ VЇ:5@rnq䭢C"GYf%|ʁnջ}Y^rוF=UF.$F\͘4<=8ol`)V3{>/p)Ve]dK],Q $l0lߗ+7lQU7 o͉fȴ$$GKY坟͎L޼^NƋRn,7UV pn f%_Tf^N5٢f*UpCPtB2LOv!<{vHs6}LΪKQ7)Oj#uznQ1&7YzTy!܊Cwb\8jl8IbJd>1vF|=tBUjEH UC>"Ku4ƻC6 hc[[5MyF_1% ;8 p \#gw̟ejT>b!Iӟ2ݰMd۸2ʘVy};[$"`ǘ+ⅼ5ogaJԬ42EpB #vLq3Dfts"3|vs˃auʛzDq xYZ';},ɆPFC9_fvz8֬p|MKuܻ$ymZ\a;~d2y(לbKe֐C3Yפ)mBְDye&v`޽O.4\ْܾ ӎ*Uj/zc]"DBY6 F:A} uuC+@4c5KCKI[9`G~ݬwU9哴qu0ds\%kZ7p#]iKn28Ktn5$xmG 52*:Z(֧ Q[-5X6ר!k,8]h "1 =ˋ 1)9W-+֜\APהMF\u 4SyV3 ZZ7p'ļ*nsnOGXBGnG*Ҏ.4WMS^`pHnͼd(۾㣹_a/BHTNfh9Nt#}MTW4ԂӎB}h^ʭE cB)AYV_wf\F*(yFc,,1k8񳄎PVE|ekשl%J(xQJn2Sv.ZNJz*Q&oJ2_w5VwJ*^71̏<SߜGXD,ʛ7`pWPԯ&XkW(#!a˝:8lӎ73˓3aQNCvV#sO!뎢X|+RhG/bZpsi?)[@|vI!2>zwCXwx$m#!Wu7]jI;-7V $c&4ˌ2u X)bpS_sX"X$86o[qW{nrg4"WZ….7ObK4jXtk'—^.FfKI'[RLjoiOy2~>И^!%Pmo~{Z,uWak)Ư@ %s4# .Xu J LՈȐ]Iao6Lj^2sp_o4wQ\51ǀf 9QB0#H6ibubs [u&MqMW&ѣ,5ifC3C9;3ND b*5_7 \mB"anS\PS* ,Gi7(GJo/E0EЀDBu>\3*+ e`ד)CWDsÊmfG$j{Eq$0jDӆƋ}gKQ(ESt{i\tUSiGOL$q?sgʗ(ԺƣkuTD;1>+aƽ.mr[1af~-ܙm)wpm5ɉ"''y#柀N@6e֯"x8ֶ4V[؃{dJ3ŁT` #@3R EER@6v OVVݓ`e˦MMA_/E9n$BDod@1$m8l5Xf.=BJ-h#5=H~cyn,x/׺]!P^07.8b&͢pw9(i焍=Q/4k?i~OpGUZ&E bw%t;:zW"#Ztb, 7"0?<!R| T~RჹWQK>H85pHߋ)}C醎0C7{˟ejnHPc 1'EY^ g`q`= Rt(ؤνS>2jtWYLŚoʕ&Qz:bJ.+ۺ$]orvEɱi'X]qEG`ۈ~6='\o{^ q,=$nUrZŅJ-[t%^U0uc‘HFCѠ&a"1>|Z˹zUlL~-Y壖kcK)Q_I4UTo`+3nltds2+Ҙ_-ibae875PIkN7¿m X ~s1{/ʒAˑPPTFSK(LG>3b;\`<@*/ɴ0:ФeƏ[jw8tAQp#c? W&Gon:Ey5zmM3Gl`^.sÑc>ÿsh㒼bC:giCn#EF~ YqE1`?<Dzy.Ȣ$tUPIKeKZ b1)B)MzF)#KϤs,6NI[׸ M *|@Éz:a"uV"2=nss t9:Ib*F#<[GLAk$C?[gTTny?\/bNqeN=Wֱ̮]zp$jk+GbքvJ0(4SlZt9dv"#Jj@`<"//&䧐1] SP, ~@wYùzS^rhD!GZ5kZņfptVI21_"Et-Z!?q #7H@Jh,4R-N x 4ç5}*-7)xx~ʖA YjhЍ+&n: 5n:Ob]Y>CCdŧ|݀uYŏ:Dtou|ȋ+m u= #Bq9P}@ vl'rShvHފy hJ#1E|_w$ e&,T<9X$(5imknum粃^tcYT%NS[TUTuNGQJF0v^P.iǴJ=gn‹qn&qԾgâƴ I!ts 4XEp(+&j:σ"|= v󔻑L2R ̏50N(m0Ww xhWL38B&I>B$gf*> DSV z@̸kGoW̬:YQFJoGeџ6 ^sr]U䯣wEl?s{;|Æ^Z0+q&~.c )b1.k* zeIrΨ iH"fhY%=BqǸ}dNt9uqQ%)hj  џ2O%> 9ņAQ܌\|ɫJRql3C[CO+ "A$=Ҫ]D;gq*Y_z#4/*A ^kR@(Ul٪Z#z/6pc([qQ ĥGQw/G7xIg@eaM i2|2FORt;EG{L7t̓Iʬ2g:IS . 6uŇ>Ͻl*nwlcWlZBZu7D$J7JHCH5z4zn\1Ps:cp~+d΃XA׃^4Oi70_(t\=YR>bi_b#C8Hi@)/je3!ZSߧRmj%"8e/l[gKDl/ܛ/mDl5"h{cZx;9e"lK) 4h bA8 nY11;_QeX>4/IO%V6UOC'E뙚dzT) ,z"3X9 4Æyi579vl7^=j F5ֳWBjПOX\6a x\;{3I(6{ER@)VZXӻ9!+ݭE6%|^FRꈒA_MY.3É` c6uq35D~21'wrH pE~%ׇb>"čƍ]Ma7Eos{jELh%|DppE?3t`\&tSګ@GK# 6֜o,T] ;VM5>ZNt'} ʫp]TY ѣ9*`܋׹9f0Emn|=/R677Rd 7ҀXu9HZLN9c\!W-gl|,^d}ub-&F=0-F~-2y!8G̗sd0WG=\$G krNkScl"1/Sq&|\\b,mr5&Z!_OwYЯ%^E*3]1pqKdFepϬOK ӓ~+i'bUiг@FĚK1N6ASƥH~B3?E;ssN+KǤZ!meJ4{O?!}%gf SV׎ߋX=ړxZ=c<g-e!Wܴ@ c 7>WECK;OpU7Bu,A*O9_,=̲Ɉm6Y &V~YXa^b‘kWR`FBuPNJu &mcOh U+hAcc+ybLu3i#hz+ ҩ.Drōm=HJ6Ʀ{̢$%{nh C{g dhZ5)W4Uty.cS_NEhP}%T8UWJ@q<:]5@iBYqmF\/_~6fNq:% $ ..biV&S}C>?%X#S^Шn w'#AhtMXXnl _%~A%t]3VчxB핹'CƝBx3ҩGTK UןuU!_4:- KUj (tНރ50ArPoz{C:wT\= >٘2Zq*_`M\JhMXK%0 ծG8hc;qI5F"jSuntJ Z~0V!0akC\YݘF]C~XOץgSsW?qQ/` GTd\-gaE,|#ۺn ! ݲ|bœz9Fl)F%\k=˻p$,|`Y&{qTyzxHNSEXo7!z5xFJaɵmGBI#6$!q+\NSs>?[՗QRBWAv{lvbYyB5uPG6i%'@a! ޿]p%S T0WuG#B Z|h6:O!w&:ΖX.K@ث7o}=rl%n4zYEg T0U6[ff5b]bL$gD% u诞(RwQ< ,~pTJ-m%,T֐oJ2[;RӰ-Ak2P,#c@:( =_޶F .)lU9r!q߄4̐Tb~v}'T爛g`(*#igc -rp&8OCϹb$ϛĀJN+U7;Gr\9rtYn=u ؽU-Y5EW36N@Gyėˇ7qKث+Koo{:PjLBҀ5LiwTKW ~7m"ꢟZ HU•F&hWS*ۀjèIJ6KgQXƞEM>̉Đ&:@ԺGU^ b+гS여* h; aY5 eWV#;ZKvAEsC}8"#ބ.ߤ87&px%07/9hCQv=/:NI01Yt Mm%jZv!OXi),31&Pql#!Ou$ף8'n,"VR02]xP|jU5XS~#zD#yBllZ!eb޹= ̯:"-hB0qfzDq1쉌fp-dwDyoK꺤Bg!t*@ ,Fz0V7 S<, =.FČ_2˲e P1dom}AZX^$5dy<6-j?> +PXI#cH5@z:FWgMڃn??뤟; a<% [59 zobj[ll /#,p+g-OX.^k6'ؕ1ŀ!aeXp|7T !-",rӜ5Afn:#dᣍ`jf6r*njy-lUk\U`6kP̥u]V〼8쩝I7$tɥz3 YƓdz[Ϝ/I׽1 6@5:˼/QOk_PW Eggb@-a]H sXmQ'R%uưkZxHnV  ZJs_k fQ 5m7[dtTQcr/ys,i,|杓)0: r+_fdW3]+R!8]`1CbJBpJdWc6 _݈"ZQ6%:'zcx[:fM̰uZd,Og,?s$XUZiq8|[Z.]i?F FfJjDBkߊzXGԷM|6jY\p`f|bɧoZgOr^öri3q#T@eeR<7vuu[\M/ g:8fUoQQ "\>ngY&zljzڣB.:W)o3*M5yI$$5bg@Yj]vN [Ab~?Mn01qpa P> 6NCq}<ٗ_-G(tٷ-ŬtU17ӿG>iɣeW'f[rnvImٯdFЊC/̠63ȚJfh \ lMed3cQ,G\i:HA. !2 &A'`]/reO #OѢeŜu?>}c5e>.VD{'tR)7#PkbyIOXD`E X@;Ld~!E2;bRosIo OΙLt?) S Ǩ#:L[cVJ\lHȍEdՍx`XB->`NfL3ZR 1|H<3-+x3KURFy^NԸQE?G7rK]=L@'c4{X״>Pn:C pu[݅`EvlI1ǠsI s#&DrOV㈘_Tv%M9Sc]85|_1IlΰxڢnĞtkRsPdM g0ށh!+ˣ?[vǍ7N"wGjbr>/Q5Y}9wP53i<.-dM"3U!Ͻs87չ|/q`.?ThαMt-i %v{sl%922!3.:Us?sŦ[z슞{™p&Suf]6c1~GT8tT9@FGL!܃ܘ1?NcNA= BB/cNiyU:7uEg/n,*}|-ZtXJM쇃z C(tXn8ĿC54_⧚Yf.2am$^~'ZB:0H e ,s܂+P|8h!(ĠZ(*ջC87kP7QS1g&8@>y I1f|Ѕ9:1){^sG}XCoYL!Hy1:ǂ$:0ݻ';}@uXr[('d{a0 t-`A Z\d,0BZx;vkJAA+ݴ nV,\TV5Dy7ѽȧ2M-'g/C2}$l6Է/709am =5ŭd.Pvѿ~fMy]cxPS҅~2ʼ?"9Ѣy.`ۼW EaYlΘ 'AYp@{]ŭP-%~emY'[^ !u4^T9yJn zQGSMb"$gČZjyM3HNVBp ~|8Oǁ1d8h"X 5'~=+|f>ǣ֬AVJN9Jȱ%]7Ji]\6)xPo @xac>G $Rc~ On(F#Ş<~f@œH|}{'A{wtAMҩ͘h|%&X,кuϯ6_03ז62kj8DbV.}ؼ8xKC-v8%X-FT- vWFP;b1wf1ylxCPFټ72B:\|?t %yXk ָ+\Te0D +0r&~eBg';=ÍJԻIo]K uF`LC>Qsv@V-Y# Nfl/ oFJCI ,ڹsi|gjkt^h&kDq88) 8T$WQ2ubk@/HNRn58Rfkm'[ (Ye%՜" .bO#FK͋YЊFlD#|7&͞⨋"Ѓdk؄+UYJM (ԧ2Fڶ$P8߳b"+P;gS :B4_2-9ANZUK|4%^ӷ*%Wdbvr`Dt₍b8>U/!NL`(?պִINo+;a.(a,_PlCO%M%vL]<&/}N aN_[ `DzeE`.mt&GbET!3[.z);&(ݳZs26> D@d{Qgl # W(%!ȣ MC#lWЖ+ +c {jtV!ҚLi>>ʦ[j <!٩/$!G)CdV& 6"Io-CAC#E"8*Sj%uWĩ'G+&~?jޣjե /U!ϥ\~kiߐV gnSD`Vُf(VZ .|u7 CT?+d@ϔQ;] @MPa_BlH%0Zimg,Gzj*zsbEQbr4Gp5a_`Ť)7yNJ1"PMVlC[t[O՟ ѣILW F\wW3ϻ. G CГD&RɄmwX[XۇFfzpot׎_wNu]~`Rci!RI92.R|^ALST^tCo?Ʒ)t[|3+4U2) mfaMG`>x-O{Ȭe^<rµ1/sR3S^؎,GwqGorm@QwjnG*)6nٺE*؛šAwe Y9?4tB ޭAas} P.'i]cm4PbަލcKTbO hq)qRKɋn}0zrBsXًv"(P2C7fTf'w7$f߇tVBA+5lt;BtJg )?ɬKz=X =ٛ-^ ?DL< Bԓ).=%8eb}N;gzƐh8z2Pn,{ڀk9MZx\C@P@oNu5e5&T<EѵųʨWuڱ;`g 0VM5lh"Ω@ ky !} L{2Sα i|H>tHg#,`ƶiĂ@CAr]A (e]k kK#yF&&[.M>G_+6% :Ƙtz 4I2 ((HFU*onܦޖݭfM|*ׇlz'9xjQ3EY fh)чJKdO=!ڀ3 0Nk톦 u__x, ݮ =|ؼ!r)]o^KoK!}:׫svo^$܊aN>全]9 mq s.~cY@Jw=@y-iҽ?!Ti QGk&[PN[]h2w yE j? 5$5H]aÀYnA.b-["9\DoŠ|]M^2jla-_]_;A Պ#L9ˬoq9a \OIYV +Y1oCP;Gk;2}JzLM#<@Y;GhS\#?u:&F̆cqjq Av ɵ$(k1|+! "1a!|> stream xڍvTl7%1:IHnI 1`NA)IIIiEAS:$U@y~9wvv_++~}uKHPeWC!1!4PYP..cp݃=(+P Sbf($PBĥ!`0P @@]! p)G' @/"%%!G#`P$PqaoA]F(W' ]y Ўr@ h_n߅ N?EÁX#=^H{8hG1c 5@? PnPt@wt0 iCWwPK<[(?濇 RU]TJJ(_`PPX @CпCeWJIۥk<-/߱PX<,a 4c(w>j^<pK}]vmj p{k51P("]DnPnk\H>A Ba }4<|cW"a(_%,&P?vXI =7 !$ ub :Ѐ_Ap/lױoDLr@`I7 *a_d?'4l I +}0 vۇ+}WdGVM3xЍ^DG=mT+< l[韛" m WC7>Rd%a4VX =nW$~>OoUgL_Īkqm8Xc\yv 1|4cG49WlZI8Eqž- 4}÷6Ҵ?YzE̶XO,H!$wZs\LZ׋PN{v!PR'~> `-}|BBeP-[L)llrli"@lj |y<9P1Z9΂sd-ǦVauzz>f5Q.Nxw}6g=H]n $ȇ>쉂dOF F%f'?fma`/"siO[I݉x.t`DCN/ZC $jjJMgT֮!UK:t,TjɍwKRۖ̚Vr^}Rg%=ǭ3-u=ƱE#PνMW=^*t"GJF~^d%mEK z'29I<%T Qr\A!IUW95<krT $nuhV06Ek%jyZIqraP#e7]?O7Y^Pu{6_+t2;.CbΩ?h|nQP 3C7TܵH,QLJ.i kkbzu ^=C=#5xa0|;cx'X'uYް)?$ެV@^ylUaZt\wZyKl <`Oިf2 dGw `Aۇцbyav|Jܣ5y\9 q`^n .p6#Fb>REF?8_O&Sn0*[6.M3vU_2;22W8 B r*z>\'z8fIP;A%iչReLwxQJDZ׸y1fMv 䥼 vo#g6/g vBIJu㼵/:)?Ĵe&ZZS2]=;/vq+;L)R朌vgeR3((s>oh9~v8l-ۻzY˲Jټ$}j4:S%qB}ʷ[L {1,8S3p־*{oj50d3T$~Lif XK9%mbNytexf n^O[Cl{?zL)>+x48Qp=H&ьsPN)9 ZBn'$x´p#hINjgo;ݢ65*^$;X7ەPZv2AXj^7$"Kz'/Aé)7viruYB6+ʮ|&z-4a'XﲰCCU{BUߜ3dX\mU/?=t͑0-v(NŗPZZU b53TGwq{I9tZ1\>,qjiq.3CV,:HznoԻ>)Mn5t\4q̑q(alR*_rډbB3Z´P# b&t\҂LoYk冗"Fǎ=N{{RrO+xw4r[5~v=*(SVEc"Fh0ph0m_^iТ3\w`&{Me a_}j B7-fpi~vH]w xL6^wOeˁ{Gw#2(ؼs͕S@yvn4F090sjԣ&kϢ$i!Yk/rt4Wƞ{v4[gn˧)!~eVCwf|TO܉8 <״A5T{|1>k SS *j2[)["Bj6fiyjAGLbMFzxT2g]5{{f8<׈w +JNKNK7h6O][{RgSmQ:-nE] hu=!DӍ bD0?- xcWt![u-#LdR mLJ 6XsVU ܳy(0\EFluHD{;G7:y}=*vLjN 7,+<,Bdc7:#B9V籓IdwBBWjPc'Bc&{}DhrҿQrKz~3faL郯 ÉP {L̝16 f, D42xWh<95̦&>Bbݥ ++7rE/G]'xSHiHV"RuS*{n7TX}}8ӂR=Ke}U-tLUOJ}!m0InM>ȀPA)=ɒ Er ]מdvWCgzU0Gī_ wF7* RfO|G 2t*[G ^='u'ܕ%C)Up:-d3O҉wNdp\op21Tږ' ';.J1C9nD䡗!MLW6G)N^s)X(Fy唒̲l] xkVX2VόRB]%~"got'7B^My5hqQdHwk[J\Ԍ4hlH;C跕A7moܢ%k|qlwv+l=M*gDqpFByWEDbKx"L>ag3͠2! /S$jW.Rך)dģ`79l_tm4; Fng?[ J <^k0uc`R2-[>x M̩ EvJeGKX"OFMrv&d'ȟ;HI& S t38}ZWߠxƤ~KDff(utFw'Ŵƹ^n{3U7x)s{{lnTr C]HZ9BK8Ua5S!V7ds@9);H:|tqP73*;f40X8]E+q{iKw92geWĦZ>=Pm "syѥ۲='QUr ' 86*ΞWD0DYn>4^Qn ʹz>- iM ;xc(N $VZāLjg1D2{Ue[3f^hYTlHWٖk4;)}v +A|kMbX) 2lL)m>ʊlm]rXympk XH86CՊGR?8ZgJ׃T_[p}; Qwb˾dM[^PU,R3?拴aSe;I8篭BHD8tk9%y<2_K AM?+qș(g]Q=0QM/P^*En3`Rr3j/go9hhpz[ލG,)GhA.Q.>;{C %<+*}+7`rRDI"a1yWU-C[m7lө`7P+IG~RQNU"[CZ>ġTnRk'V߻9R\pj`k:Q%{O5Jg[ܵ =oܛE"Jz]@=rj umi(t8:mXK'WI޹:LFO4]^CM O9|dDWj{pࠗH'jkYNPMJ=䉮c5l7롢}xeۧAڜ0 c2_bR cBn)q =}-Rx%yu! >e_D\0ֵ|LTU8ng1Q5tZM٣w#ET1}>2crZ.tˮ`Jy94l4Gn+SR)1}t6,󰡑 XЛ  )2@\vmjtT'{FԱ J̴=1x(>[|b#`?M 3-a)|r;hC sul_!Gʥ  nT2^:Osy@4Ĵar G9L;8 $;YD՟)۽(VB[t-##Kj$n~udc\];XeH; _k7{;Ev0ehpȋn7|q~o akr83s}ZroH%WQJQ9k9}NYx:ŽlL%-\ VwHTP~"..CBȥGkַ|խ0AKĒº[n3ќyn:Q<++j_㥣ͷ8 >=)1qx:sowZ[vk]٦gl~}kLv%Z3!-:i:F m(iM6 Vkv{O}Nrg ҔuMLD.wf;$Zi mf^$>6aȒJ*T"ꇑܗ'2&m(Սl} Y2YR}nh2Usm '}ݘ춙m{Ɔ ՔDGL=YŸ}\.뱙{gHC{ayL 4 oWZr/ϟzk}+JqcݝfoFV92d6N4A0Ut85pT2VX>$R47JUdzqɑYSI,4x5%Wngqe#S9_ h ݙ#LƗD &y3vG'd.JZZG?c͊JɋND1#b, #oWE%녾] \#Ŏo S'>IMJ.>c!Z ;Z_1 ׹ ]"? 1 "C![Ŋ\QξQ-@ t4eo9$Evw7{j? endstream endobj 1408 0 obj << /Length1 2221 /Length2 17447 /Length3 0 /Length 18770 /Filter /FlateDecode >> stream xڌP\۶.{p4и <,;] <>s 1檦$UQg5w0J9ػ22x,,L,,lAI(5. {ŝ&2 w3E{-`caCg>;s P;8z9,\ߣ#ƌ;@ 23(Z#@@Wruucf`2sarpex\j@;W%;߅1!P>Z\%Vwp0q 3˻9.PvX_ {E do R L { Ml]MM@&'nU\̜A.L. ۿ*dɒvv@{W9޻;xdonW n '7Ŀ-Ed@W' 7/zY1E/{~>~ ;++d 0Z' 豼+ g߇ˬ"#%GwQ9x|yl,Vv._Y{ ᅭ}$ӧbK}b?b<M_,HKњ؁lW7Wtxm׺*Anv[+ji"E 4WYkT%klA@_ ޷pyǿUfm' '} ́O0^0%0Af?,%YR;YzT9w w? sA{ &{֦{< w_'l `7_=I?9 KwwB?]],)ZݰYkj>п7O2~/bo /KOf]$ .W.ar]{rpx/OzP߽  ~g:+-{\X߷H h?ĺ6ZqRpr_ -ϲs#2l mUVЦhH/ڮ$͍ ɋIK=lXkjۓQ~4Th2hDSf/2ѡ_xΡN%#a/b}X^/ҍGKy>>C#v*SR6"PH!m- eW>ɺ5BM0T șL( õHti!~caF;[X&M1׍Ğ[ q>QpEVzOEظ:gML媖M֭ӳP^w!~eŧoc04 P;c3)s䞓 f~hq5Q!@R:$6nk_Kr[PB~-rIgx]͢Sf&KFlBpe姰 0H'FﷸzHMk!XCIQ5,Mv-n-29rKuծ%1YB*X^܃݉=/|>^`v|PAԣ~EsֆoB./?ÖФ k nM།n~Y/)ǹF XDËJsȳ=CW8Mp<+HĐĻȐp%cUPRgl>vem>/ 5l,5X$ "d H}$5~ҥCRRs/v"H ^j2~1>8R23HH*+<+Z`N>ML… eN[+ b,HїaG2>yr*!|56Dvw߳R3^ȁt覫(zz2`ԚH0_ jjG/1^lObfUR%K6 <*i3=k;m}>ļ cS@Suvb^2)& Z+xvY|KmLYي]e7J#+KZ2 )i@']tT Ǣdy wܶPmw%q$\LnC.iFZq\AۈnfoG`/u六C_COb(Aה

\Kdd*nBHE~9G;CߎaݎּrPd r2?}ܐE2֚_s:]~ oȅv3.#+g>1e؝Y.=9? fpc-]bm=).Y;;a6UZ&OVqq~Wh^ 8Kg]XEuy";8D?O!R&]qu܇rk^)b s+)(O]@C8l~nF;P[IV&)BU /d)]L` 5~$adR nB|G!Z]#`J> |B}/W}7|c'Vc+K֬H9~)H>"`1B]04h6NJYİ^BBJ?CנL> KY\3t$(nɎ2vl3h# pgጊqFFK7*[t&ȏQ VW{ ,.c]]\{'fS X/k8< ~goPewNn SۣE7*EB&3&o5;hLnx48dh5dym'Ԟn|'ae2 r;6qn߯ F_rkYfN+b-`)=(̍w<-A|,Rنl|~@wWaї h;c>]n@+xk[9udOqzN/kN^BY>ՎxT)3A͛T C0(!F0}at\_ƅt~;ȜK{Y,[67D t`dT6dU 2tlAyj}!l":ݞk:ZTɿb}D3<,r/dVωsN+̹9:+'[ҋ'| J`rh,mR󏟘cm =["L zs;)Pi~{h!TTOq\ޞQ3icX: [M' H2"6_auDZK6M6?b " m;.Ku&I6%_CKQ!׶p9ѯי(0ˤWmKrx4p7l>k gT,aVQKq#W]FHCFEu0:GN&^ԏpq"?h ѿvS/r|~#䓌8 #yrj vs\ f:OHQ;PrB@!+EFEWFyk5FMr@49p=L#|]:+2debf:Wj4Ƞ&o>!(X!`@ڼ]>K[pW$,)2t1CIh/>w&R-gGb}+giY+*eܼ{aS6W~ !3ߟ]$k2beMc̽{AЖ3v?q P%{6~ilFj$[,/K"L{Tu~^7J ],QfrBxi3I xS徙kphh' }S7:09')g0)֏Y[$*բ޵WBzY69v_EM-!)9')`}N>VhO#5"킌@Bs@!d&]8\7˦:. u/:igƼYi+u.QFK%f n33ĆkyJ\gy%qig<LC-᪢$Ҍ^i>p߼e**PR>u}ܮrlBߤWPj8 AX "o&wƢo%XkMD>uuDAU%dL-%jf3P7( 6H%hZ̲_go|c׀gSD& i*aՌږe}$$&Nmdk:m O,?XCztRk?Uqwݑ|FFkyk>6K5< mnă9 y+\#rڅf`?7'g\&W:}WxbuQo!% BLyvFBo jpSR2: 3/N?జ2YdIJߘ90DUZsV9n= b܀۟uv엉-^xJ^KMO>配.}|')y64 m5pX'=#/Z2[AJzJVD'V|p!a6CcL56`UT@!) 9 N>*W*lz1fbVEz~n3Y$BI8.d)R U) <8Pڹ iDP ޠTG[e8Y_^.9D]Wq|ЕU?K(,K\|ĜtF R,^uVOb#OCn.AcW0e=u_ yy=f0js>5a^ʭ?>?ѕT*;O,!2ֶKIiò}P9b}1 |G +iMy _Tˮs1=S,u)Ez ͝q H|b0'&k*$w"2]l@DT4\;${pX:!ˆM4Sh0ذvO{F-(Zt=3TL\jp6a/}an Q4NYbBPqOHoU}Q^)lL ^&Q %orNWI)Hh'.V7_ BQL4ۏXsB9ڼDJ6ctHۓoˉѢS"~O$3~QTt7@+VĜP23^~pNB0=sx[gϺo@Yeo}"Px]F4tlim\׉m` wbBu~0Sz 0JGd~AwfiF2IKE\mܺ}D R#졸3+"_P1wƳ y|5T]_ v*#u7KѬ3}u U9HtSKg8{Npy?Z˕A36)7Dhrofz w(f,ٳ5AD;[΢]`ϥ:ƫ꼄9%d?`!%17g][~P%u)F#*f֕!kfWհd0lbݼ<4)q!bHHLg̓||{ڇeMv<ڛz֔9h<n'/r[RU*淾+= i{/Y_v\H2VrZ׏> \+gZӗLlBgftR="DCQH]6Fo#))\C|JH?KDViNS+JI髟A^4:B"au| u]szOB-^nkQh08Fn"QWy/?}sj1JYkԠF/+77fDZo<2$[,AݛjJ4_GA.} LGTG;xWu?J*<|ptXd DHߌ`nxuImc+\҇މ][_Pj*TDg@ZՊůDE<\ zDeZۛ aH fo "CI;4z.dA0J0NDАkH $D#hZAhMa"Do%GeܡfɹG)c¦$_AC-!t\Dz=lP0bȌsX%ҟ)#xF QNop{a}ASC"nhJ}Sx qPC7azk-V94cs~NǠ.|%irFzP "gcm#Щt;BB>dK[ 6WU4WVٹ D44"t<]IzǾ'naiT'ydǹډ>!EY3jx=(XSBqĴ *bέSOO\Y(aiX8JZ(?[y!oҴņ]YђfQ3[ۧ^\o5$Ҭȋc_[1xfiA|G6n#|\:д  KP?k2p^%ղOsYn5#*]qOğ=Be]ONrG6+]oҺ@eI4 0:wC2|.)<3㷒[Uα%s{zDZL,$? /(&.8׳ hUt];ZIm5qA{#ҽ&,M%k)KCix&ie}¸ɡU7mע>{ۚE٘yoh)G@.Z.YP t35#S[^@\"VuNȶ 4ڐA3zFpqW3/o/{'C÷ a6J/&O6#cȃD83Xm.o;n"a$SB)z`{.푺G4εBm{| >0ݶ U`&-Ň|y' ˰OC*lXrՐQBA" [: 3M3t@у9քگKg'\}"gP'Wg!]h0ӈ? ^j|7aNFVsr]`b +F,lk7.<>{^(/d M6ϯGC O|Noҥ"yF~' jfvD;d :xωF-74^Jn*Vfe7=TØtߔځn qЁ ϿN{epKvK˛cp^vK'}N6ló`yz50` #? YL)~]BCZݎڐeKc3s=dF(P/&C|&׋]N jJ^T=>bо,ϯA ͺb#{ AU|˳oSP!tjYI_H$`۸Ў8cOX/J\YW;!hIΙD%lj!YJcA4v=mEJq!;c;e E*-ʓ_ 4|*0O9.G晀a52+F*ؽ/,.YùB-GkיOi{a93V巈#ǩbA9,cs @#"!?u[oLD:WGLmF*gnI p^%[$"VBl#PI_+Joփ{.q?r!'آžaGi&GjY{* K?%A]73z HYPgo`n5*"SdiMA{DkV 8 K^-"Vo3+V *ыa*%MEJ+.x}SDn鎯Y88[Ò qun^ly6<yp7 1zGn4U6vi2;p;DJ y B k߯! "sh Ÿmv49#/R@{_.XsI̡F +mΒR<1 *gYPoOySl jYgqb3.$,Vfd釉x-XHіhKE;+ޭ:/y2Qmټ\uHQ|s1>gH%ְްE* ,  $U~h}J f†i7LxH(9I(kuZgXkڙBĤKC$ UrFb. %GYȃݠAwʒ~ 됍pbBխ,لxOϵnp?E#?;JE!8m%an5}+~jZItgiAi hͱ`=uY7 !Z+(hƖȬUQv< ,ܯu">РzEvtyq"4zlsZ +/EׁS=Ks6}0rĨ<cO* _i]!g֝T~UWv!FHKμ8~bE$)S-Jq6&Bp̗/A݌YKbo3~ 'Xb \vacwomѬb a1RF & F<%ڝ:Ow,_? nU:$qiW&Ήz!'LNɡӜՆ?ӬHUzDgn(H O'dcs903g;QH!#ǖ|j6;MݣJ[A510?- (\;߂H}i!zWUyt۔|Cx<'$c#ʏ:DnƩhJi)tww6$B)|{5o(K\h5MDayAt/"oƥֵ# Bִ{Gv)3?"nq$x1i(T%v.!^6ڤ @hy}F)0@tQ8_zzlpZ6g*(ǭw}C0T.4o1yvQϨA>M'ulURc J4=`VLqH2FFD1MQ/)[- v@`Yєo+c]IfoW I;M:ج5Q_ ?j]m"v^{Mgf{r z66lkE}k~܍ E͜fT)DȢ/A#}+; "F_ x*/}"% D]]NMw-eHřnݞH0Ϟc@DKPD]<>-b`aJlիм$H@/xBl3SiG^ՀyUB͊6q:Rչ$͝QON|0k"s~JqU`4sY)c%|(\o5Ӵ,VïHȊř'TSPS?퟉Gzs9qjJ4M+RՇsa;y(FMyy5ր,IoY"O}PpFrΒm1RRrr]ƌwa #?" *mռꁏ3N ڒUͥxP\URUg4+tꖻO=G6 " ur1t#1vN`0xpʥ*sZ]ѭ9>u춃n׶0Fyjվl7-6CmuJZP7%nlwFc#\D y#n􍏅ͽoڋrunZJtzuU*KxHL&J$M<dAka}vT*TQ%S몵t<[` *ɺ/gk oz~ߗ7gb$KaȃM/ Jߑ7 x6a*"xgd3vYn Ɔ l@؟/#}jk{PfHvnkWm}WQRBs2@{M i?oa\g](rY73.veh{LIƽMF ̸hmR;[7_qke&Px_a"5⧲Z8!ֻťu}!R%aۡ2:^NY4OW"[Kv}q?,{ѥM}'b9b 4"ML$nrKzm<@΄_0#a؈+¼0QzDZ:}tw1"O&CؓGՈCoMe兡hT _׭)W.B8hN sb4B[nYr1L;ٮ:p8Mz_VR9 '{ RAlyY7_̕\e;Vإ{VkWomr =#.T3oU?tk=}B|# oxr %]lBpXĤK諡V)~lNrTGD v&Z Ef W\Gn+{`)? S y!jú]M0)qaL1g>JRk֨7lha9[w)S#@& `\f ?O}H֝0*Jtf#^g.TvށO$(|h pWfb>K^R@%enRhaB#ň`]䗃2@R=e\\ڊr%wl W B3 +s f<1?±`>%66G&Ku/ zNq0;O n. J ,TM]oz}C/9Hvڒ#2Z*M((2JvG1Z1{O8L ZP8Xv %^eKwg$?t3n*G}%1.*Hfx D^$C ;5VrxXgt^!3S&d`rZ0"lBr~#@RсR,/( Caz~Eĉ5cc'C\wJoyzY:|TPv(#MpW2vI<՗#*$-޺SP2jwŊsv=9Uqp^#$eC0m2avn{ONaŮ/6U#ǚr8F"D`Umcggg*X 8%sZxĕs8;+L@>sR+ @}ʴqЊ0)'[t}ku!D-YPE §$ed֕`{ZIF"5M3πOaV.V&ߨ>Ac۟@R>>~r濱Tl3lI \Ff #)RHK)Nj3k2hN*ᠽUaf<3mpP6p(9-39ȧ#~`B"/npjaF̠f45#"t稲Q3FLX"{Å} B ƃcd"!9pRL T3tYhX30_L)Ͱt2mP6ۿf5lk.l9*:ljʘz?WFchU6&n/s9e[ L[AU9 6X /a[YJsmYoN`]q!끚=zC \%ˊn4ְfeKeG+NB^O[NԮڐp{#b%l b 7GnyLT'P+FX}*oڊ%f]*"*բ38YEZyC%(IsVzslL%m]ۻzs`P[9ͨpTOXp>ujf&uY$ڻ-D4*1"C\n5@׷Wȡ܊SJw$xdQ FPYfB !ŀ=`&LBlX@=E(hÑfJ! _؎i7eZsog;@N&T{,иH~tlHgeFЈ˥[Tx7W001\ yi31nax Y|:?C?\nP&B gXKl̫ 1"b OB4ﳼ][WfmB4jX$`uk q?YO`%NASo0)3s+@ 1 FE֮x+&<\ZU_ҍkk+cFӉzȉ֓|a}_ JIFtܘK0] ?6b@}-$V6րشQkxxd? kOB^^3Ull㶆~SxN{/G݊:."5!Gl-7@)QZ݆rtܲq21}8֣g-Uf诃] Q$ԇ2 u9-)fۿSm5{9!m_K՞hc'*=/3nuAa*iul j bjLK=(J(OFcm@3 TRm3q}xHtg6zo {X99s'Lޒm(xRWO1}!aC3f51u“-q-:|(H=ZU+?%gZk{#B^~faNF4gc@q}y|U8/j/zQP鬙#lc|^OMz\ʫ@Nq\Dv]ἄ[[Xe; omIkk}n HzrwTeSDF&y.٥tH@]H!b'O'j\{TlFLri@ߚm$Edxt(#?wruz] 'ʘ y o(T(,01iesǀ@ovbܞv; ҵ;&YwDTο۪G X҃ܗk]CA 0vkɆbAdz$Cu>-Ε 8Hxh|Fӫ"!Okq8_B/ wm։j߿L NIo;<&Պuqtm۱ b'|?syX$-©hKQa7Դs܆c5j O-q+X+l4P-Tp| 3w/Jq^LDZRI3C*s3"[?'t&5m@))q=͊Wcz)7@^rwG]2;o4sjs&j֒M*,w!/gGgNpG2~BjcyjU~E>ӊ|a/w/6QKՋxlD~TeEtw&׭*sHyqeʽWLR4T³dpU$a _SI;f0ZobO > stream xڌP\Ҁ  0@pww %;wwwrNry{R"y%ZACk}-#@XFILGJl`ThgojmP]&n(cmt02ٸٹL 19dV@{8RakW;Sc<00rrڙYdL ,J@ Ac`EOLgiOgmgGIp6u0(vN@C_-d,FG P61Gdmg ,L V.V@;{v4@h?4Hpzog=kK=+WS+c '&M@г2P_IBOb  ~̢V֖@+{1+?ddjehW6_Lm"ڼ~ˌVvNt10+ o%_׭~J$i◧ij(o?iPk9uf[0:edC0Y,@~QoX2;rn`?k[HS?T*?>5.(SVhB?K_8S6Tud5`Y~ hqe, hZT [ LڈRܟkNY837Z_݁@a*m&"rAD0i7hmkA/kZ_ d֍|XTuVw}`xL9R5r(e,ԝ%wW!'(l|P"0lngŢdnQg?b'8uG)A4r\̼:9n {b5!lagO}"}栙U=eKF>*+~pi7 >ig-;UØ e7MiEý"YEilsX`qמAP{Lo|+8~:SP*:D‰XAIm{(Y~IspxYH֍\m- ezfiSweOSa{QZ2goZLs4qrfr;?+YŬ߾^S bn;Ϫ\0Ũ|H$?? bښtl8#8 pE#iΔ:nF9mp&n I,T<(PlԪ>G[$WxA( *+(aPawC֯0:C<_~uDipn|fN1A/\uFt\>R)5BIg)Eœ+Ml{6cDZ,կ"7{;uvT;s灚+2v|L@)Q,B-9VW/ |1 /X[Q,2T8Jkc)O#I*-!0WgƝ)b LHGJ^cP&X"(ƇyfZ_g (_R=$-D"-c`cDJpÃmRsR,`Zv)#I0 !<\GWʩƚ(pha9TRRsi;TՃ ݹ 3N8;ڈx-\ P6Ž7gmQǭn\.]k^ J1dehG75@0N"\ڡ^zh%N|V̓]j~8Azc1oeΎg*i L eIC4#Dva>f"~#9Ϣg%3@]ú;qiRĥRFZbEACYBv!p"=eI%O36gr-1tή(y.;L b5i05Q KxgGc§ N&Ҧ$NU"X'Ƿr~lfDs"E/cߪ'7>F{Bg(F ɪZ[/U ;j={˩!L6',LY`JL}Pu(61jGj].=lIֺˮGA1^ ,Y 4"~bְv 1ڃ)^ nBR_9b0%SyǰL RN?S SiXs,EFY #ZQ7^1l Dl݁qP{ R`#ޕm(MtTYqqQ=P1餈onFzIَW=1\Ͽّ?RnJO^ǣ=!|&lfu6Ýl6TMF6$/0o3$3ݵNNl wJgb y^>Hy(q|L@z|S%/'n|1}i© 7ʧ ;%e8ա6i*{*MuX,(: i?܂I$qq7zn -58zrouVLA=?~W M1959=Ge#DbpziO}YPKeTJ':k3K>}M}Ծȑ:9 >❺[ XH<* j@Q /ZGWqq_1N 'xc^DI@oLH0E֘Ά, |KeN+d3_u{Xj[wuӗ9sB9ғzmŊ&⧒P傡W!H9emBeLd9lAMbB@K W͗A`jXΔM|־mj '{u/fF*#OQB Kτ*zړa5Q`<>z6~ߩ{Wo1߳1_QI~uE=-2,ؑ+_]#2AkL_-'(Gm˟X.l/U2+ay@Ʀ|E#A]Ď*#pHhIoOjqk)Y6`y>.c>ȵCS)S>ɦ-q+ )[ɼ*3>M&WfZUXIx4ɝ/U**n;IQ8rWIe_1ܮ:pB3u~=FgY\烤CQ!?cg?]dUC!zk^'}Qʱ@doF* -wR &j=I-Y(4ag՝^ ZJӦ1򩽂_MDڅ9Dx |9Jǡ8^מn׼: =L|\m];_ByKp &̛:1ǠuHK'Z34 OG(>J&Ś;,g$:? ;I dD[%Z:Iru W sG<:"V-:<j+56)N(´5]NS}Kgrzԓ}K1'}7z;?͕ muңOUPUkUSJ9Fq 0x>izۨWඝ,b*Mq#)bNB2׾he>iy"ʌSMRU'낸n?Шl'C֟ي!n*LGV:lq5o-'j ޚ;ru$a(y5>/ig<&^&cy-BE5pvYy Vj&)_̗ 1קyvue">5+b˝wpЬ!f1&^rῪehl@& xP# l;Odgv%dEHSw맣v6X:Լ![CDn1pEalNUǂ7KRXBVc=+ܤP/Mbj _[T}Fl`2R0'_P1oSt&c g+'f*qL}wwS>@zsn$=C@+ǙI庰bO}elwGb/M'a:NՒ^T0YHtHoKr`v_:omֿDH_҉ȁ'd hD4 %;x)W8c3j)_6A Qpm s/ Xk`kԚ`5 OdRTAihh(pWŰB 7g3TfB0(sU9mPj\GFxwqO# }U  \wF҃B]g8͚X"bC(I;;+HdDL:hgЕ ,z=f (svd$v&="ٗ}Ubm#$ TkZLbj:B{Ͽˀ-$j}$B+97<ݖpΎbvU#eϮ'Jmp&G>b0E#B 2h|[EsG d.%*HjV‹2s F~r^CT|R-uӅ%&6Je#ͅ4cd@ig.'o8ء9ѽ<^J3hsү2gttpKc&CH܂d3ħ~;_Z;HPӕgkQ¬RnT)YP;H@*xY ,8Aj8#6rQЙb77FHGӍz v z>]SzJF#p&W'>Fdblh%^/ JS'cAǴ%~H{AQ/pr)7oa/p }q(jk+**VF|CvP\BpSnU[3ӅM?ɳ۠b'=O{ dYB)zEp<v.ϲq&wS0Ŷ9㏼/FK%PKY imr#'xׄY2(%QGpyk mJVu3y<4H $/*AeR"5ڐi|qh|cl+{"$vEzҗi"La jnCOM4WF'_Ԋopn&Lfh6qz (K7x 8:DBf*w%ZlYw5dy^GjgPu_b!; Ég½Mp* Mz<-0/s&(6WPG#uqfM %t>}Xf\;@ˉwPʰ=Őrd?\h:aNö'z$aA_hh>۹SEk$1Wm<ĶȔkKYR{gRX~n j-~l2V n3pƸlJϘOCP }umd|7*IO:6WBEheXy8c nǯvS0Tkv} ++X -uƵΥ` \ }cWO ~`6㾕}D njU:}DJ$*_2N/beY%9LLѤz4b,&rBk6ʯ_d*Bw"Fj՞T :4`a!@WCo 1kmm$@շ9)$?̱[26}KX|稅 0!#lDiNL۴fHW[~-p}@PHI_i%cfe-* (4,_T~0"߁2]ui[=.2j}0N"#fޗIѯdZopcH%wA_^fZ0mRKҪ=ޜʨ@I xSAT6ϵq ٬@ATs73stt\e=: h ?V00hvXK`ħ>7 Q=Ҩ^}`Ӕf7w&0%/\,z8vdȖG =PwH)X5A; ^c ٔOb찬. b}aM=0Q!;kQ'_b3Dym;_zɈ94Gʄ IɪdCD_ iE[1fzVS9LV fil_zX-{qug/B31$w< y!*؁l$;:;}Or`=2YC3';EEF-|^7H:a&7Ցosב 6ʘ>Gx8\u\kJ 5P?Jq<.Hŵzx0apl'S+^v>͡MqbO{Η AV@>^ #ڎRhXP ~hPj=#ZQpP<^L"# TIؖSr)&w 鋹ZD׏fA[f)ŋYחQ|FrWVpFѻc MBhq;VÕ+ 28ҡp͑KSIH?"|y#.6\Fybt'PfΣ]_߻xBc[x3oҕJd?5`I:@,ѓip&{7y&#⏺$"¡V2#햜,xo%f=8!%!ap/"NXE!I  6 0gy# O&.4 nmlM}c~gMV[TGD5EFFКsWʥ:Ӏz^TmsybYTs"36GI~%Ԥ_a##lI&) )b;,̇XM\-Cng2,!)UHU%yj{&/?!Mh@Fv9*a/'AE{e;H?L#'|۝e:` MịpJ=~M_V5j ,rN1$RsLX]"zgMo%0"^|07F|[+mG2hı]:,)|QK9g]\;omw>cWtoOZN:\GI*њ|eulw$z.1 |h7 [? E^z8%s|KCگ:FoRcp<];bYsN~[Aos\Iarp>NUB\K{@-P ICkPs`;*x"kLy)3bO _z[U?QeZ=b?f1(>b=Ѱ\{+`k|p"'&Y2ZҢ.2?x]׃:|mxN7V2AW#4ҡjVf!X=vn`ZY%`7EِRtj~8fv ெ_!e(zh\<ā ~9AvŠL4.39[vMT[Ǎf٨Q*Y'nߐ)~vaOluB8tZAd+ ٚ:OApk]H OwV#[K|Bn=k hHh奣*!ׯs(sDQkՎO1,8 g-GԒp{iܘ!w 1 tZ`Ѣ,لh@#)?t6Fuho81k7WUL2ps^XZ?+xO;-O<Y?9>^CE˹Q8m}bH"=ᢳa,Zٓ)P e[Zr[T]8(R" "DjGZbpA*R\Hg)ݕ"~n^"LDoO;P݊H TX%[WDHb:\Nz`!,z8sG./n!鐂?lԳ5foØjnj^Ba_ncmݒOfRX}?wIN&vـ: hA |. _X ,ҍ8O=ǧmI>R͈ۑx0$YL'VlLd:NCYOgr20)⛶բ2$+v?b$ d:n;͔_1gar_/YY]06 {6S2%o~"H >*fteDaM׵qCgwQ"& ^oAÃT@VuXa_cűJP^2?K Z{xpqԔ^Ҝ;E-f˫?dI LΘ@pD?$[qefy4v2#=  qx>/QR䐁}v4ȉ5YcheaY=IHS9:jNu`,( bCbW$X>X,1}YWF}BMcMt9 J7thî[ӇOŷ8Ŕc rlUn{xy }E=~C[SKJ@4g(,JY HMl]Q-=P 2o9;kt ~@jzL/`_yŀsi`|")UWù-kA*{}A*ZHO i-Chy[Lau.^*!uQ^Ӕ޸5⦱L.rEƢ˸;7πvKtXAv g`fHi `1`©Ƞd&Z;l*TrѼOr|[nໄ8{nVNQP;%p(_'96< յ 4scO\Pź_>fO!ɃwiYx:?x]T\aǬS%(~C WY,IN{ۮ%,,MU!YBWOf;Kq@veZCgbE $@?`ӑM5AG)P)"x; bP>u"Ṟhjc ̓jؒ9m-?Sdf1eF4ᙤKl*D`ܽTG-,uPfvX9s4So#Jz8Dut^W/έmue[e ֲ&;I{&c#[5]3c}v%[xlKWnR(;^uz~C8Ev(r̐@U9O1 ?d^Y}"wdxrY M<5aB3jmS$R5iQ=YyLM9%%1yqdy'7d{o 㘚91IvǮZ)SAV|=}9bSbtHczM!Q4g^mqwM+uc*꾺ZlhG6]6̐K4_"N&غ fm;LνƚGxٹ1,ukea+EC31Xv+|=% =ۻ,k>8ȸN:97]3@ ׸f7{ ~.Ra$;K],m2]6[7gSvF8"_DziP?NL{a#o6K䊊ZLtsqa=uJN 5W;􋤤 "v\l5Love6YiRչҲ L6Ԩ|/Ct_ ~5lS3#QΘ+C ?Zm8$T&PB'%n-j <'=wvs3}*|3IG{s1h4JSQ-pȌ^֍F(gKodg_ҩշL‘xN4Qe OD0~ ;*e  nR\#mVW[HWk ȅ""mplm2Qm/i܍m4e &[%yk"cNE"bWhwxy:M%r8=DvČa24($}D,O.> $lLݎ@'.id!rgme[c搵Q@?V=l)"0tfny=eN(+(k)0&^GY*v7_ph~z]٤nE"9x3M֏ ڏTJqB )5.K;0?D(rw5f;om@-7J,#{pmSRB#/Qnth30KH B? ѩC+ۼcĎRĖ4 ;LNĕ_1; [j3vhG_l0 LHɛrg|>|wQh<(Gt9B6$ʗs/>,ip(wB ,E,c~A?2Ȭc+Vq䊂fY (@D.tu?ŷ ze ‰lwьD@"IfADRdE|~=O! c."I~'Y׎Ɣb{Z8aPb , َϖqTŲ>Q>Bv̔+I! 6ܤqKBijd@:KG9"x W01:KX8 Q@Vum%_wPJ@ ,:³@a>ĶO% _jfZ !7>ҡX%W[}dsS~ܑ췭VKPoUSt|#M#WЪ!YK%d$(KM0lk*6'mFݒl ctlI`4>I@-y]Ay"TI)z|rcҧU71ZaCҎ h%WƔ. Bzl#L)[O,DgގW5N7COcAGOxL k >MgB'OTmEʏmZW^Rx̳ ٪y4pGQ WUEqض:#xJ=>m3;M4P_`Ўq#t}3 ~F24 Ja}`RaԹ\sR]8- _X)DrЬ*cʤ&/][{IDOd+N/`JOea~P}^@hB#*TkM|JO!~"y3o&;+Ump+o` HA9Bƒ|ZRLԏ:dkne#V/CmLot{FJЪah]? Ǚ2MIGSD10^RęR3ht"мFTvfw$3_HGU;ite̝XGd'&)𨷱H9"F``c/ĘxqF6,dxnU@mz6XP5w;Za#A-hR.HK0CQ9(` YU1A o Y2Q UwEПS`˳\=/兤:.1јbq w5U2 NO1ZR}] mVluѿU"gv\'Q,@n9SF찁oz=+pu##+HSXoQ *i x6$\ VB@_4f8B}h~!$'аuTA滯սVrFѻ.(z2לz )د\O\!I%8JXVJ{[ƹ |'#c;C;z@i [s:||Du"bK뮴%iC7-\o=R PѶƊB/g <`/VU::,jKAEȽN/3Wq`'~gI"֦t>'U (=阃X4È[ڹlIqNM0'aZY*dm,*tw6ôv%-M~:sld_Yȗ4ϑ慔Hl ު2Kf[U@r\<:oYh'čE "߃5zl 0Ef28G*9_5p#z[ZznsAt."H'k~O؏@0Z\pzZl kЪ7Z_&ӋGsz]Rv-xq儽2*pl sPwy)}pH̢-xFp0氓`;x˫k[joB&' bm-kIUF# |H@4%^/'y>6Z"“oJjPWlg3q aC_ч47S ;[=ޕtu # ?' p# &w&Rih;iYm}ɸ9]m>ۛp照.ӯk(SJbf7-EbdzoG:҆d 0 L*IOnsѬ*G'V\w9grދ$_nd0}Z"QNsj=&~0VS+@yfZ>Hb9Bk2R9ьߌvF̘ynOz.?+.A2[H׀k͝LS۵\h #GүH RvB؏k/gZ롵 x=٣D=_I λAPRԩOG/x'Bak3rO/,{j2'3Cd w1ShBnZ*-(R?|t20 \΂D3x&W.N΍&@wBzDsG3`Imvҹ.OLxD$ Nf7|;k||fmtvz5#CQ.LXͨ9&yB %'R]#{eG%?_ P2{bޥKJtieG;slj O3OJ |^~},2 VJFF g{lyA2m;E8.sE~Q q`{7T<(Щ >ydЊTaL5{|` endstream endobj 1412 0 obj << /Length1 2453 /Length2 15561 /Length3 0 /Length 16983 /Filter /FlateDecode >> stream xڌeT[p ww. wwww -8ABpw  N7cks(ITELL,|1yU955V ; %-Rb`3$7v;dlV.>Vn>  Vfy&=R_4V^^n"v@g+Sc{%`jt4-]]=<<\-iV hm(jV.T]=hrr7:@rEG?r03+W +MM-V@+/Cc[ "cPՅ. ĭ{1{6>_92[9c!Y],,,<:%QrdK `jgeCq1v\݀~>*!̬L]&@ +{Ab?g+O. ♙oYQ]SRYߦU:x|Xl.Vn/)[?\ kvh'"0@z,,߬E[45YYzDa7W:;jbyJBDmF^&V.V@3%+WS˿iX*9XuYYXk6οU@*oV {Sv `l"''f@Ͽ `fwp@:Z.N_Y70F<f7+o`@1e#PLS7T~#PA7b0F|(oʠ/e@F K+()h?3?b+?f'(-pp%]_`6RGu \@4D.̭܁A? :raYAEXA~CGdu;7u[ uk3{Hwdv=NBvP6'7sƬy8Aͻ&hg qbkbG PEӀ.KfWKgg jP Tw1upsFyAzAdPP? (4_5"yS7gЀ]~)@w? 4EXYt0P/B;ǥ~Fg Mצ'-W\iRVR<<@"ÆW 3 B* %K~R,nFנ9i՝6jvу" qUQ "-/ί3E)[e>nq DGjĖ{̚. ~Qd΀/L+'z~Yv we(DP2r"ON!̭%-T\rtV:NQCpj.o)#R,;x$kN<cjv܈|*_!=Nx4EزfšTH{ ݛmҮ$WaB& pF>)RQwHXԗ~&{@vk_BRM3uzhϴ]_碷z+qJ~>Bd)}]?X @22>|!9Z`M) Adv9_N/[8W'`-iF5,wj*e],=|C4 )-Uc&r_%uS8p(Lа{^Gj՞zM$]!t%Ԅ#}vxzQPF<&0c\X72bDcb^IӋx&Bj+;{WD=xcFǢZצ5nrPkL23Q2ۺ QdvwgssWFޖ3bnz[`swYp;''8}ͨ)ąm=yc0ƧCKY_L LNF nGJ186|bZy&Fm9* Z{y{l>]QॾV|R=kvq`W_=m˛I$d!Iܬ<.J3^8PTQuWPT!@ƯAUҬ_ZL;4r6Qy;* 1K5|Z0G嵲42օ>C 8ESg)KRkr$r~Q2ƽ'#5}߇fE*g8{?wy0 kPX͜]8ط﫠^]Qgbm_ K<>>JuJpǶ]Q6/ 1e.зrtCMPa^uw}]xLdYbF1mYnD᝟DoQofsҘ"]ZX#%vI+ u#;r4:ZO{ȅg7{ $^3Ҝd&^tŎk&˲&zv(F !kr,b u-#k Ϝմ7t|0_?29ς{-ƕ̧uk^$vvQQBxU gN؂NK$q=6[Q7:xaRYO{;|Yq7d.o;'7Z,uCJ\WaY"tbʥ!A2fkpiKLJO,. Q+G[-hZcą)Q9чyB\ N !Paq( dxɕh=0SLM?`Pυ}э6F[[E̮uo"J^N^Ai$;d ɔߪe53Z7#ǹ֘]OWue0^N\sKH6.ca1za闧#wHT̯:עGh7W';t"aȞU/$^UAϊ}uįL;:FV/$BL؈г>0szTPhNsoB:~'KrLTuA}f\%0yѵ40s6*IoLY'H92ő.yչgRI m0qnUo[.=<IJAº.:k83}=*}ee-SyWČOBIlI,e'WQfsUYQs\A:f0gmKk݊O[4\L8| =wEθy?͜ުӃ@Wx"cy+3R)t̕=sqDJɣ5dAJbLi7JgRs4z etоoܤa&c$~?C4  eeK "H9ƏJa/sbXF?sr'Cr,q 1]1Ag}H@|c-S<sh+j:ؤnx]" '7"4sRڳi3N9mgjųWe.cW͹gLYZB"e i$(pv_!_c#o#ː>DβÖi/))(K^Щv*YA9)p=⹛b0ڳ:gF^]>fzvI" &!Ȃtp$4Jzg'9<ɯqQI/#.ш9zV>4ۜ,R)_B/Io-<_{ zR,Z}Ɓ?jT>ONjX] w!A v"!޲Dh/>è)ӡ]:| \nM) %ڪnn@?űE*~j\]NZ_RK##IWL&ȜxѹY.E1n7+̸`;SZS p5,zƊ`Ĝ"g0~ҶN:-*p \6_MgB3mbgc bډG]j>e' ? %ukQ5UCǃA]+7Ǎhdvv !tW8qU2ᦥn6|zۏIKmX*F=6˹2MZg<]nlżIOy@օŵ\O9 x&c΋T'ASdRj7پNU}e׌쥿j,$Ϭ7hk⭺E݂ ٬(7GZ௳Hďmħ +\:p/]w~[tqxGF]DGN:B~IdH/gkۮnLWY!HiM'+C!ǍքX`-ťҝ|2t1?,ƨsrBO .`'t-bU\ED# 6|):A(]eUhKnx5VGK(<1a\ Kjy*Ì1}Vrtkv!WBᏭ]a3$9P0~N+9pMR<45E"X7z-׮oªEl`[0gӉP((v 﫬9.6W6.r+A ltIeȎLx? ]t9oA;L޴m(`7ᗢi*j͙DYc*x\#FC!b-M?fL'kRDZn_^RQR}N9DHdlJiHsA7㥥 :77I3E[LA5I5\*Q ⏘| 7w ݜ- 2Pˤm)G3؇E $ m)?\ꤌBv(CMay$8o [nS5oOdUW#;6`Ndӹ>BuxHI` 8HI6LM%3!r ,k؋BUUK#Op[c'5=*"8BJ4͸H5~ƅAt;.h>e#~b+Yp@^,R%F0 'Q7qH%~acmlq'Ys+J3aM^Ցz Cꩉ,B̟1En_siAx%#֔Dh 5<`Hٵ{Vk"x}x$?XKXDb 4r ږ3rR Qޛ%Pܨečv5n}:!BxgC,NfXED恽)eT'p񓐅fV"C(C|iã$V%}_WvW6md3c9B:tBC /u] eJ.6tw:_&9ٿǧdFt{:(ǻlpt/:Fuu.N.T;隲V+˼,P-xMPmm ZrQS*Vo2Sy 9掬)q*d=̛0--M IRp⾄twcSe#MRL!7a~ЌF\voH-&D0W%z |{9e#9y գUlR~5Ӊ^jPeD$n͉{or1!Z k}ΎO~`+x-@+sb,NNx!Ϩ ת?x 9&,L| T/D\i#=UW^MCB*<~6V\#TX}vV|xBHw y!tvlخD&A}n7);3%J'$$+uW M9{oN{żWىpGuֹ8VmuN ݨĻ6R*8IihK<˳^J FLUG%tL)MnpCuƳV>yޢX@\ϰDtB%EϠ A<# } d d5QO#>W[*7YΟ#X3ٶyc:k!Wf[K)eƌlbcĐeSwSNGd='87`lv}ͤ j&+7}'KpqTj&ڃ䈎y/`-PRM]HoJ,:Ex!^0Qf4 Dia<:]+nh†QbiR^K;/xHO!\%~M7;HQ4%Ϋ+Q!-+?č \*YїZK.b.Iٮ1p6(A*IQ@Dpx9q3*Mī|} MD%J%D͍ OBշ  xg5+$4h!6r#^T(N`nr)z酘wf.:snwڌyYw]-dR` {/2ХL<\hQN| S_E0_},] b|^Ϣc,'Bua\?$LHϖNQW˄u1 :fP$ zCFJC'[1<Ոt9"C:f[?@j".)zT"(7ȥ<$ 2>U9!o!fLNؐXsٟa;!=)%'e"?A5q) q=w-m0f]L]Hpp /08~e29/hR PA<22oTo]og0G21ؤdrj;]^+CFS `_]2p `ʱ2dkQ2j>~( whOMWb/w]O@B6WtLK?ϔ 9_`U;˪&鿌ǚ3]hZPQhn忝W m E*Jɫ;*p3L$v Vq3KG  <0Ĵa%xIi/;UpPdZ;Wx f7pLEP&ٛ7rWƪ劚0C^xׯr2\I>_Uk]!mo6O,fp}<ŻmhJ %^@] wCkZ$n{ A_>~TdM!z "Cd>,nU܀ᩐf̓EǑ8k)datyb`=pN\o#;-{muwU?+_&ctB3߈o (f0hIi}6kxuc]M+<!E\g )tF?hQp? /bƔom5JDwU'Tq=«&Vhώ_k,jlYbwSs cRFEH[Br/J_ q nM6w*Bm2=K~ Mit~ΡG|Yo`{4!]f, i!Lո2X 3>*b$h\Ŏ)KǑ}+SiSs~T%wBp|]m3[x۵V{YngX۞{WZBeM 3H_<}x=OƂ}U#~Ƨ I &ے?*~Q%O`!{$ v|TH ow~QRϕջTw Vx|l ?$GeN& (Za[y]t8~Ζ<AAp0Le84 (kͿS;۲=ۼJiF~Ԣ؆] | r\/q2gZBo@|8n:󴛺aS@s#]Tq· `cRbH*['ɯPȸmQ4^!#]5WQ;2nm6"4f>ua L7LjC>ks{19kh.|)KѮJcZoV|+i͂waX΁L RHJZ#a#Jf9ZprlZȌHHn~7C_dw(5@1( Ԭ%L) Jh2)`jdEwTo7KMKϒ}9)xy@o =A5B}[U / &5Ϭl;^TȈ HLy3PE&@_{k[G!"_cAlh*ܡ1MfG".iNSZ&SDPqV|y#7RBM\x'jKh' OO9W4;! 5Y4CR-]YpEnC$P_7LH ;eY5s&xi_hmN6~6gX=LYLN)i0^ݼÏOaU-7& rpyvU ^ 䈺(4~5YkI㳃\LM x`_ZBNe1f~mkN=swwx Lx`fZow!V|e]Idno!`f^>3QɊ1ԋ0i գ0g2dP,IAS \gΧNZ%zF[!׮@ ُY} "b ĆĽcrK~UOO['G7ЉasIQ+ؔ"n+ [S1Uv~w00}å|Qmt6Oj& ssQTDmݕfʅy v#r[1ef9a~>LN++ t)m%efZE_*Q8ߥ' W'3 p/2r, 7޳8Vb/sqQ b!S}P %=bo%DʥYYGX.Vu\gJs2ϒmsmcq~3LM.y ;C ;F`X5 (hcNcj2վE>C5A )<0//|!,?*I/sFQ{#*iB_qrt& IW(oAas^}$.te{rh.cQeI eryKZ=um[5Q'‚Fj_֠K>\&Qv۲g>{ 4 xO?54b%~x؏{?pFr++yO;x_+#4sn]WEb_YՌ<XYx?JjL'O  3 ׀N@6;{l嚣-WgR3GC,7aO=G#WPz]qY!b)"t/ 3q.rIզ&St-܉Q~[(e~{^H +4;ImGqZf{a~ӉF? 8#NnxVW EziR"ڱ GBҎ%/ >1dNELji$m=馟\K<iZi^6F{IOr%^'{_ )ܘ`TЮ}Ie?[RxmܭD|.{Ǔ";]n-SYj!j"&iL{,&תV +\3o,>bζCYNVBuGDginT tt-cVdOZ. /쬯1󣳟ꌘP3azcp/*0 loOܨ^FiЛ04,$yՍ6 z='Z4p?1뎸0;;d s P/t"$~KࠒO\ό.~Yb+i(ph6%pHRuDidK>[4؅Yr3/fi wP1pjdYf-Q\B|!F45凒Bd!HZ2."J E3>W`f_"6ܒl&!s$Pt%(ad>{QwF;Lq^S69\3嘐SM^w[˒E>K|\P/ƨОu֠Y)=JhٌBl~@=:ڴmۖ( &] LQ]Slj$.=wX~\ OӍE[wLCM廝Ĉx$dna7l#nxT qZSKv,T]M'+1V[Z9xZ, ٖ=b^%Nɢ6 eV18N}ާ◟af%veh&M=Sɦ7c. IVQ 3Zc^Mf0(|0 ?!tr]&ŭ!4r8=h>ˬuTd^>[Bʰ.( k*s+ /nI׭J7-H;O )/gL [jV*-o+9^Rk 9 t{`Us[TϷ^z۪'48k;du#)_ =}iʧ`rCD')e$)bQG[ҝۗ9b^LFI4wsN h|=d؆o<AV!3.&(S>}?+A~q; OE"o 9qq/&izùh9*d/3D?#]iV 64Q-rZEIKضMZ_`()3T>h׿=5~p!9NwWhTf!fTȣGʉ l);٘dh՟quz[YlJ /Zr2R:ypEhEIod g١E4 4]'5 NEiiȼ"armZsy^/=SUgPWpq V,aB3v;.+ދӹ.A?Uo0Sx`Ӣ7X% Ҙx wseMo}W(z%aԍt}O'/ݦ>ncOK!a09V}Ud<kՆ{ʪȪ0o/V 9W7?ڈOe J#yM:>oN ~$VP7}m̤DU݌`d|,SFTՍj<u#g٪z4I~c6^rÇt6n 㷧[VfNeU:\d!XR MpmBamwҫ,`-R,U9{( 9|6Ö";!Ѳ ;,o33lj=wR\:M,B}qrʭW5]|f#~Ug1g`OIՇ?mNyC^W~3ʞ7ƎQG]XL@4$gI",Kv*},d3V_p#9Ѡ(*%ʍnw r{ld(Lag y}K6 p1y/#R;W|pA |Z4Bz&S ύb=I`e=o7ն2IgQ]4ܰLiq"4j M5T.u01i>0x+.x'n{#qXb<@ R@jiΈJ fɬM,}j4(pw؀Cs%sƶtoߝ bPa6=l^1K" endstream endobj 1414 0 obj << /Length1 1401 /Length2 6058 /Length3 0 /Length 7007 /Filter /FlateDecode >> stream xڍwT[6R"C7 tw03 ] ҩH(%] " %!)~csZ߷fg}]{_^aa㑵@0$?/H /$¢E@B<P8L?0eS#Q@ 8 Pt~ ~Q =$T0EupD rܿYW 4HG+-ЃB!H`rD"$y^47 E: bBƋ;Bzp{7 .P[ A<Tu@OEr~?ODPد`- { RRE 0'삀^` :P ̇!~Am"N !x?Sz@lQpapo_+{(vn|0'DEeA H $@#n_Nf np75$jA#^ OǿWx @0k{@}3~7 0࿎OIDX;>??# Qaq i?mG Mu;&E\A [ԃ_!?;Rtqg `WH4()j\ *H0J 07P@촡H[|m74( G@-?_>lQE_.J=.P\Qz1 #Q!j@L@@?]_Um==PN/fZkKojn+TrV)Kͳ{~5IO0s͌rveړ%#4;gC>Y!s)ʹH4Ş%=hjDZ"k3L3$NרּUSM(:e1wb5bscE|1Xx n 90cjkX/b9YXŚFi}xp2 ZHTE-͵8o1!G0g<-Nx}:lI Ec&sXsA$qV]66Ϊ3okb.YnCZSh9iMX{#+= O"pRMG4sAIz [&^-pz^&3c\сi'%m=oD+Ek{UZ\]K-b4'0Xz#ᬉS:Qqˋ Png "eS?)<%C2M@GH-]D)מjZF!&gNHݑkN4dRyd2M扅}Yk 1tmb#Mp Gգ9L Ӹ^䉁ØifԇGz%`l恼GL{?u~dٷZ* C}Ce0#O\鶲LGnKRMz~9ei#涡hϟ|sa>9ݡզFǖִ` r6el:&cВeS @%ӱiGHC b/VD~"J]VM$Q& XsWc ?J#OYj1ۯM:'u+Ew"&LBs 0ݰ>$+jDk֡))O*ɮZb19+CoDXF̽GsV߰  }Gjd"L^WW/.Zi!M9΅Md[֮@&sb}ApP9ۊM,IΕSsKJ;w!\#-)%tipFT'݃@f & %^n›W.rv>K]7$e%: :fSnTQ}i֎L˱kz]#7{A" l81`ڗޏ >&~ʄۡei*PZqՠ*Ey F(A>+ufj\i{[ ,ьk;GS'AG)] 'ҶW2Ԫ'(l- {wf4 ǁ$1_N a*`XwMa4!d8dGZ 'mu&G% 9Np6~jR\剏˜Jh^Sp&S*>_#%ӼタJM[@(L3Mhcă;?#&$O3yj!XPoᡘC[Fi7 ~bʩ>ogNwvqi'N/45)PpeXQ~Gbwؔ1g?ZGQ'K~.YNab>#|Xͤ᲎o79WbqנGVv$uW?sqY|uRȑOq!k܈x~?gd!U#y)QzU679/^(K88-sAYav¾^5`QnW-eAh?G%.]S _⁋9sn' ?=s(o@␡GeicK48H!eg3n.is5A2{ֱ]S_6S צ\E̫Xg#|_s-21g Qf^&O>O6B2׵ȺXp<Qj$]ښY$k'?tWtymшP4==v|8Zgq1~y.5m/pUxl: YEd 䪆1kr0F mUϢJٻ>ŕ80AC͝a,*}lU0SX&\Tss#-={,^cR22y;} 7toQ%ـ]ڶ0TŜ Ux1)vCF MǘN2H'ȻdșK2NNSMI-gq "8hwTge OZ 7!yBC&̸,lǗwW"mJ7uY*_2 V#H%#- u~1_rb*s roF@cU\? *07NҶC,f[ŕ !+E]Ŧ@mXFuvOG>b۫\[-a#ݶG.gx;Ǜ7SKU)q|\K:͏/c:Q$HI{w?dzjltoc~=pt>p)UD,~Qg4&H'xPnk1~D!t:j8tśΪJ;tAcP ƴ=}<6O ܌~w%d1w{oƮMf̤FyUX+Zyn|2ηı4δA%ޑ1!Q_DH^K$]ْ]> ZWW͎ ż^ ,!c(<` 5 GnEΌ:S7CS™R%<ܵK.{˲0 zx޻ "i"h{fޣ-hT I>oȝ9jSōdcX~Uk?of-v£1~90?Y.y$Q̟Btz~1ó?Ljڬ;Yݸ2 y@6g`6Bo `geblK շjvL[̤8rܼe OV3꺣bs5Jwdvc2B7*6ψ Hj{);zByt^_^NA9H~CȳQXe.KΕ!ogaAf+^*h(>; X2 i?9RϺc;`v0A|{{P ޣב}@,T_RZ Z[frr*RG {5; &_&;?.`O^j㠻Y3|0V]Md[S>]k$iQ4/.[Ե[rkbWe=%-YfP0`?ꏚ̜ީc~YDH]5 TYȑʪ3Bo#NQyH]^i[[\dٔ>q]P>>UtD0%FM4K' a`t|I3_w^x:|,=s^޵E]ӎɵ V3'hgG6LtvbigoUn *ޤ;ȾFzG=h"Ic2QؖȜ 56N[LŎ:Go karj.t"MޜcqTZ7u|b2KЗ;mC^I|>HUxҌ}Q%󈔗Ӿʨ-zc%\+KKa52&ɷN#̟E<UB}1T*/5 >6#pvw5Lso}Pp;W5T?ox|8 _#`#,C'GlGa]%зa^ͅ:L#&fRcR[ cGL\u+'aNzoEk#z-n;X HDm@Kc3(R"ҍγqKXW$E˯ˈq̂>vqrTX5zSFZ}ՙ endstream endobj 1416 0 obj << /Length1 1724 /Length2 8131 /Length3 0 /Length 9264 /Filter /FlateDecode >> stream xڍT?HKn$%0%!HwIHt  -)~glu_>>u팅Q - !yx%ZOLBx,,$bFA01` ="QD-8 D%$Ic Pnx,poG; !! F@@@@ t;v'pOGH$'/ٍxB}* tY/   D( an(w-@x q kAy8^+]0o`:ʚH/$7EB(ڠS@TB@\nn~AV !~Pgs`pO_+;W.|0;XfFD%DEE`W koooU `*>|݀`+<-؀!0`kT/?J~_,P àOE[KSIϒ6*(< Q~(@LL8@ȟyW fH.JO 9 ҆ #ts~~MY]T+U;c:C2PuG@ RV5$5 0{yy!n/. rC5 un_7 ʋl!9n74J0װ kJ+J[o1xap$`Gj₀{]QM@({@_~Q /@ 0loПvAu/A (K8PU1ATf.[0RA`D7:RQ3 C?">9/UuJo鎀!QW?ue w{Pk y8H*ehu<'8ZwT@ _MlWkۚ ~'#є6Nx 3i'26H艬0RozvjovJČ8SF5䈩9q<),@p=K{,>kǷBg}u5d>yCIXD.+KYWZ|-HroV 0]91Gp59ʁ>Yr$N߇Aj^5 /+2D_jܞm$ h& T ep3^y a!U>KA bmHo 3=LPIWA~+5w$FJ+@< ݎnr SL FBD$ 4w2qM%9}]{!*&?`yc↍{z_1-m'|8O˴ԑ‰ě]ә|Vdvq\47F>FnXw=|=uŖfDEr)ZՒ Үq"lyъk/`v%%b۬}U1m!LBhF/~Qc/`y/] &TVc95eG:>!ݒ`eB>舾4|8ر0v}Նi*ZvJRh07Vhty+a%v'@5CM>N'f^?[)(-a;kF&OJ@Mt}Z<ҚI(d'ne7y?WATĹ2Pzۢ9|,TRgx&Q^ٗw'a5;rcX+#g"o=Жr9nZF5-v 2YXf]qheby1c٣=0Y1Tjnns-iTGi %z g嬸(GsH)l;j׺蕍Ydjê>N+ AOF u|5&*h?uzI4+hЪɢS wBhE-^ht9#i{LK@v-Ņs>T̃= Q\vPZV]{8[4"M#_lv{0 7T[OݞoĔ%c6 }F\scS<^Y14h\BhD;HS7$rԅ+ŬPm;$qkĈux9#=+ح3 qhZ+67|ٌ[πk՟(0H%ݸ[=“9U&Y.-gld%4Lv2M_UYaFNϦseCV.卦Osh,n_+Nhm״)76'BzsGg6hJhOH^2,F'˻Gz.WoiWoJ nz,0H8{S6&{H<~Hq>ȝ<c㣢(Xɸې>.7Z˼Mg;x %l}[=L7\PjWڍqZUC <7wO#HCJs#>8S"c ;.yh;cڵl^q:_Nk3L%J\֜X%T?8>۳| )5+=t{C`/)a7X_EB ]unff~aeK1onpsٻ?~#X%(B8,e?89c8wOvm0D w!}9rY=$W߰d_~&Pl]bG"DB2Q/BPΊHDDlOs͜C*ҵ.ח'DV_L 7cG3D'N}յ{@F'& DqY7֟;Q]z]0̧ -ٟ/h7dxV*!;)X~;F;8G*yv<c}@]r}ڬjydL:OG&?fUwsK|}NL/)-<)EۢLaKum2 qO$(̍vvhQq#A6I!G{۷{ZZx͍-u#W[Bh-O= t}(:'ubxTd4(1eИ1W]@lii5읰%ސ$Bk|ٖQl}fJo#Ҽޡ:2oi:MMȍY]3#Y3l6reޡA]&V g8'>+3v;fScoX :o>2[bc/?#Yt+ń7y\j,jͮɾO:*iL-EN 18d] 3TA2nT Yl>Aq$+7û!&?&4~x Q`IЅG4@ZJn_\-i覰!D*>RKq R9}x5zrE1QG=/YIԐ_f 냆l(?5lմAЩQ\b}%獨G^gȃ@BъFjW5oŢ ݂k+wFS cEnTX"c ~ =8iU*72 갴U9s*)B5c y2ap[eB2YiiNӧl&i\Jb 'ڛX8Ygm" u(1E2MBvŘԯ\LY~QHb)}B؉ER z :)B_{8 5:2ZU$oaA&U` =-F<م7C3w6ZDڜuWY >O >DV֛M6DRБ+fJR ^#@6/x`ϙӴlLi)SrR4Kx oBFTl/p /c*kھ8?4lF1퐏oJJȱsX%[5k­D5fCٽSМW?%M ;~UՈtO@hdȪfgT4ƊP(W{ vJR.L?F@ysT܎G6quX$gR)k*L]a;Z ӊI^KÔ[Wr0Y B7RdZ1=\?X30;cYѣT2 iVBO^szIO_2Tp Xy}b<5yHXAM]]Qh~`A=K"y!jܡu:;x>߶ ZW/~$yxs,{2y,P4'a/h>&(m,s)-n[n{g7)J |Oy+؈U@YO0*"`,woo3e^`YGYd9Wzc.NB[7Ab&"8"p.<짒;ov0؜\H5dyϙ+|3(w%% f}B(-7|rBtı?t`;^8Y䚫ޭ yC[ٗO;6z/i.N@I.4>h+Xx4|̵ Cwn6(7F3$ZTp2r uАѧbEVaoSz_~N j=wVެ~XX$K8ܗ>#M5tyd[^6Ɨ+{3F`tm8ׁNp"xB5g/ JAYfvy0]$5f=]@d ~_f_G}O:A>@C))qe_l{5)_/oU DCS2)s= 3SU=2u=6wYD{7_ ֩s`S2=|3|$[aЉp:n9@%TJTVE{~)TAW٨FCq\BTNhÑhrvYZm0EibFV`|̊枥/>o+4C‡V_S.2y~J2𭊐&A <)ez+*\ߍ$ȾNFRr~mSz ﻘk[ 6D ,X #$g\x?fs$,S6GqQpi;~~>ߕoy>UX+'~n!Ob*lj ^T sHi;p>ګae촂n'uʗbN9BkHʳ znmBc.s ]D9eg{̝, tWN[;렘F~-۫'LԢ)ۖʳ@Y%$t{u ާ{=Z1ZuUU/EʨH~A2Ij5G~,s[i NE]BN z8۱glEu_2-=$Zc z36TilH}6qGŬWtrj$]9 &C]%޾%/ݸפ|}omzq~ץ,&t=ۢ>iO zal\9hCp$*Lݗ9x] T?'"ȼy?$Wĩ|?AʓY!l7V}S.{0S+t$b_ب0}礖/?aBŞ/ch ^yHdgNJa GG5:']K9sGdVT)ѡ<ʹ?Cx1AƃwD#:"o{e :>1 +&'Y[d ?1wMgxWR $fGSza,o%Vm;/Gw-a͖`F;So wn$&&u_0-߫ðjl9sb4UOKV?rDffx\pGؒ8DM8N(;XVjk;ru:!3dQM3ðŵ/[˜et`׊tM_ȉFCH:<71?ocU 9  Nx8&;ZGyX׻XO\% M]*@Fì1L ͉F%cMoDUIM\٤oQIh6r*bq9eJ!薑5aSuh ^x ?<6f-$<`7]G6NhdE ?p?JX,^"@]R?U7潋tָPZ[m3|GAb{ƴuD"E<(0ʳ 1KMh_d>@! U.7&;ȡ$$8?iw>#ʒUVt2PI Yfj6/OeKQxTGt<  ZvMNn_ {d\ȥ?z<AS endstream endobj 1418 0 obj << /Length1 1441 /Length2 6336 /Length3 0 /Length 7327 /Filter /FlateDecode >> stream xڍtTTm.(ࠀ0 -H0303t7RJH)!)4tJ?~~uk羟Nv]~9[ TG% ZAAaAA!NNCLiE`rP@Bh Fcp3$ I%BvD %`-@KCQ$ Wo$_7_p  -0v 0(_)hWI S@ exEz@mh]: :Pp03 0p[(` q8kql + ; \\po`st5^{0#ă=0g w`iP$@sJp[ FOB0 3Y'8Մ+USCQbb"qJo m1"\v&0;(C{@h;"0`IɎv֘#a^sA @_,1Eq=_>ߟcGx|A H;.WĪ{Ew.mP?$`^o1W ewgf v9{!;#-Fv5V54#9= A?8 ??%5g@~-(Aaq( /{_%8aKgBb0 &IHT Ƅ0=H_c1Q?~"@#f  *¡F3 H$Fi)K BH&aaM+=,,3..fnv(:`OaFlĘs,L-(⩐ij/qb`gM+}ssY]G/5:*#i|sziQX\ n3DpTXX8;],r($MƦ!^)>/8o4! u8^qX97dӻ/eJׅdm)GvACn;BIہ mFiؐ-7#f3d~zbs؂,RQ1(v>4YP9^P>'d6įne}u!Bd3횳`fS50 1+Z9,V`Qp 8ӑ23Kͬ03LڮM~,Nג %jRNxT}s8BwGQ*#RLw6sc"_}}Gѩ$LlUx-]cۤV}JEo \,K[C1s v"ݭJkb|o*w5 c@םlT,r8ꖁ9X`Y?[w Ms6zs3n{E)q3UB^W歉!;λ. !]߰ A6gtfy1 ;͊ מٞHx[E 9y@qIΜh>)IZߏ]$:;l={FN#O9yW`K #`:W YXQjJr`ɊxR=q][/zkQA,?FUTsZd[91 }w.'ՀUpl>z8$^%w"?M$03Ved5=^Ͷ"D-y/~C6ׇ\&ɏd$ L D53lF_XdF69V/=P,(;|NbSk^t*W8|zQ%d֠+ 2 1v^ 0o/u"~I>H9/`TmT[4ߗEE擏3ց bJw6ْ]x[( Cʔ^W3~U :'S?MJl<(}k-㦗MPĥsߜ1UXBUGv/U%_xJ\D2w2Lʕ)UE6!|XP}ILUQt^,ŎE5DzY`Yw?McKثף/B6 Qxn,όwi`= W$PwxY'؅DJ ҿ.2:*Re?i㋚l-@ 2SˈA~AS ],!ܷ6*Oz" wyػЉGad0Gp(Vi]i[5e_E)dN.)/.|P- ]F ,nhኁ˴A4džpw}1s1Zaʚyʷþq2&la[70zuDeu@h+unt@Qލܢ@!0w.ᾑt6w[~ mp<Ξ~"WD &<jSIfINٜJ䉒?(ssT' IN8_lچ߼'ZJuTsd}7fg̥ra]Ժq[J}KS xݩ&M9;l1l52:o튺z.KGb,LetdDOORA,&a־6~{ TRVj蓴*OXӖ[kwnz*bT^RK5lOjWe@f{sfINWf>(d:ݠڮ{x-4w ɱwt|&&K48JbI4.W+KOԛ6v OU eGҩNL*d .rCxH i:H}kRZMll^ +VH9-Af!\F:K5:1dYϻrj~\i)K-D3fFPA7]P(1lhYbȱ"ʉT-:5Df]sDaU6Yy3q92kMR M{EAK- lFe{~>$NG"Y:>X>Z=w^^8(C,M"Z9^֚VH_P+!Z1yEuݠ8Y]hkS' ͌xN0cC ۷Z' ?t ˂(_ՐF?+ QŶypWI1q2v9; p*>`8/W'?Z<0Y,˺NۯDF%)NHp"ؒ\sSVw֪tOFQ`tNJ>Z؟g]֙ ?d^5HNҤmA2)_{$߫ii:\Ƞ9g7YHb8l~y\ɺ?K4Ii1UhW1Zb!Sl>X 5VxܲmoaԞ?+Go NV𳉎&)^!١ XKpnI~|v"pR/^6ƇQ"EU}FM.|`P+즚`Jp/#;F:1VymdN#)F!4ŷȱK:)?NwFх]yqQE*tK}v>{Q<.9,Ok[tH3,ʬ׏?TtD5&'Ă&6z{W\=DoO{áiңb 7GV'h.=4@(Q`2 EˬTyҏ()j|G<Y Vn]U{6߅#os,e ʸOLF?6h]^K}W!#X"Ȁ`}QAS'ꇋ|P#T3M|u;҇h)njVt{ƭ"ٔ(,/:C}tÛߪ<~Ue '>) 7UL:ڢeFU*-+ɭ;WѼ3?:#-zV*wOȗX Lj +~ȫi{?"bا/{Mޠ˳N͑, "uS]o}_ O^y6}9AJKmTDaa*Jr?ǿSxN԰DBl5@PUqMӬB\ nkX.ʎz MZ+f"\6yIt7.ę^Id"W;fkk7#d{GN55k-BI[=+]@,f3[`2\XgPnEs6!L27d]᧺NЋ.S ̈I|/ )Y:,[G)Ux0G^5$9KP}^L$>SZAXd&iՄ%j L|$=Sxvg!SͮRtﵾX_EsB--ٲ.ШOa93e_-[?K]d`\I lt>!j=l/;8 B@r. B(͎jkkg᷽mCЩ21dj5;jkHYIfOWL3RsBtSFB@4+Cl_s[iz/rM%s'?NFڭzpLVY[yqcg㓍\++?-uj"KEZjX}`zL:2{ {!jhHL)ZxtxI:TG7 R3N|Cւowaf=ifydr5רN*XLAX;9D&f}4 T+1K- M%RۤGR M1Q#_mQoczkgBi{|w {%|n=FV\KmxBF鱃'fKow;#Ѽ7U[+[s koے#iG.~+I4]̢Ț7z5;/KPVrB^51`I+qmZwQqm@)&4s>iV4h,fV!8Mqv`Agو`.=|ZfcrFIw\"=l7-mQ[Z$s~q@3e~0)lkFa.|ԫqo)mv vPDͭᆂq7ݖT>ZfySZ1T =ۡDۉxP0>ANG}mhzRn;?G"Rr)1rmInתڵsSRbp{!n89C7ʱXvZTȓvSd'BԲsS uU;zhA⅏bcтcŧJYf2 endstream endobj 1420 0 obj << /Length1 2072 /Length2 17492 /Length3 0 /Length 18743 /Filter /FlateDecode >> stream xڌP]ҀAKwwpw ,CkWuoQk1,ȉUM팁v L<Q9Uif&+ <9*9<: dg QGLP `aab01qΑ f 21>E=Ay20sss:LlrF@&F;BPY8;021819 P@eh e ߭1T-@NRؙ99k xP(me,/:p+og#;{#[9 d (H28;lM24v{7r5Y]@BX `s2q;;180,nk*jgcuv>1#=}Vvn^!3_m3ق\byLLL\,\nbWU{J=x̀ཛྷ\gG?KS3h] 4߿#>~~>avbFY--9_;@`ffap?oE#п_徟Jv P{AK}r?do:" kT2ـ=m>.[ g TՕ\lV}m'_rhr6K׾YlvN0^LLGd&Vo[|ߡ+nkbgײs<^[i t{ v.}fv],;Q/ѿ(8 (_d0J!Vz"ޣ(%.&zX=b0{>? `/q{-3~HF{{f@33Kdzonn_d{?/{l;Jvr۾~^?p{N*{^g7߫vW||ou0qqt|6zߕ" h`gdYv_#F;q2VcGu_)@5?bIkn/a혥JJ;5k{6㱓 ˞Lg!9Y۵,56|ơ$ES] eoDO\\AU"³sdNB',~сR>\g pNfwz?=P\}2vS$͔ޙ܉V6o܄O݌!9߄v7K)VZNYS^./з'1;!U[vx:N_)1s6n4AQkyn4"1 D'N chm0\V֋,@N~DxL^1y:& L{bldlBc<=5}̱[`0 [ ˪5Bt%7TyL/)g|ٺ%CX:5{i& 轒: 2}i { \dyLV;fP3oB,TZ?{!Y,TOBvQ >/([}Y)Vl첼̥dt7 av~Mno- 1P6_GIY;_rHd~>fSui:ΕrVNh 1x$p?`0iSMkh|soNjPbHcmP̬KiԴ9%?Aw@_fA#AVW)"bSIR~|9v`zh}:m8uONVcbvێ~@; _̕gC-@D%ca$9CƸ2+%"V&1^Z, 䀉#9L;*D/Jq)IqMK݊~eVaGSbcVP[Uk="8g774ͥ^: T[T5 IHg"Z u>RUbkOn3ϵT,'GcKz(7_Ə+)t:ҧ5#@{jg_VG^TcqS0>1B1|wk} ^,=#74ņ2[W Lv3GeOv.D=%@8˾h犷9$epY3ܟZT {[{"3߯RR(m[>/o'n}ˠu \`n'Q&X&#'1'V D>~oen\3~󮍁 Z#R ggM<eHYђ~96]1E>0kN1HrcP+,9 v[oc>ռTQp:ELn(rtfk5T:},NT $ˈq!f4͔]'l%f2Oxs[$zj=1@M8cBf)0frE,5#߅þcVu[lvE!(bF]ņ\E\osݫ4"!tOS^?یl=41E7B|+~0 \d3oܱS^ 쒾 Rdw׫:\Ao2?sDm 9?S\\a5jkLv)(NuvMݶ2^ Y6Om& }-+s땟i#j ;~1w6Ab$Wbқw̘walL'C^nfm Eo{!h-rBF=/0#4̮)|)1;3v{]k~z([Qqfna΋2yOw79t|`/ԿRlK6kЅDC3?:7l)3}qF;D6"(;3'+UZy -Dtr%K*WD0flِObۍA&Ly@{Bi/nxXx*wyo*VOԚ+t]pF}# lgʸD57\E'VzW:}ZS96[5y \3<1y27$NeC}DDZ`txxyޟpg1,k2;\FLUǯ!ޏ?D 5Y2F5݄Y S LEV[)r7 \UvUXelwt~ $K[_\:U#N6@L^3M` _ф~ʃ[Y &m'd=}~K=W.g}B,hsRޱȦWv8vˤHq:J NJYoP]ktuX*uN.5 kgHC->5Ƣ34'6 JQ8)Sz,a[_yb9gV{С"g͇?ݿ  IW)!_R\r~Wp[<7+uЪE0j*)ݣR>taP! 6mc89_ n!rdScNԈu~:@Ń92em/^QJ .c)#o!WM-T$۸W`]Y`!K7 or-L4{'̼Aďr7swK>Ho۬;YVCKVnAI̘K7OIUѱMDlDul֌ʐSfA^⹡z:t\zբ9tm"$4s 4Wb`2 "f]^Q΋DY9UQuV0+MQg\~~w"mp.-W4.M0:I%^3K ^ꎻlI~4us&|˨e,ԑ~׫C7Q~M aAvQ33)!%9:Ji*Zc4I=''i,?T$#b  COuh\ 2rxI6wYs99;.،muU9o_ ߞƆ%%~ezxN`GcOۙk'ZR=Ԁex^26ԓxqҰ.aU3L5/TPY0Ya΁"G"3|0V1rń+|NAԉ_,x |q!W NĐE6Uomrp-^]$d1R'R Wz2J8rʜzeь?qZan36Azq vq=Tz?1qdjW,ᴓqC|ib /˂E h.p%G(+gIZ]&oA '+v~&̶cSmёhk1r;Uck'%i Mdp)*|x:EJ$%L:Ǭ\:}:[>6ӟ~NWeS}Yp`%`̈'M,`JN8z{ pkӁk ³%a~j+xtzxU4fXzv7$jS,8pD'zڂ E+dQEZ}YRU3ΛF쫞y Wյʡ57҃#v>r~,ލlo8ֵi.D e=5Ӝ⒳o[vP覷R.ăwkȳvnQ-i Ё'm=1>6iCǏR_qt0xeXd=\&U^ eH&KepbH$t5~0F(B*'pmPp̓Z~gAv_bF}7VQ {2v__ aL>"^n:X :D5V **֎2:~҅X@dl}*y&Y_US`H4hMaqhۉhLh6>麀{f<BdFޞ@Zz.o 5mCх]UiYe~sO!4"t+%$@= Ię_O!ZKU\_8_"H)ᙥ|LƬG7#sڽjЂWҲ,FKH3蒮d@@J3r9EբA"Li`ź%n ,)_ldhv zZF0mEvKB-yWȄg/h1'L'k3b#v~n/<- $Dzz2HڈRsy*=s1/0ЦP e=OWНQ8S BN/lč,zW%2hsCo%;:_2vFmSv]"]7И$tkgo9 n{sU]@xhN` $miݧGT.`Xrn}(Y4);Dveb'"]f(l8 K6CKϣrP1#̳'9+-UW+$~}MRqNY^E&7l[*ƦkCHkpVb_#^,˸\X7"c i9QQYT1r %1&v͚_rc)q@ygWih$Ĥ38eiFe1j8Mr6Qȿ1_q/U%Ɛe7&d=S_մ &K) "p"I^_"J`k6Eua=_b=srf]7Vgv<8)~<36pfw4)=,2?E.|`y=|c~;yV',@\ cn`mAJkbkb$FKmPkcKja 0TJYEIwtUqdQnhOpGs3^5=8t;np> v ^oXQT,M^Rig4[bW+T<{51#C=:&FIv@ \"oָ/@1pfftKn3y~Vlɇh6Ŵg|Odp şǜzDU2^r[Qs2S{_X*ym|!KG3xM=rn,*5y,xGks$“M5/`fȐEhΦG>0yY(,-D}b!ٶn‹P=%}gއK9qk^/v(f}uCDHv-ma&q1gafP?",]AnKED-Q"P+&J5[>}l?A 0P ] &)Ɗ&qz<>^B5yhryE􀝇 ?(u0?[bP AM!d{IZsy4ި>KH2jrl*/ FvŮCr+Dz>Eu Ggd3cJ%Mf;O̫r|}o7Dobj2cVIEK%ܰLᵒ$-Ài^Bg$S`̶/(mނvަtjWP(,7pea _rmޟ"HX9󄻯@oSԕz AQ&ApS [{|,~q[j'7] 3&ϾBy\a(pvfuw#I+G'<Vg~v9F[ o]> !![6>e!LP^R;d!y BpfyYUӦ:}bOW|Vߗ{'`_9.LCz|Ӗ)V֋u8ߩX0^JvBwߓDlſu7c^%GN<6?yNO/ r_MDbUZ p+dzO5<u8a+ }Q'L޿D5! he|y8` E@W-8 NnR6?'D^Gֱ{o\MH`b_DwVfhQ7! >Y ~g1?ȶF 2&r FvġOi?m+ Qy``|_#ϙnvhyR!nErY&L0?4/դ!.e70\z5[VH`r-խy9 Ρ{hQ㫇IHܭ&l_ˁ$ƙy<폐5nI 'F**Le)F\D7/*}ksu{N5:tނ2eWCb)PʉK0׋bz:E6Vr]|n{FB%ҝGlЀ~ŝJ@P|  {VγlԖw|2ja{*ew{M4 Qo;$x3 U?+Yhp{thQkMiE{"ױ2ja`D:C6:SNjB?0/LjnW6YZeQz$C.A,i[CNa;~ + |С#k񧇯z`CLբO5t[Z~9 }6axt-"H:&LUp78(Ong Em٦MDS~]VN w]߸찊G4Ɛc&]gٲ+HדLmV%=^ 1z=s, |m䵊h+wa?p.<2 1F}ltv#ؚjek!'^*\Σ 8gJ9"4wߴ ǹzwt崯S"YIVϯnjQp`2Z=Lʵ1\uDM|Z~ρ)K%zlFZFsZ`pizMr4Nt_e n}ãaq9tRM>^fD]^4ق/Z]_ia3*j2U]"Bh _ewٽ|h E̒8LRv t5)ؐ%R' ڇƳs 6veԳPH2Zu]s1Jc+btJT('5&_fƼGNGߪ+\6v)r$(LUh!6F|yw.e駈J pf|o^SZ4hẍD t]4{e.v<tnB8YOx$9R>@7vz;Hkۻ\~|9oe#̈gJG; JhA; D֥J֝eZU.㇟F7X'%S'~/>9䉰6 :P@GR'~iOʭ|B+؉1^쾭,x8G@f< yE}c{,Am_`3wv)2tlƶduo) ھ']wܫr&ÔW{rt,>IAmwH݈ͱN돤HbָTLq%7#,T;m{=8D<+:u24; ~E~̝Ec3#e[޶<?07 Rs90,ŴIiYznlz#x`jlP pRy%h肏U<3/OV7`{(%Quv RJ#b4򘊒vQH.l=P7&}^MiU;7Ox8ih'ƥgvAfx fBQZ âQ:͠<'z;;k#hF$}P)T L9 =fS|Uv=~%NҐ"D0aOh {`S߉ۺe<<(#s~ oa) l"n*W uMۺf!.~gsy=!ۯ;b$/{(I~Ӏ +}88΄k3yxGEt ,5!g4ݽn<#<<X[hQ ua۷ֹ^310# /sN!dM"*@7bIB>G!O&=="}q~!( iyT~kE:/s~γG)I,~m˒ $>1MP4}%GGC$3[b 1}Cw`;Y߿8B/B 3?J9MDE%aZdp &$VH[,'ahQC6̉Z7=lU6RO7_j8dٓ 4ꑇ[EB[]ιa͒W ^UN߳MɆ 5c #DMrJ LǛ['~nR喋Nm uHRܨ<9Α( vK 9PqNd\y5!~_ցnGOQb@oE@Q*f7F~>́3&ԂCl#&[%f,1}^ {o'zuӚ)EeAW&n&d|]p|Sciz^MJ,=/NpP,-x.=Xl:eŸ VC7Jsow̹mVV_4 7rZn10gbMr^(+Y~j` lk0R<-9XC4ZɒY9c_գ}ҠmB<7eeSo7U' V >j"PD#$ܪ)rݑ=g9S4Bn>QXP!}?y(s }e2Kn$~2b)?NAG4eKA6_X vꃯ}trZ9Z,IY{xJjVy8rR1 a155X(Gۙ>sX+Kҭ$艌}3ץ0j(g0􇥋+%tT#0ZWH bBt]´= X@1ALnQl;$\#k*^4| 1 /M439!Q*|GkT4P+g9wx<ݣӃJȾp/֏nX Q.e:OP(?ٿB_ԵuԪhea0(rQw)ln嵧qR$OZ|Aas ԰GدPV51Ū7TC}]V5 9\ft,([M a1 -nJC~0$jdXՠHC =s`TK[b^yV/ j|1ߺr嘚czt[dsu3Ėl~onOvQO7*/7ul-;D~ k׏MWD?D(J;)IךoڠȘ"j2vJO1'>&\=xF7}iB1Dڠi]Gs/=b+k<=k'$(K.ٛ7ݘs~"lp%ٸ`e,dR?|pԿ꣸?;Xnn4ֲHN˜{>pP :*QHacH+F/agUasΈ=h16.W.M~C*!ؠт(Y"E!!( FhE SigRvZtbHJ9_Tg6cgJxV~E 2o<"ui]~sa-!|@49)1\Q_?!})LJz0Pd4dؠN?mL WU׹ZFtϩl ( O:!i^NNUg}5=x;Rw񉘣ĨqF7ZBbF{Na!^uw=m̆ !/'fƘ:f%R;4ΥD(U, Y IM0RvuDL?5i$5?KW@"ϗ]XpJlmf][Ntp.p5( 0+!'N#,,C*H)UCu 0Gާ(KJmSDG`_\]WI96p͆_s JS[fY>.jgT;Tݤ=ϗ1_r4 pd!jߝ2brzc%uc9}T!|#ؒ6i= e:Ifk ∂pwY{ds:X5Ra_g)ZN*ւ/ d{= Fq_Ԥ$7Ew!mOW[kRc%:թ>~)Dد03mʸO ~+r dI-/\y&' Ħrҿ %.)Z)tDc |v`F(\eMxdۑώ=\caup X< 1#ꄖpc-B2{#yD@> stream xڌT[ ݍ lF[bn$NTis{o{cϬgι\' u-VIK9H!Vpppqppj]@ꂜ]?,A@WL 5T8N>!N~! !B;P8\h!^`kW(0X08YrHڃ@ de `B0ظ: {xx] b, @rvY~ Pڃ) mv[r:Puqs9-e#oc X4o; ;+&:X2ڹ@@w h5+u @NRVO}.`GW6ݯYRborpuA d?kp;XZ*͑]R*B-x988 '†#/%/1?G# ZlBqn ??EhK+d v@*Y q@Ǐ߿f qm(i3SJ))'  E'?< v 3 #࿱T!й~+^ ?/3+ߌ3mڃέ+tT MpzWd vZW t$m$E TZ5u~qYG]. [ɿT Qbkɸx@ggtxy>my5v6+`qFu|v_]7KFvH./Fv߈#(oeW*]_$S|]7kFPvʮAu#(oeFP?࿈w˯K_h@ 0lf+:`+P&au;@ 1?⿷ߨmAWBSA'x~I7 [pv~ܠƿ-&w;}倶w?5M[zA@sZhlm@X@e? 4@] v?*쿩x&@]}y!Ƅ -Phc( ; NnWG*𿔜P?NZP'=1B@3ֆZoZ#j c~r{ }UX@6Є=AhP? =)9C#y?σ3\zo_d 'm~b!:$ֈ$^ #ϼ[,$ʌUKɤN Y Ma -w[-hscDy?$kzjKl>87)f; `_{t{,lilW)ߗLD ,1Ϝ&Bre}„w=uq95DόwÝcf{L˥Ԑ98EYUُl0C=m/9hZj0P3`͒0[yx5tl^;3["zlG0qz{jmpAjY!ɏ@|[7uz1MOImO/GnXhyI8yiU-f|W3~[#ڊ_.g20[,=wg?3Y}k`du>\FRAmv1g:Kcr{UWqMA ˹Ĝ]L4?f&eu8 dcja/jn(]{?Iz30J3Ȁj7\_W/H3q1CY a^B61frO hsDj >űՃXZZtzqёm?+"dLs! BpGaA'P,X5q.tQalO-(H̸Mв}ѱ_o|^"/`R H}.yYo鉶 Y`zK0HYi&MCXl3vpGJeN[ n͎pM(`j'So+c+ObҋefȮDjqsibIZg=6!ҏXܽ#bsIB2 : y ͫV8V!m(ZO{XOjuОH)i7szahI0{+F@4[1A֎U(ux۬2UWF`J21|AԀi4"[m@Q֌'DGM<$}]~Ӕ"|+6{>2c/ˇlϻ=QUU ܆)Uͨ$}=ﰾۛdcCa{W6`Q;@ ñ1f\u~8xgx0xE& w mY*s^" K79S{ %." uRyo!T+"h/}IQdsd~?3 ؛l9brG=U)~1>(*Rl'Djw/e_?vwko 3&޹ǻ9$r'/|ͪ ,=|gC02v_5 IS[{k36EէRqJwpA6$^GɹO3qᓠlI̔|wx53aoFPAn_R Ѹ}qq&z#{}i@twWP[{! (ኋ'!Đ 0!b~AǍZ94EMX>#VmC1^0f*u (*ԽVTVT⠫GB_e@7.RC8a"dX_~HxA^wӠ"s.POdxo+Osm `Xy}$GMc$|&zNvaCk`p- #QT0aucb/uMDmII ,T} RY#}KW_ 7@sdZI?DB\h;nӇ-"Wj5"qڦ$H6wZh``Ն1V5[> o8 `ԨTgEﲙ"s9&>^,iB.J &־%9 ɖ[3ƼnY!H$\ckM<19 m[ϓ_&X1ufE%9:y{,0vN_T45]L^~$ 9 x56HC1|Dhr=~L7LQXx%.DҰ-iwAo:?\Qϧ,K`#7]Fz%b<$hpng / a 794⏍Wb^ߢ|t}S?Ht&-TI$_FgmɈ0v#<-igPUEʺǨѳԇlr۲jijjےD%%nIT)6񓦏ę x{Z:xbZ|W\9l,ޠzFCü.VMo GNUgu7نdL(I|])@:$o*:Wq p,$} zk3n_xo]ݢ5ӝx})}/uOj.60+Y;=ڶ"fXShX y!3/? qFK+??=WB! 5l?bn-M!DK|Py뙊G,DLpK H ͷfX_Dc9 k(8 _F1\pAu9-v4'Ǔ/h0ΐ5ާ;='SXoCbfR]J !F'a"o9-oTs#*/8&\G+D;'0LD^p|UN\QU`{$NT8 Sb3[["8}zo>""WKDC3a"0>-9#Re֧x퍕>tLL}Z{O'A鹡toz}5{X树f-*ޑ+V? ^y֎t&FXξPȔUÞM Rgxyg)x| Us\իjJ zNLL-TI{0z5^*#VMy7t,ӡ/+Bq[卂v%{6)>ȋ2`&gz hofƍksv+-'(\q=6m`,?Tch dcMg)483=m30E) iLan('0X_4b oo}Ȧ?0a&V 'x>=E}Bw'A73h("CܲIKsPIOlBO89ܐԆȂ=ET~8oGU%=_`Z%>Nv9OpkeMcf#V,v%vݰvb;+;"'3Kniaz&k5_ )KEuw(Y8z=6ԻOo5~TF .V]t]3aR+ `l{PlG*k1kGutHQϻ eKA?Yb} GGO3/:"Ю x3jO>^*C=:4P)r9F *~ɴ0#~sLF,_n-a$GE2ȎVPZ ~sf͛gk!a<*[,++BFW- 1NJp$yZ'OP{1z\:Kn@m gD<tQ%s¼(lsNrsw+U1 oHC:Y6 Of].t X*7|2tQ > 1ϒ>.7ե//#Mde1:FFd̋75#0Bl?_sн0LxvڋC"r[aPKr%/rKㅫF'R߲㮛B̚[:V@%j|ӼnՈjV||_?t* Ut x8#%1@8 l#U#:"(/K;Ӻ[u<:tVS]/S4#yiƘ.B0"~(ofxfA@^27^D熬vD}MKJe_2G(SR_*5V )ҟߨiۘyvɚHcǛ2 +C1hF ƘmӋ3#:gH~mUX&<"+:3*xjVf{x'RF:6k7{ ^zB aAղr~FЏȶdnqeO0xa|zT-u:ưPNܑ^&;@T:ݭ`LOn:lpaiȆmwWYO sTH d{io޳Ym7(J0=ȯxbuDꩊݧ{͈D{LQV%Ʀ"zG%GhȊWLY$|]fA}c8WW4Qj9#Q4Y{̤q ~SJ Ua."$Zndp O;j檑hs~Ya9[06 ä왗]4UH"$> wy^5 .< G]F3ء[|MYx}x=B.Ꞻ9i D@85FoPXaAg'^]~O eBEWrRQsK}ϽܙjYUw]j-dc=e#zOh2,nKĦ(p\nh}8:e5g窼o3 7A(x]Ѭ]a88"9$"#8kD`DZ4{{Fߥa%?AGhNȼ9#B-ANRcw]~wPʱ/yO :i#'POLiޘt'`UgXeF~k" #:xձ4?rʓ=q*y5;)mc5~ WCk7woϰa]Zs0NGRCx6nd.*+/ф&gG9PnօۏY*S=6ؾvvX\*m-[;h9eJ|9dMcW+ϒh `)T.#W)∛}`Bn&^8[}4lSod; B \rKZ7M++/̶g-Y.FZԢy̟iu;Cr;8lig^\jTBaZ ^j2eqR_B+EybUtq p[5-TUt‹zpc ИNp<5=_a#?WsS,w;vc1-'&8بτЫsAIvwڇNJnfp?ٮ0IԵБx&+RyZ _wPyMt-CrES@ khݑ}f9-.pQՀQEh|u)S 8w*Y1V[{H@AIjg5+Jt#Z l\N{\zϨeo}OWV}#b{'+ G`ÍLmr@X7M_R Q9 $,-LCi;#ȵ夽Gif9ڇ%Sg#x\&c{/(C_vڵ/]XpKp?A%жr)9VA+Jdvմ~ 9YHӰ"z^+wX} %Gg,ZLG{Ï԰E!%TG*.(ջuZl&s\; @n9pSN KЄjusR_o= |z@8=5S.7DGf! Y*"uB`7! 7Fs:8(|&ԫN;2~vgmӣUi‹3c^F4xgϒCCY"q*>}a6Ev /k928#BFsU@wJ)B>q\D7X|xz{ ƌAv;_Xj)}6DnD$[-`Nq&v ֗v0\i'iE trx\$w6} ԁ{: :7>)Gs*j_wd\;?r,UBL! NjN') Q9whdK[) !.U䣯;]ޫrN1VƺJlR7qm!G~P=ٜ|YF:;cK׷oxeqe7T^wXTFxKM3blgì)^R̡cQv] Pյ<5dr䧱47 HȩY=+YmdX%b g:4KawD B_#. E[Ocd1C,|ё+o򶁝tf[qj]}3coT8m*ЗE^tIz"57Rθ5d\~)M"zkwq2c&%n 'b)wfؔDz,t@b{A^̀U7Mi0B $1ynoI,*XIf*x?%\XjUǿ[%94p\}.ӧzX{5t+h\hd)/7&}O@IkGwUajM맚Ѩ^ ? L4ffrN},U_bGiLB1wP>ߗDRUR !4rh!CcVTrQUs]v0E+W;Umә?gضDMyX팴Ə|Z'TwLsk辒O 35cxF+,u#R5ENTLgKF솚9Tּc|*,G9UHzυp`7rUϦ~_;}BBYФ(C8{ɠY7>댍DY#Sv)㲪S_%m W JbQA3xS Wꤐ)8h]c]t݋`]Nya%r2)l 4.uZh^t899C8uYLA&[I`_e~sv">:~V!C>S:yxfeuB,LWjZA蚩{GLQ{@SK:S`j]oGseBםI(AAw +^w08{V k;f>>p4%Zv 7_>T؇ ^[*j7s{9:δyʠĿY|l c=xZeU$)Yy`[R[dy͍laQØ4LΗNLQ˫vasvch o ٞ0:n{~?EFnVUo!0nD|7eXhASN`ƫwFpu󞧼VJn$Us^ʬNd0=kgUYqlX`NSNŜ"sbtO26V5!]/d+/jLC̘Hkڧk'xJƱ yJO[wg9LR Q Gx8-DdLL>wEc,{`0轓E oͥᢻb72ݮy ΋y# cWg6et2!T cvBͱ+~.ĄZ9XI]`pu`|%r8y.Maҥ:HT TH`'}2yOhplLek1[#kJT\%hL )z|k?T& Y?Z2p,DQ' [:ߞ7u lJ+t-=ԕGMyg"÷ʖ)Q3 O}تO20RyVRT5̎wČ6Rb@"A5JD'trB"/HC?bedݥ\ 8%'2ytx y%z @"IEs%}kU Td26$p(o%[䐺C,vtVUni6HDDIzυ2]"`GۚO*KFF2]xk?rhc#q6 !8KW=Xm^s#?%Z?鲆ħ3/mTcCa (S%.kL!zeJPw#=ͯ%S3acʈ.v¼FkOnpSmb2W7wyclϊQI(a)߯3jk9yO8]Ͳ, $4?Ȱi1NtEVsyY<;Sƀ7k!ĠxJv"$XzP@x-ԨW!cy#ޝYz*Ѹỳ2VrADq8Yq?kG6ɻVyF{閄}L Kx&4qHw&5[l0b}.ɡ -?kkk[)1U:LfKEOwSn;d ĶMIb5`yzgKk Sl:EJ*ݽ F05U"V6fl%ŧ"#r:ϼyvEW_'3m,{M5AXuiplC=?sG"DȪwZj*`:Kus_֪&3NK;Uluib*0u,'Mxu»Skist:CDEUWag=hzrv%*y|ụFx^ xf&C|$K=#mٞ\]pǒB?^W.I4J7SWJ椺|^ؓOg5"58U;Aum?P6K՜I?Ld,g˜^˘7?Bl GN@ޢ.LIfLfFUy="L k{wc_<6 qdyfolAmBZP6|yzD|DR9'UNY#lj橕O|1icP Js^qܭ[U`d$aZ~"~f() [D{Y(P{| Ƈپ=s QqE=iQJYCgq0JKEҖO\'HK9ALi +VTn_* ) 7r#7i;_x>Kw8ߩ:!m턿 I%x8_ϟhr4!'6et!dV+!&Vr5e"7U_] g^Y7d*~Gu?>|֟Tc[XB.jL]f S5X7& 7!5~g D]Փ3ERC qs"wxmL/wLǩưYJsէ[@LRo|A*]2gƀǢv̈́Gha8ط p cEj@ jXznYz˕lLJdJWk.*14p$ϊARL5_Py||ZoЗu&y_L4^K?LljMゴuTFJ$HX}P WdpLlg}{bdƖjthg@*]GS-al _o$~C9o0覈MbY\6;_Ȗr L[{՘Koi owzDK?p)Q-˅Yɂ&WY0eK 3(I;ݐN4xtG*\#q嗍38"d캥<8ptk͕^SCpzgӕw̜ʴP$d!Zbp-znJk|! ldEJ! ;lc2G@=)ȫbΒzs\}e6 Gj(5 k:pkۤ}RY1:TkP9l#4,I" Q?3:jMPcn?lد_,/ȳZȽ*ˎ 茧,JU.k,̷M5b<ٓ#W#BpU3iHl LZ0~3%哸Nڿӹwڈ,Luw1-u*kܦ Q`7ywAUmP3h"jW]c/mgsH&OjtƊv1ԈQ{4,J/ &Yg,7+!EචZӒ\PUiW G~~GzlIJ`5Bk= }J~e$"2I j^M3 x1-hY? M K"Ml%;y.ZKi&$csϭsˏ)qۃʕ95P 2y=zfa=4-6[P ?axav4ئ%MDčznDvT Q0(#b_i $[W<n]Oc8h5 Jo#&|]o;Кn~f1r`+Vb=+*v#,ȎX܎*{AK'RJ7[o =:Ӥ $󿈠DAڱiTPEG UzEռ2@^ۜJSz=,ΛCG&qڕ/q!vS5YGXlf!Qn3wws$T3ǁEi5çp뾡y}W!x$Vj ۳TeaЫ\yQ% #LQ x;L XhA+X,JOЗQe!= VN!oN9}a6CeomlX^9Ykj_p "iea'$~d=R* ch+!i bO~a<:j<ߦpi7Z;cPY&xNVSPSHn s|c`]T]/=qm+e9y U%ά@'^p$px7-S-glVdߐ5K>SչGϪdOKW.OUW& PAXh 6x 2n˞97pw Uw8|8}+,f6ˉ`3K.+OG84 J'.Q1ޤf.z+-a , -C8z@ Gg1'bc;QJ6YRޱ;gB"tlq4HΉG!Wtn~T\Fj髧ڂ$ULtgf//ιhgW9f ^~m8]}rҊJ "5YhemJ+%!k[d#ȥq\$[&:DIx:6j,// d}[-,>ф`+G࡙n}[VVӪD6_pW7yPR5/2C“7s Exhi1~$Wũ4~XJI@!j>g:8H8Eݝ /6MS_$cmoG jI~YU#%EM#,*OV 7~ ֑SZb:AJj=Ztq2d2{"'MzDy.^ЌpU4 ZS3lzfzFxd/ŮD09k<)6}(cb%'S_D7Fzu)5Q[OZMM{ 0YjF}yx[au0?]l Ѥ5ݔ@&atpOLmhLc4%d9cY;z feNl-G<ڮNNL%щzc6@) 2 r[Q,[W#?v.gјC9lXuh +.PmGbCd "QRLZ&gH* Zd^/9A0P&F_{xU)UfoW1ca?1yΈ =D3y<F2{.Қ. ()5>`*fY+?vWZ,4dtݤpSk+gSԏu/=.hAx^ vz-B@eqֲ |Q;,;:mMPlotهg i._+ZvUW(`YP7ܧ%*Ey  endstream endobj 1424 0 obj << /Length1 2202 /Length2 13864 /Length3 0 /Length 15164 /Filter /FlateDecode >> stream xڍP\kwww'w n=xGɹޫbնDIA(ao WS03123"PP\l(4N {;:]db.ovvW C{'^ :#P;x:,,]'ڔEq- djl7vھE45ڛ.傚Łݝ֙ =b P:܀f? (f rKjon l@@;vf@'[p@h_{`adߧp󰱩'`%]<\vf8ۿ7v31@BX`V9:\A6􇛷.ۙ\O 4}k'_7kmgn7(ՁI M[ftp033s%<*U`0+ 2}!x;.N@_+XXf S dh]6{,?>/3{;/_x3pXNn;Q2vr}ku^ RY 1s0a?^o# ISQۂl<6xYW[5@3j]@6%@@3%埃XAVawR`bW3{ũ6&;hN8em8*qk#lx[rϳan;4שcAB jB{>/>֐2y(J ka{5 1z)Mrޑ¸0b\xaN"IC=a+b}XڨTcu#yGy1>C-r*]Z)􉙆lٮBArdpOij qMa|41 TgsN}\Č -W}_7J(kߪcxzDdQ'BEr=߾>ᩪXDq 7p0TarR&@ҿMu0-QM(`ó'/ Vo 7Mz6DH5clW/㙺[-&K&ANSe2N^SqH:|G<-!C/i].AI1iǹ0r09܅k8X9 y˓y9r6%SvJ,n{i.6ZS~:_sM/'Lcȍ$zv}fyt9ݸHܕ#KO(h< n.MYú&9JSiT2$!0|Av`l\ڟ5՝=zB^DTfjII]?71+ x ~iP?YHf}ɶwn'A$:[z<%/αRe0(ҕ؅4c{ج[ "7v"# s _k@{OIyObQev8o(HMCxqxn6J-e=IOw}6(Bnt{UrCcOX[y'UD:,k9<>axUFȐ'NlG\ ծZ'ld{4ĴiS6ӅIm˷ e_,W>q +[>Sy~4"!{) uq#W}ta&pӴ<Kӥ#w)*p; zά"K_z.q  c![D|DdBZ+V֋ oJTײY##*P}|>pH-7Vj7"G@ӡ$b\R81E^)WQwB_fN\5U^=e+<_ DGn1$\CPp岭(^+'!=OTa`WN6ֻJ_>H~!E!\:ŀw[ѧە5~ OLJopf22Ḩ7Z%#wP.#%WFTjHPġVxQ#ݫpc\ax/]0Sk'ޏ%Xem6R4WiqEZvQ DciJ %Jʩȓ7~:P{o]b.[^DR~g2\"A[Y}Xu#J{ف^}>9?-p2y\wntZFsqD#Җs ?>kϿ)߉"t9G-HʘKiN/| ;Fsb!>|abfֶKo(Uh麣[n^Yܹ&u J< -ilU?'Nz_ U!A4RmC! qPQY ʙ'%XfVo61rUrԫrH~~RuzBKD| km acpXUN'fH~QjX 6`וO;m D ~[iT?cr!q`e1̘1w]x'(xm%Y J7ҾO_{'::!@K#x lkbs:8<h0`m TÜOcU _^U"Z^"$ttiׄxͅ}u*PMa#0'٪ l>LvյؠrWkQU>8P@ >ZߙtCֻBťYdU<޲ RLtbZμbz[ZPhy}8-i~+yRĞD_\H"UG cR}]FqiX g-ʊP*0r R8gA _ϥ&lƩ!>MN4M)6w)DU3l6? f|L$RgSW(a'{Rn&b.A=C-2ZP6F mT\aHn,I Ki;w\e^ndً! 9%޽TY'7S/#S `sbl\h(`-+z}K#9Ti>cfxP̮Yz? j@˫%%uF|/ۀm>,=zIJw߾yd)2]=Kt`I,\KMt@*xۦNWth~@ܶ#f*JMF"noFDL1d3@61vE(]|bx ))SN<W8u XToDOM)"QDZnɉJaXD75)C\ۮ)q!()'d:W.rlDO&OrSݔxRv4pS>w6{|/Qn R4.hQt*7;{ںgA7.'GiJUbԞniCnR))/\7 <60h§f F)ڹr.ɓjxر+k(%,>\7i"s̃ q5bHz9a;愡 3nw怲z02h0|B6⃏K SmOSX JTXmRIxR݊zu1d]>dwH 8<~t 1mJ}.dhTx/c,̽ PB&1CN)p^[,{wT3O9iE@YRft^9s )B|QBbkmtXPahCN6mlA3rňV kt"i9a|adH)zkqJ[@- 4Ӧн\T$f[] IZm1:G=(D[M|p٣/5~ޠ/.޳vTaf_v:&ѧ"\6F~&1tHV`DDH!{FBݓ?0,ڠ5EO&"h]XhۙL&i,4̊d ԝt\4639}yuۑ-DZ'on3wnSJ|7a(#m Z3rס5U%?wr(ϩs ,  q_|NڨO̬wO'b!d+E ]; >P0R+4iMB˖fJ@jDn谈ѹgvIh!ҔHQN7Ag| (t$(!0_9s>Qh"@?u;Qϵ\kegK|FϽęԩV Uk|\F~NXK 13\ lTHǙzYU2vo4,+MHhW X"9|Nl"XW}ۙ_A3݂F!7;n5ɷnGE$?ʅ}յT![dL-fmnmf[p!2;খnI0hmpj}s5.KNW>: i<3k(iƌֈ[ʷU(R_k{p*kȖ>3{0{N Sұک9Max ToThFMv"N =gb}*/h@ڄPj˃Gv50Us|є'WqVΡL^ԗxtvKaܕd+:gS4o耗A.?{sݣP Mt AF赟ZW)7S[o+u:+Gˌ&wʷ :nU/l 4<|-5K18=q-ݪ'.#Ovk_ [¼9SХyؽ0yGN`!m6ifzEuy8tAdzd,s?!!A}4+3N_Aljڈ'z\!̔0._a?_V6Ea`НN{]D<ءl|a{_"Nc ͜kKBfңr_+-V5G؏+iU^EL]xg<:=Z?0hTʯk'Fݞ-&?ˊ`oH@Pk0U"EUޠ-#aJ ~I(JKOو\GK*DQ٬f9uF )evnEXp,K׶҅S j -:(U!8÷_8R#\S> 󧲙~g EzՋ9<"kR;B=*~ .!Ϧ'p`+RYC{_Ԋ/m;Zdz0D|qrI2=i7'gJtTd+b斵fmP7"DchBkdqc(dƕᝉHtap7_ k*85W-gX #MY|?5w+4awV-l9C6sL̮ ;%P4wYt}}ٌ!Zۙ6IW<#dPK¼3=r| \BE[r`Bx.9Ng{ԡ7AK(he ,@";ھ⺁Sk4T`='ͣ9~Gi4s5jٙE#jMW"5=}3 (Dqwѳjg=#ڞ4 ]˽pIǓcLsY\͊09S4O=mz!كɦ0\BVleh}?;- 3UJG5å`#{]'W7dxL.')$X3'|%4/Ձ>3ZRq3ORunÌ]o>Ssv0MwR Ƃ=ܫ۟\I1 6F1g;O|ʵxr.Mly@kEOtftoI(ȞI@pHaNeFIfm QG5UQ4AH2,_LF  NO p5Rx~ah WQJ%Үc܀rrNp r/+ÄExgA]M6(cdt@ROtT!۴Hckelv2!s\q1; ŶMsf^x ?%Bס|$gnnF˟׬msTe?v?-eԹ T6҅SSIsܿӣnP.ڍG5>pokGIP=u%bQNxAz}ܴB8S + %g6/2!)P:2uMI\$c1^/`8;' ,^[9YXPٹݭF &*%jre.{:NfA|TJ7]) x5qe8 1F uX/A`qmSKa"0ٙ"<5Q^gO D+$?'+-w&Dz|˶QcD"" H׬!$ bM=S.'I /׸p8 J[ Ū,I.?hIH޷ eVj:6 XEsu)V Uvcz{ 'ދu&Wm6x/HAWߦVp ,m (n?>^c"WqNX85(~頊S0fv*yYjo5D،A|Uqd:s3ND9l5Si6 iEA^sF>8hDWs_[}W#kPl8h}vʁ 94k1(e5[}.6n HU`+;NGJ&`,[DRSܚq[Hޑ"e{4)u"5,M1&Z NTIvПc HYa?~ӯ0|'W%;B/NiǜX|AmB:.!@(|Ub )(!P '"PPCB˦]'I-8{@􄝒PO]Z~ &QNۆp3UՍmkQ'm_|,jarfr՚YxS= h(## bt`ɓ0.dO#; &?',>R [æfo%.NalM*#H]U<ΩD"d}赗JgwTz8.x+ IJJ?]&".Zn@KWduQ# mWYa)Vf>|nvԏ$1*)fjDd,0. _p`.!>`73]z5cR8LAi[֠ЭP eT\̷ۚ k_9)D:ӈ9$Næ?}*.UItEnnO~.h$. l?m=HnFlIˉo[N5>0*N^蠦_+MIoODںT8dA'b8(}=B:Ym9y]6+lkR磅W,c*!| QG"r@/-X|2a`kpPv͸;:y iVW.cb5h>2r$FbU‡JF,Mʤh;%b+sJ%:FGȱ!**{jg,NEfmgx|[R_ &I:=OQ֛5VSR59Ѐl̼;H^]\@m) ob@V<% -9 }l t2Oω6#f$ݒ%]p]p<91XG!3 vp,R(}zESx3 udh {Dp;{-:B[%shC.0g5 ~h$VpD"St͎'4Zvfsǚf !=Lo 0%WL>FjT=l`XJAXzo?eODH [t _v G+.+'m (\sPjtѳf0 5 ES즏V6j3LէQG3#"0 "q7wLL ٜځaظ9 -sߒhpU>'W#RZURo*0"v\Vm >ҩZ}=h'̗9`ߍP*rΡ5M9sV'+g& MKաH{m ijI:dͿLn@E mI tُHbm5O.~KatR {EEv;uR"Yy +iK vP +:;I\QBx~UQ͛f>#|K&ّ8!x2 8:?N/Y!I~.uDJIҭcԜ'eXvÉ^2VLPxڷoX(ߎ2G29gX-*f #CT h>G(*Uz+yy_cW|9u~^h O2)XhoKJ)K9 v4}ZN ~_fK{bgBEh:%R Pg'$fl$;E {f TW2[ג'dJLq-W,#|[9]e;[źg;&E&J©6κF><{D0'|D(3 _ F5\Naq}qX:Mz9;S-JLGQS*!{/` k"pl."j=LG <$ $DyЫ}$~tT(Zż.gVN`IG?i(CKkLnb(yrR3s 5gMLtJ6dV#'y|n)[DJ0L騼f~qf*-zDlWj}RH{DӭSyR30lC%Z<]|`?ny[$_Vs]lIMl䩭=t?{WiXrQ]e 6}P>OvT ]^x-8!pDxTW0,lK 'O@HW]Ο86;c]̩Ea:W Jlβ~F%+skq;S3-qb( J~Km'A8a=4O,i1 1|;dϢsHj9C c-5 p;b}ɜ +WҺAམ0OS#{Wa&ߤN ޜ91r]ه^*$v VIx@]< XDsNUfDmܨwe'G}:<1u&įONID*a֕Ee$!&1? 86`Wg B7ccGpx̴> <`-NpgLRt|)K[oWϟ|1t~ty|Հ>/x6U*$Eӂ-06ҭv4jkrHCJ\< ;Ck9K&lJ)2^+ذeƭ DOسM xeʎLp "FX˴/' y#ۥ^>ĜQy(̕Sˤ-2=ghDw!1 ->ImƲGFCp/|܄2-*@s7l|8o tMm'ʝ8Y}#÷69'GS3Dr"#}7;wHt(d`ɒ0Q.@_V8@RQx$;fTNV8yH]ݭo 3uMeIzMHVݢޭ."dW@3ÌN}v ߙJ]SE|;NȞ;4k abPd !Im"mu5/csZU@NYOSHvեNa;k#V+I2ӼpN%>@߼_ 2|&a|%A ΎƼW: m?~§EKV}"ڭ!k>MkX=PJlke E4BCm0V d3hSUѹ(j0o$;Frih2}ho_yp{CbG^G1iFtr}VbR?EJX}m:gmYC}b9Em0OCQ6VBf1qg^(l."xAc#]%•/39Fb2J<Qom̒9a`qyX%#q{KN+)3>?f' mcuy8SL[ns; >+*HqjPrRz W{8I/'.8VD!3+?Oy29[bN. ls-#^}]4п ފd;i,/NKP33JP~fKxeиxv/LM`Ǧp38Bջ4-*DZ&F"A b35`k4a-MU}0'4 Y* rhe`ajB"#, iO+c;c0> stream x\[s~ׯsj+V:U9%YNJ+4H{CbI/0 | 2NURJ)Simb+c= uB\%R8*Z B7H%ʦH5"0I5"d\BTZb n@*)B *9.*%q \Hq2e GXijaP*HU50LۈBªA -UDU⣩/ Fjx[X[{gA\r4-^A=`*(s6 Z|18 bK4`l Fl6 r0@i UE.*( 1F ʉRSс[5O* @X@Dژ@I9\aR^y}`nJL=qzw=?]ֳ E)=lcH NE8i%^Ug!~ #~ G(i6s; !~*ٌSx~q#?v/#䧓H7oGxvϫB|6wϦrOIiJ~ 탬WoU`d5ߪt f`h"=r4"'7>1q2^ְJ:ć/g=Y\e>]s _:SUHpbrL?X }eU8Uʀ1lQ 9pP*J;@{J<>0VhfԠjiǂD߃+@AOa,QwC އ2J%@Xmq-iL,ԁ,%H)aVdc@ XA(LdZ"S2ĦjD=%XKQqfZ˞% PS`[ԞSs+B[▋.g>VB0^v:DiDBLc\2&0.Sj+I-H&OK-pjJA:hizs+5;eQ-"g=^#1V8%`0i1HAx@KȮ$&3),XbHMG73xHѓrC&TV޲γ.vgä zY:~5ㄞ8gKK.K&r`qCzMc%]mɣ{()eXgU L9z(bB|cH`HE%1&QVl@EI5)iK!'&"r"Lt\b)*S$F4kQԒ %L=pyzـ1| iPꤡNO3 =n%'q8#u%jM>%B/:{ztuTqO |‡oj\W@tQ|iO|ʃ@p%^}R kF#q,މx/NU|g71B\L 77Cq)jE|ĕn1I-nm=M/şb&b!׳N%_7?lo`3+xӳ7G?}~Rz3 xjҎ@M*cڳ% DaUo퀌뿠|Uu@Or?~z O~:|W[Y. !w܆qJgËqe?Zݝ/VfqK?Ekϐ 5&j6_7qp[7yn$uNW=." b.B߁-FIpـ;ڠцW'O@iY5؂-Fݫ=vmDm8}X/E\ᢞ5nxs~9z>xspnGfS܀ͶAnׇja3AU]/,?YfO^yNJ6Є@LndQzE/:>#'lX#0ԎUzpr4Wm<(_r+qz-#zCjt7]Y:m?+|glV(Kӣ-S\:*+`n8@o.QQ _E c (fE §-mnqw]T|LݛAwvnf+zrdV6ãׇǨ$=@7Ni :‚"ވj-?=y{v.gÛ7~7K&`vz,o_[9?x~z`FyMP}/Bb{gۣ=&j+_~~AЛ*޾_x_k#|@ǻk N g !+Awz6{7ʣ zڻrzԿ1&pffm^Ww֫`)cW `jy`7h{x WVl6{χ%*9]Ḿi4M&7׸f4ws7^nĤܗu.n60c\oB}+1}p OBԻF #FHg[ówGncDvmyY:6vz+r]GPyC>(IO.14N.p~1>:h;ini\s&|9btBpNE{<ҳ<~<:HjUVFgkՃ=:a<dѷ{̕߻j~ >25ԞrSf[hL\6.!o̬Aߒ 帓0 sH hxк%Hٓ,7RiPH>cj{_ -ǎcf|V/V+59><UYz9ܥ{lw˚I"'fZ61u1?(\E[N.,/ - endstream endobj 1431 0 obj << /Type /ObjStm /N 100 /First 942 /Length 3447 /Filter /FlateDecode >> stream xڥZr6}WzP V*UxSڱ6)5Y!G~A4IF}}N7.,)X!,_ZRBU!< Ky!)[H 46qBr~ a>30{g`@VBC\H] .5* X9! 2 X06 l [A0 ; +0 0Vy0VkP/4%+k<+Ăq8!cz@\0$U BtPYc h'5*"$g؆k0vl@,=e Ő7DC \+,T4})$ V hʫƼq@(`jhB DZ 1 `-Uh|@.[N^>d HbTPW^A6-Ta@C, \m F{ _xz!7 oPOP`,:g *g  g`Ōtẕ?` 9&\0r4Z C_ *\cŹP+Ý?pqa*( XC}my]Xz K;<O?`Kb% `AX&gl=NY3$e{l1(MsWzd+ܚaS,1T5,T 9bT:r!0 +!2X|du&,)MR;Säʹˑ<''eH y#FLl$Ci Vx <)TN2it!\ ap?tΒOrһ9Y +WgO 2Xc_2Iq1]FbƬ+F9gԎ3o\jkZ2 %W!Ps5ǬYV7R1$:+g#vѹNRWl𦬫+~YUR_ulˢ/vl}#mpsw\%VVHу ^ :CLZ:s`Ns .HO%3:|r+dd4n zadMQKKELN&&TǠ‘ǖ( 52"521e6!EQ"*-dy5*'0(1bq#.-^8W&u,$:m\kJ,҇8pg1V.*e1K| %Z\f, {)ǖq)QY)5zp )ɨ^`.9d,="7U%gPdp3M^e'WW>AYT/7͗]uPÑUOcxu_#N=Mն͇ۛ//Nh}'"܇r݂[IU~7!u_},KV`m^}<~nuXnz;nN]v}.{8cϫ5g S^mͱꪕ8MWTUGl5Ӷyx"N>$ <.(v^ʧl[H9{eOw_NMmImŚ|]vrc2R|}ە]Iѕw|t߿6]TʄŀͺCkomW;6A .ڥnav+Ypi*YFm9F}E67{(/붇]r+ﶁ- |$ 2oz}2~it_|':⛪?d.]|YKd+Sa/:~7 OFIs xP8qhf4P7uWmwntb==`ce?uyW̫nB9Ce.׷((@oIC[X] &F&])5ҋt,Lmofn__󄵓3s ;?RmdSֈG:2zT=; x3GL?tl6],&/'⌈ y hlb+Eg6t蠗v-ꅻ1x]w]:Ӡ3{${J:-tӛ"up4O{ƤpImF1hyD*T擄Taanwͮifa=zQj Fį *Qߵw倥/-j{o9WlCvE8G"#mIOb-QV5x]㋁3,fS8hgn(:-:\1$oA5o26]MY`F317MI˿9T{NEYWio,317IȚhSjJ-rZHm%}اDWcg"ơ%t 7i/ܬ/LG֧`!Ǟ ^?_1|gMv"~4:4_#~ԣ?cc0dЌ_;DSI')U9af==Xr: E M C ;o9>6agvlo%s~e&XE) NQpqwg;6|ckESB&4E|-xއ IM$5Ԥ;xgC 7DP Eg[]CST!A, b)X"cUF_ endstream endobj 1482 0 obj << /Producer (pdfTeX-1.40.20) /Creator (TeX) /CreationDate (D:20240513155432+02'00') /ModDate (D:20240513155432+02'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) kpathsea version 6.3.1) >> endobj 1478 0 obj << /Type /ObjStm /N 4 /First 33 /Length 172 /Filter /FlateDecode >> stream x3417W0P041T03@ qp{g+D՘rdf42ӭ S4ԤX.;;Tf M5ĭ%>.hHeAsbIbN~:~@bz*HDiINfX"䗘 [@ -@CSaAH endstream endobj 1483 0 obj << /Type /XRef /Index [0 1484] /Size 1484 /W [1 3 1] /Root 1481 0 R /Info 1482 0 R /ID [ ] /Length 3680 /Filter /FlateDecode >> stream x%{t]U;ޛͫIڦy4ѼIڤm4mڦMGaO"pEs:0ttq \\vPFAAg{>A @tAo;e R((2(e T@%T X VC BhFhfh mz ,,a6=ʡ j:`63pNx)(+ Ca .Ǐ6 p Ea` lm0ah%Xq^  p V(L~8IʡAcg MC9tT;ub͜Vnb ,@/l^G^iOl1` 4@sE Vz9 Gy5B:y~v=1-“p/չm&e{ F=[?tȌ:&mZ{1 ,ئk1p,#;Iev)jmK(41Ơe2bo+#ƨ}u_All%U VG 23U13XX31m:ډ1XzbP#cz:5Q3!|e¶BLOA3Nl1f8KV:bSV41DK5b3QYRvQbzV.Se؍45QL,l&.b_f;J1hVsF2QiZHLv|&3efH"d8[],#e hr{_:Cd80P12j,bi2j&.lZKǺ)Z0'@?;/X\_zng$;"c6_-B \]v,%G(YL-OlɀR \гuP-[Tq%8e=͵=%"N \gEsR. v~WZ4Faf=e|=(㰕yDܫq"ׅ2UtYt%혆) .,~Lgsa/COj/N:+ 8gZ:!/04g%++r6 !g |y\cKtu&I~i"#D~HPc: lBtJcՠTHEgpyootixLcҘ XU"O,VC-Tpmp%<<zŒh,18'4Ix)gElױ_B$IԻ[HIhjJ I@ܽK %WB %ˡDk/ uP4IP%  ڪQ> QCr_M;yr=;xsO?{泟zsO๏?G=Pg={>w9?>IҋX +%x6WAD_jZ_iGD_{?o<߸=ϥy?۵C4HPcz;ZhԃkG A;t@'J .Ɠl@]p!e0h>1pT4^s!"H(WU%@bTʠ GJ,V(G:( $Q (G 8Juvd9wܑsG9wܑsG9wܑsG9wܑsG9wܑsG9wܑsG9wܑsG9wܑsG9wuב_G~uב_G~uב_6 F5Go֌͒zQwfyְDh2 ayK/f)C 9$cX5X14Pg ˆVC 8eX;4,ޘ L ZkX14-X1mFYI忯'-?=[}0v +" pUD X5,1ެ 5`X5;/a-Lh5_ aemfUv*a=a`ΰhX3` `Eذ.oX7,^ kumD_" 1ُ~Lck}ѼяIQSnXoi)XoXK1CL1CL1CL1CL1CL1CL1C' /jdn5IV "?~JJje&sv|_:$N JoѭN)8Z)V|n Hst ITLb ȑ0U_]rׂ.Ru9]rK娺bT]NdEc]rx4躭g-UrT]NuQu9]Ul q29N&7Hѿ UD&{9K%JR$E;CѮ=_#n# endstream endobj startxref 608331 %%EOF queueing/doc/markovchains.texi0000664000175000017500000012630714620415615016424 0ustar morenomoreno@c This file has been automatically generated from markovchains.txi @c by proc.m. Do not edit this file, all changes will be lost @c -*- texinfo -*- @c Copyright (C) 2008, 2009, 2010, 2011, 2012, 2014, 2018 Moreno Marzolla @c @c This file is part of the queueing package. @c @c The queueing package is free software; you can redistribute it @c and/or modify it under the terms of the GNU General Public License @c as published by the Free Software Foundation; either version 3 of @c the License, or (at your option) any later version. @c @c The queueing package is distributed in the hope that it will be @c useful, but WITHOUT ANY WARRANTY; without even the implied warranty @c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @c GNU General Public License for more details. @c @c You should have received a copy of the GNU General Public License @c along with the queueing package; see the file COPYING. If not, see @c . @node Markov Chains @chapter Markov Chains @menu * Discrete-Time Markov Chains:: * Continuous-Time Markov Chains:: @end menu @node Discrete-Time Markov Chains @section Discrete-Time Markov Chains Let @math{X_0, X_1, @dots{}, X_n, @dots{} } be a sequence of random variables defined over the discrete state space @math{1, 2, @dots{}}. The sequence @math{X_0, X_1, @dots{}, X_n, @dots{}} is a @emph{stochastic process} with discrete time @math{0, 1, 2, @dots{}}. A @emph{Markov chain} is a stochastic process @math{@{X_n, n=0, 1, @dots{}@}} which satisfies the following Markov property: @iftex @tex $$\eqalign{P\left(X_{n+1} = x_{n+1}\ |\ X_n = x_n, X_{n-1} = x_{n-1}, \ldots, X_0 = x_0 \right) \cr & = P\left(X_{n+1} = x_{n+1}\ |\ X_n = x_n\right)}$$ @end tex @end iftex @ifnottex @math{P(X_{n+1} = x_{n+1} | X_n = x_n, X_{n-1} = x_{n-1}, @dots{}, X_0 = x_0) = P(X_{n+1} = x_{n+1} | X_n = x_n)} @end ifnottex @noindent which basically means that the probability that the system is in a particular state at time @math{n+1} only depends on the state the system was at time @math{n}. The evolution of a Markov chain with finite state space @math{@{1, @dots{}, N@}} can be fully described by a stochastic matrix @math{{\bf P}(n) = [ P_{i,j}(n) ]} where @math{P_{i, j}(n) = P( X_{n+1} = j\ |\ X_n = i )}. If the Markov chain is homogeneous (that is, the transition probability matrix @math{{\bf P}(n)} is time-independent), we can write @math{{\bf P} = [P_{i, j}]}, where @math{P_{i, j} = P( X_{n+1} = j\ |\ X_n = i )} for all @math{n=0, 1, @dots{}}. @cindex stochastic matrix The transition probability matrix @math{\bf P} must be a @emph{stochastic matrix}, meaning that it must satisfy the following two properties: @enumerate @item @math{P_{i, j} @geq{} 0} for all @math{1 @leq{} i, j @leq{} N}; @item @math{\sum_{j=1}^N P_{i,j} = 1} for all @math{i} @end enumerate Property 1 requires that all probabilities are nonnegative; property 2 requires that the outgoing transition probabilities from any state @math{i} sum to one. @c @anchor{doc-dtmcchkP} @deftypefn {Function File} {[@var{r} @var{err}] =} dtmcchkP (@var{P}) @cindex Markov chain, discrete time @cindex DTMC @cindex discrete time Markov chain Check whether @var{P} is a valid transition probability matrix. If @var{P} is valid, @var{r} is the size (number of rows or columns) of @var{P}. If @var{P} is not a transition probability matrix, @var{r} is set to zero, and @var{err} to an appropriate error string. @end deftypefn A DTMC is @emph{irreducible} if every state can be reached with non-zero probability starting from every other state. @anchor{doc-dtmcisir} @deftypefn {Function File} {[@var{r} @var{s}] =} dtmcisir (@var{P}) @cindex Markov chain, discrete time @cindex discrete time Markov chain @cindex DTMC @cindex irreducible Markov chain Check if @var{P} is irreducible, and identify Strongly Connected Components (SCC) in the transition graph of the DTMC with transition matrix @var{P}. @strong{INPUTS} @table @code @item @var{P}(i,j) transition probability from state @math{i} to state @math{j}. @var{P} must be an @math{N \times N} stochastic matrix. @end table @strong{OUTPUTS} @table @code @item @var{r} 1 if @var{P} is irreducible (i.e., the state transition graph is strongly connected), 0 otherwise (scalar) @item @var{s}(i) strongly connected component (SCC) that state @math{i} belongs to (vector of length @math{N}). SCCs are numbered @math{1, 2, @dots{}}. The number of SCCs is @code{max(s)}. If the graph is strongly connected, then there is a single SCC and the predicate @code{all(s == 1)} evaluates to true @end table @end deftypefn @menu * State occupancy probabilities (DTMC):: * Birth-death process (DTMC):: * Expected number of visits (DTMC):: * Time-averaged expected sojourn times (DTMC):: * Mean time to absorption (DTMC):: * First passage times (DTMC):: @end menu @c @c @c @node State occupancy probabilities (DTMC) @subsection State occupancy probabilities Given a discrete-time Markov chain with state space @math{@{1, @dots{}, N@}}, we denote with @math{{\bf \pi}(n) = \left[\pi_1(n), @dots{} \pi_N(n) \right]} the @emph{state occupancy probability vector} at step @math{n = 0, 1, @dots{}}. @math{\pi_i(n)} is the probability that the system is in state @math{i} after @math{n} transitions. Given the transition probability matrix @math{\bf P} and the initial state occupancy probability vector @math{{\bf \pi}(0) = \left[\pi_1(0), @dots{}, \pi_N(0)\right]}, @math{{\bf \pi}(n)} can be computed as: @iftex @tex $${\bf \pi}(n) = {\bf \pi}(0) {\bf P}^n$$ @end tex @end iftex @ifnottex @math{\pi(n) = \pi(0) P^n} @end ifnottex Under certain conditions, there exists a @emph{stationary state occupancy probability} @math{{\bf \pi} = \lim_{n \rightarrow +\infty} {\bf \pi}(n)}, which is independent from @math{{\bf \pi}(0)}. The vector @math{\bf \pi} is the solution of the following linear system: @iftex @tex $$ \left\{ \eqalign{ {\bf \pi P} & = {\bf \pi} \cr {\bf \pi 1}^T & = 1 } \right. $$ @end tex @end iftex @ifnottex @example @group / | \pi P = \pi | \pi 1^T = 1 \ @end group @end example @end ifnottex @noindent where @math{\bf 1} is the row vector of ones, and @math{( \cdot )^T} the transpose operator. @c @anchor{doc-dtmc} @deftypefn {Function File} {@var{p} =} dtmc (@var{P}) @deftypefnx {Function File} {@var{p} =} dtmc (@var{P}, @var{n}, @var{p0}) @cindex Markov chain, discrete time @cindex discrete time Markov chain @cindex DTMC @cindex Markov chain, stationary probabilities @cindex Markov chain, transient probabilities Compute stationary or transient state occupancy probabilities for a discrete-time Markov chain. With a single argument, compute the stationary state occupancy probabilities @code{@var{p}(1), @dots{}, @var{p}(N)} for a discrete-time Markov chain with finite state space @math{@{1, @dots{}, N@}} and with @math{N \times N} transition matrix @var{P}. With three arguments, compute the transient state occupancy probabilities @code{@var{p}(1), @dots{}, @var{p}(N)} that the system is in state @math{i} after @var{n} steps, given initial occupancy probabilities @var{p0}(1), @dots{}, @var{p0}(N). @strong{INPUTS} @table @code @item @var{P}(i,j) transition probabilities from state @math{i} to state @math{j}. @var{P} must be an @math{N \times N} irreducible stochastic matrix, meaning that the sum of each row must be 1 (@math{\sum_{j=1}^N P_{i, j} = 1}), and the rank of @var{P} must be @math{N}. @item @var{n} Number of transitions after which state occupancy probabilities are computed (scalar, @math{n @geq{} 0}) @item @var{p0}(i) probability that at step 0 the system is in state @math{i} (vector of length @math{N}). @end table @strong{OUTPUTS} @table @code @item @var{p}(i) If this function is called with a single argument, @code{@var{p}(i)} is the steady-state probability that the system is in state @math{i}. If this function is called with three arguments, @code{@var{p}(i)} is the probability that the system is in state @math{i} after @var{n} transitions, given the probabilities @code{@var{p0}(i)} that the initial state is @math{i}. @end table @xseealso{ctmc} @end deftypefn @noindent @strong{EXAMPLE} The following example is from @ref{GrSn97}. Let us consider a maze with nine rooms, as shown in the following figure @example @group +-----+-----+-----+ | | | | | 1 2 3 | | | | | +- -+- -+- -+ | | | | | 4 5 6 | | | | | +- -+- -+- -+ | | | | | 7 8 9 | | | | | +-----+-----+-----+ @end group @end example A mouse is placed in one of the rooms and can wander around. At each step, the mouse moves from the current room to a neighboring one with equal probability. For example, if it is in room 1, it can move to room 2 and 4 with probability @math{1/2}, respectively; if the mouse is in room 8, it can move to either 7, 5 or 9 with probability @math{1/3}. The transition probabilities @math{P_{i, j}} from room @math{i} to room @math{j} can be summarized in the following matrix: @iftex @tex $$ {\bf P} = \pmatrix{ 0 & 1/2 & 0 & 1/2 & 0 & 0 & 0 & 0 & 0 \cr 1/3 & 0 & 1/3 & 0 & 1/3 & 0 & 0 & 0 & 0 \cr 0 & 1/2 & 0 & 0 & 0 & 1/2 & 0 & 0 & 0 \cr 1/3 & 0 & 0 & 0 & 1/3 & 0 & 1/3 & 0 & 0 \cr 0 & 1/4 & 0 & 1/4 & 0 & 1/4 & 0 & 1/4 & 0 \cr 0 & 0 & 1/3 & 0 & 1/3 & 0 & 0 & 0 & 1/3 \cr 0 & 0 & 0 & 1/2 & 0 & 0 & 0 & 1/2 & 0 \cr 0 & 0 & 0 & 0 & 1/3 & 0 & 1/3 & 0 & 1/3 \cr 0 & 0 & 0 & 0 & 0 & 1/2 & 0 & 1/2 & 0 } $$ @end tex @end iftex @ifnottex @example @group / 0 1/2 0 1/2 0 0 0 0 0 \ | 1/3 0 1/3 0 1/3 0 0 0 0 | | 0 1/2 0 0 0 1/2 0 0 0 | | 1/3 0 0 0 1/3 0 1/3 0 0 | P = | 0 1/4 0 1/4 0 1/4 0 1/4 0 | | 0 0 1/3 0 1/3 0 0 0 1/3 | | 0 0 0 1/2 0 0 0 1/2 0 | | 0 0 0 0 1/3 0 1/3 0 1/3 | \ 0 0 0 0 0 1/2 0 1/2 0 / @end group @end example @end ifnottex The stationary state occupancy probabilities can then be computed with the following code: @example @group @verbatim P = zeros(9,9); P(1,[2 4] ) = 1/2; P(2,[1 5 3] ) = 1/3; P(3,[2 6] ) = 1/2; P(4,[1 5 7] ) = 1/3; P(5,[2 4 6 8]) = 1/4; P(6,[3 5 9] ) = 1/3; P(7,[4 8] ) = 1/2; P(8,[7 5 9] ) = 1/3; P(9,[6 8] ) = 1/2; p = dtmc(P); disp(p) @end verbatim @end group @result{} 0.083333 0.125000 0.083333 0.125000 0.166667 0.125000 0.083333 0.125000 0.083333 @end example @c @node Birth-death process (DTMC) @subsection Birth-death process @anchor{doc-dtmcbd} @deftypefn {Function File} {@var{P} =} dtmcbd (@var{b}, @var{d}) @cindex Markov chain, discrete time @cindex DTMC @cindex discrete time Markov chain @cindex birth-death process, DTMC Returns the transition probability matrix @math{P} for a discrete birth-death process over state space @math{@{1, @dots{}, N@}}. For each @math{i=1, @dots{}, (N-1)}, @code{@var{b}(i)} is the transition probability from state @math{i} to @math{(i+1)}, and @code{@var{d}(i)} is the transition probability from state @math{(i+1)} to @math{i}. Matrix @math{\bf P} is defined as: @tex $$ \pmatrix{ (1-\lambda_1) & \lambda_1 & & & & \cr \mu_1 & (1 - \mu_1 - \lambda_2) & \lambda_2 & & \cr & \mu_2 & (1 - \mu_2 - \lambda_3) & \lambda_3 & & \cr \cr & & \ddots & \ddots & \ddots & & \cr \cr & & & \mu_{N-2} & (1 - \mu_{N-2}-\lambda_{N-1}) & \lambda_{N-1} \cr & & & & \mu_{N-1} & (1-\mu_{N-1}) } $$ @end tex @ifnottex @example @group / \ | 1-b(1) b(1) | | d(1) (1-d(1)-b(2)) b(2) | | d(2) (1-d(2)-b(3)) b(3) | | | | ... ... ... | | | | d(N-2) (1-d(N-2)-b(N-1)) b(N-1) | | d(N-1) 1-d(N-1) | \ / @end group @end example @end ifnottex @noindent where @math{\lambda_i} and @math{\mu_i} are the birth and death probabilities, respectively. @xseealso{ctmcbd} @end deftypefn @c @node Expected number of visits (DTMC) @subsection Expected Number of Visits Given a @math{N} state discrete-time Markov chain with transition matrix @math{\bf P} and an integer @math{n @geq{} 0}, we let @math{L_i(n)} be the the expected number of visits to state @math{i} during the first @math{n} transitions. The vector @math{{\bf L}(n) = \left[ L_1(n), @dots{}, L_N(n) \right]} is defined as @iftex @tex $$ {\bf L}(n) = \sum_{i=0}^n {\bf \pi}(i) = \sum_{i=0}^n {\bf \pi}(0) {\bf P}^i $$ @end tex @end iftex @ifnottex @example @group n n ___ ___ \ \ i L(n) = > pi(i) = > pi(0) P /___ /___ i=0 i=0 @end group @end example @end ifnottex @noindent where @math{{\bf \pi}(i) = {\bf \pi}(0){\bf P}^i} is the state occupancy probability after @math{i} transitions, and @math{{\bf \pi}(0) = \left[\pi_1(0), @dots{}, \pi_N(0) \right]} are the initial state occupancy probabilities. If @math{\bf P} is absorbing, i.e., the stochastic process eventually enters a state with no outgoing transitions, then we can compute the expected number of visits until absorption @math{\bf L}. To do so, we first rearrange the states by rewriting @math{\bf P} as @iftex @tex $$ {\bf P} = \pmatrix{ {\bf Q} & {\bf R} \cr {\bf 0} & {\bf I} }$$ @end tex @end iftex @ifnottex @example @group / Q | R \ P = |---+---| \ 0 | I / @end group @end example @end ifnottex @noindent where the first @math{t} states are transient and the last @math{r} states are absorbing (@math{t+r = N}). The matrix @math{{\bf N} = ({\bf I} - {\bf Q})^{-1}} is called the @emph{fundamental matrix}; @math{N_{i,j}} is the expected number of times the process is in the @math{j}-th transient state assuming it started in the @math{i}-th transient state. If we reshape @math{\bf N} to the size of @math{\bf P} (filling missing entries with zeros), we have that, for absorbing chains, @math{{\bf L} = {\bf \pi}(0){\bf N}}. @anchor{doc-dtmcexps} @deftypefn {Function File} {@var{L} =} dtmcexps (@var{P}, @var{n}, @var{p0}) @deftypefnx {Function File} {@var{L} =} dtmcexps (@var{P}, @var{p0}) @cindex expected sojourn times, DTMC @cindex DTMC @cindex discrete time Markov chain @cindex Markov chain, discrete time Compute the expected number of visits to each state during the first @var{n} transitions, or until abrosption. @strong{INPUTS} @table @code @item @var{P}(i,j) @math{N \times N} transition matrix. @code{@var{P}(i,j)} is the transition probability from state @math{i} to state @math{j}. @item @var{n} Number of steps during which the expected number of visits are computed (@math{@var{n} @geq{} 0}). If @code{@var{n}=0}, returns @var{p0}. If @code{@var{n} > 0}, returns the expected number of visits after exactly @var{n} transitions. @item @var{p0}(i) Initial state occupancy probabilities; @code{@var{p0}(i)} is the probability that the system is in state @math{i} at step 0. @end table @strong{OUTPUTS} @table @code @item @var{L}(i) When called with two arguments, @code{@var{L}(i)} is the expected number of visits to state @math{i} before absorption. When called with three arguments, @code{@var{L}(i)} is the expected number of visits to state @math{i} during the first @var{n} transitions. @end table @strong{REFERENCES} @itemize @item Grinstead, Charles M.; Snell, J. Laurie (July 1997). @cite{Introduction to Probability}, Ch. 11: Markov Chains. American Mathematical Society. ISBN 978-0821807491. @end itemize @xseealso{ctmcexps} @end deftypefn @c @node Time-averaged expected sojourn times (DTMC) @subsection Time-averaged expected sojourn times @anchor{doc-dtmctaexps} @deftypefn {Function File} {@var{M} =} dtmctaexps (@var{P}, @var{n}, @var{p0}) @deftypefnx {Function File} {@var{M} =} dtmctaexps (@var{P}, @var{p0}) @cindex time-alveraged sojourn time, DTMC @cindex discrete time Markov chain @cindex Markov chain, discrete time @cindex DTMC Compute the @emph{time-averaged sojourn times} @code{@var{M}(i)}, defined as the fraction of time spent in state @math{i} during the first @math{n} transitions (or until absorption), assuming that the state occupancy probabilities at time 0 are @var{p0}. @strong{INPUTS} @table @code @item @var{P}(i,j) @math{N \times N} transition probability matrix. @item @var{n} Number of transitions during which the time-averaged expected sojourn times are computed (scalar, @math{@var{n} @geq{} 0}). if @math{@var{n} = 0}, returns @var{p0}. @item @var{p0}(i) Initial state occupancy probabilities (vector of length @math{N}). @end table @strong{OUTPUTS} @table @code @item @var{M}(i) If this function is called with three arguments, @code{@var{M}(i)} is the expected fraction of steps @math{@{0, @dots{}, n@}} spent in state @math{i}, assuming that the state occupancy probabilities at time zero are @var{p0}. If this function is called with two arguments, @code{@var{M}(i)} is the expected fraction of steps spent in state @math{i} until absorption. @var{M} is a vector of length @math{N}. @end table @xseealso{dtmcexps} @end deftypefn @c @node Mean time to absorption (DTMC) @subsection Mean Time to Absorption The @emph{mean time to absorption} is defined as the average number of transitions that are required to enter an absorbing state, starting from a transient state or given initial state occupancy probabilities @math{{\bf \pi}(0)}. Let @math{t_i} be the expected number of transitions before being absorbed in any absorbing state, starting from state @math{i}. The vector @math{{\bf t} = [t_1, @dots{}, t_N]} can be computed from the fundamental matrix @math{\bf N} (@pxref{Expected number of visits (DTMC)}) as @iftex @tex $$ {\bf t} = {\bf N c} $$ @end tex @end iftex @ifnottex @math{t = N c} @end ifnottex @noindent where @math{\bf c} is a column vector of 1's. Let @math{{\bf B} = [ B_{i, j} ]} be a matrix where @math{B_{i, j}} is the probability of being absorbed in state @math{j}, starting from transient state @math{i}. Again, using matrices @math{\bf N} and @math{\bf R} (@pxref{Expected number of visits (DTMC)}) we can write @iftex @tex $$ {\bf B} = {\bf N R} $$ @end tex @end iftex @ifnottex @math{B = N R} @end ifnottex @anchor{doc-dtmcmtta} @deftypefn {Function File} {[@var{t} @var{N} @var{B}] =} dtmcmtta (@var{P}) @deftypefnx {Function File} {[@var{t} @var{N} @var{B}] =} dtmcmtta (@var{P}, @var{p0}) @cindex mean time to absorption, DTMC @cindex absorption probabilities, DTMC @cindex fundamental matrix @cindex DTMC @cindex discrete time Markov chain @cindex Markov chain, discrete time Compute the expected number of steps before absorption for a DTMC with state space @math{@{1, @dots{}, N@}} and transition probability matrix @var{P}. @strong{INPUTS} @table @code @item @var{P}(i,j) @math{N \times N} transition probability matrix. @code{@var{P}(i,j)} is the transition probability from state @math{i} to state @math{j}. @item @var{p0}(i) Initial state occupancy probabilities (vector of length @math{N}). @end table @strong{OUTPUTS} @table @code @item @var{t} @itemx @var{t}(i) When called with a single argument, @var{t} is a vector of length @math{N} such that @code{@var{t}(i)} is the expected number of steps before being absorbed in any absorbing state, starting from state @math{i}; if @math{i} is absorbing, @code{@var{t}(i) = 0}. When called with two arguments, @var{t} is a scalar, and represents the expected number of steps before absorption, starting from the initial state occupancy probability @var{p0}. @item @var{N}(i) @itemx @var{N}(i,j) When called with a single argument, @var{N} is the @math{N \times N} fundamental matrix for @var{P}. @code{@var{N}(i,j)} is the expected number of visits to transient state @var{j} before absorption, if the system started in transient state @var{i}. The initial state is counted if @math{i = j}. When called with two arguments, @var{N} is a vector of length @math{N} such that @code{@var{N}(j)} is the expected number of visits to transient state @var{j} before absorption, given initial state occupancy probability @var{P0}. @item @var{B}(i) @itemx @var{B}(i,j) When called with a single argument, @var{B} is a @math{N \times N} matrix where @code{@var{B}(i,j)} is the probability of being absorbed in state @math{j}, starting from transient state @math{i}; if @math{j} is not absorbing, @code{@var{B}(i,j) = 0}; if @math{i} is absorbing, @code{@var{B}(i,i) = 1} and @code{@var{B}(i,j) = 0} for all @math{i \neq j}. When called with two arguments, @var{B} is a vector of length @math{N} where @code{@var{B}(j)} is the probability of being absorbed in state @var{j}, given initial state occupancy probabilities @var{p0}. @end table @strong{REFERENCES} @itemize @item Grinstead, Charles M.; Snell, J. Laurie (July 1997). @cite{Introduction to Probability}, Ch. 11: Markov Chains. American Mathematical Society. ISBN 978-0821807491. @end itemize @xseealso{ctmcmtta} @end deftypefn @c @node First passage times (DTMC) @subsection First Passage Times The First Passage Time @math{M_{i, j}} is the average number of transitions needed to enter state @math{j} for the first time, starting from state @math{i}. Matrix @math{\bf M} satisfies the property @iftex @tex $$ M_{i, j} = 1 + \sum_{k \neq j} P_{i, k} M_{k, j}$$ @end tex @end iftex @ifnottex @example @group ___ \ M_ij = 1 + > P_ij * M_kj /___ k!=j @end group @end example @end ifnottex To compute @math{{\bf M} = [ M_{i, j}]} a different formulation is used. Let @math{\bf W} be the @math{N \times N} matrix having each row equal to the stationary state occupancy probability vector @math{\bf \pi} for @math{\bf P}; let @math{\bf I} be the @math{N \times N} identity matrix (i.e., the matrix of all ones). Define @math{\bf Z} as follows: @iftex @tex $$ {\bf Z} = \left( {\bf I} - {\bf P} + {\bf W} \right)^{-1} $$ @end tex @end iftex @ifnottex @example @group -1 Z = (I - P + W) @end group @end example @end ifnottex @noindent Then, we have that @iftex @tex $$ M_{i, j} = {Z_{j, j} - Z_{i, j} \over \pi_j} $$ @end tex @end iftex @ifnottex @example @group Z_jj - Z_ij M_ij = ----------- \pi_j @end group @end example @end ifnottex According to the definition above, @math{M_{i,i} = 0}. We arbitrarily set @math{M_{i,i}} to the @emph{mean recurrence time} @math{r_i} for state @math{i}, that is the average number of transitions needed to return to state @math{i} starting from it. @math{r_i} is: @iftex @tex $$ r_i = {1 \over \pi_i} $$ @end tex @end iftex @ifnottex @example @group 1 r_i = ----- \pi_i @end group @end example @end ifnottex @anchor{doc-dtmcfpt} @deftypefn {Function File} {@var{M} =} dtmcfpt (@var{P}) @cindex first passage times @cindex mean recurrence times @cindex discrete time Markov chain @cindex Markov chain, discrete time @cindex DTMC Compute mean first passage times and mean recurrence times for an irreducible discrete-time Markov chain over the state space @math{@{1, @dots{}, N@}}. @strong{INPUTS} @table @code @item @var{P}(i,j) transition probability from state @math{i} to state @math{j}. @var{P} must be an irreducible stochastic matrix, which means that the sum of each row must be 1 (@math{\sum_{j=1}^N P_{i j} = 1}), and the rank of @var{P} must be @math{N}. @end table @strong{OUTPUTS} @table @code @item @var{M}(i,j) For all @math{1 @leq{} i, j @leq{} N}, @math{i \neq j}, @code{@var{M}(i,j)} is the average number of transitions before state @var{j} is entered for the first time, starting from state @var{i}. @code{@var{M}(i,i)} is the @emph{mean recurrence time} of state @math{i}, and represents the average time needed to return to state @var{i}. @end table @strong{REFERENCES} @itemize @item Grinstead, Charles M.; Snell, J. Laurie (July 1997). @cite{Introduction to Probability}, Ch. 11: Markov Chains. American Mathematical Society. ISBN 978-0821807491. @end itemize @xseealso{ctmcfpt} @end deftypefn @c @c @c @node Continuous-Time Markov Chains @section Continuous-Time Markov Chains A stochastic process @math{@{X(t), t @geq{} 0@}} is a continuous-time Markov chain if, for all integers @math{n}, and for any sequence @math{t_0, t_1 , @dots{}, t_n, t_{n+1}} such that @math{t_0 < t_1 < @dots{} < t_n < t_{n+1}}, we have @iftex @tex $$\eqalign{P(X(t_{n+1}) = x_{n+1}\ |\ X(t_n) = x_n, X(t_{n-1}) = x_{n-1}, \ldots, X(t_0) = x_0) \cr &\hskip -8 em = P(X(t_{n+1}) = x_{n+1}\ |\ X(t_n) = x_n)}$$ @end tex @end iftex @ifnottex @math{P(X_{n+1} = x_{n+1} | X_n = x_n, X_{n-1} = x_{n-1}, ..., X_0 = x_0) = P(X_{n+1} = x_{n+1} | X_n = x_n)} @end ifnottex A continuous-time Markov chain is defined according to an @emph{infinitesimal generator matrix} @math{{\bf Q} = [Q_{i,j}]}, where for each @math{i \neq j}, @math{Q_{i, j}} is the transition rate from state @math{i} to state @math{j}. The matrix @math{\bf Q} must satisfy the property that, for all @math{i}, @math{\sum_{j=1}^N Q_{i, j} = 0}. @anchor{doc-ctmcchkQ} @deftypefn {Function File} {[@var{result} @var{err}] =} ctmcchkQ (@var{Q}) @cindex Markov chain, continuous time If @var{Q} is a valid infinitesimal generator matrix, return the size (number of rows or columns) of @var{Q}. If @var{Q} is not an infinitesimal generator matrix, set @var{result} to zero, and @var{err} to an appropriate error string. @end deftypefn Similarly to the DTMC case, a CTMC is @emph{irreducible} if every state is eventually reachable from every other state in finite time. @anchor{doc-ctmcisir} @deftypefn {Function File} {[@var{r} @var{s}] =} ctmcisir (@var{P}) @cindex Markov chain, continuous time @cindex continuous time Markov chain @cindex CTMC @cindex irreducible Markov chain Check if @var{Q} is irreducible, and identify Strongly Connected Components (SCC) in the transition graph of the DTMC with infinitesimal generator matrix @var{Q}. @strong{INPUTS} @table @code @item @var{Q}(i,j) Infinitesimal generator matrix. @var{Q} is a @math{N \times N} square matrix where @code{@var{Q}(i,j)} is the transition rate from state @math{i} to state @math{j}, for @math{1 @leq{} i, j @leq{} N}, @math{i \neq j}. @end table @strong{OUTPUTS} @table @code @item @var{r} 1 if @var{Q} is irreducible, 0 otherwise. @item @var{s}(i) strongly connected component (SCC) that state @math{i} belongs to. SCCs are numbered @math{1, 2, @dots{}}. If the graph is strongly connected, then there is a single SCC and the predicate @code{all(s == 1)} evaluates to true. @end table @end deftypefn @menu * State occupancy probabilities (CTMC):: * Birth-death process (CTMC):: * Expected sojourn times (CTMC):: * Time-averaged expected sojourn times (CTMC):: * Mean time to absorption (CTMC):: * First passage times (CTMC):: @end menu @node State occupancy probabilities (CTMC) @subsection State occupancy probabilities Similarly to the discrete case, we denote with @math{{\bf \pi}(t) = \left[\pi_1(t), @dots{}, \pi_N(t) \right]} the @emph{state occupancy probability vector} at time @math{t}. @math{\pi_i(t)} is the probability that the system is in state @math{i} at time @math{t @geq{} 0}. Given the infinitesimal generator matrix @math{\bf Q} and initial state occupancy probabilities @math{{\bf \pi}(0) = \left[\pi_1(0), @dots{}, \pi_N(0)\right]}, the occupancy probabilities @math{{\bf \pi}(t)} at time @math{t} can be computed as: @iftex @tex $${\bf \pi}(t) = {\bf \pi}(0) \exp( {\bf Q} t )$$ @end tex @end iftex @ifnottex @example @group \pi(t) = \pi(0) exp(Qt) @end group @end example @end ifnottex @noindent where @math{\exp( {\bf Q} t )} is the matrix exponential of @math{{\bf Q} t}. Under certain conditions, there exists a @emph{stationary state occupancy probability} @math{{\bf \pi} = \lim_{t \rightarrow +\infty} {\bf \pi}(t)} that is independent from @math{{\bf \pi}(0)}. @math{\bf \pi} is the solution of the following linear system: @iftex @tex $$ \left\{ \eqalign{ {\bf \pi Q} & = {\bf 0} \cr {\bf \pi 1}^T & = 1 } \right. $$ @end tex @end iftex @ifnottex @example @group / | \pi Q = 0 | \pi 1^T = 1 \ @end group @end example @end ifnottex @anchor{doc-ctmc} @deftypefn {Function File} {@var{p} =} ctmc (@var{Q}) @deftypefnx {Function File} {@var{p} =} ctmc (@var{Q}, @var{t}, @var{p0}) @cindex Markov chain, continuous time @cindex continuous time Markov chain @cindex Markov chain, state occupancy probabilities @cindex stationary probabilities @cindex CTMC Compute stationary or transient state occupancy probabilities for a continuous-time Markov chain. With a single argument, compute the stationary state occupancy probabilities @math{@var{p}(1), @dots{}, @var{p}(N)} for a continuous-time Markov chain with finite state space @math{@{1, @dots{}, N@}} and @math{N \times N} infinitesimal generator matrix @var{Q}. With three arguments, compute the state occupancy probabilities @math{@var{p}(1), @dots{}, @var{p}(N)} that the system is in state @math{i} at time @var{t}, given initial state occupancy probabilities @math{@var{p0}(1), @dots{}, @var{p0}(N)} at time 0. @strong{INPUTS} @table @code @item @var{Q}(i,j) Infinitesimal generator matrix. @var{Q} is a @math{N \times N} square matrix where @code{@var{Q}(i,j)} is the transition rate from state @math{i} to state @math{j}, for @math{1 @leq{} i \neq j @leq{} N}. @var{Q} must satisfy the property that @math{\sum_{j=1}^N Q_{i, j} = 0} @item @var{t} Time at which to compute the transient probability (@math{t @geq{} 0}). If omitted, the function computes the steady state occupancy probability vector. @item @var{p0}(i) probability that the system is in state @math{i} at time 0. @end table @strong{OUTPUTS} @table @code @item @var{p}(i) If this function is invoked with a single argument, @code{@var{p}(i)} is the steady-state probability that the system is in state @math{i}, @math{i = 1, @dots{}, N}. If this function is invoked with three arguments, @code{@var{p}(i)} is the probability that the system is in state @math{i} at time @var{t}, given the initial occupancy probabilities @var{p0}(1), @dots{}, @var{p0}(N). @end table @xseealso{dtmc} @end deftypefn @noindent @strong{EXAMPLE} Consider a two-state CTMC where all transition rates between states are equal to 1. The stationary state occupancy probabilities can be computed as follows: @example @group @verbatim Q = [ -1 1; ... 1 -1 ]; q = ctmc(Q) @end verbatim @result{} q = 0.50000 0.50000 @end group @end example @c @c @c @node Birth-death process (CTMC) @subsection Birth-Death Process @anchor{doc-ctmcbd} @deftypefn {Function File} {@var{Q} =} ctmcbd (@var{b}, @var{d}) @cindex Markov chain, continuous time @cindex continuous time Markov chain @cindex CTMC @cindex birth-death process, CTMC Returns the infinitesimal generator matrix @math{Q} for a continuous birth-death process over the finite state space @math{@{1, @dots{}, N@}}. For each @math{i=1, @dots{}, (N-1)}, @code{@var{b}(i)} is the transition rate from state @math{i} to state @math{(i+1)}, and @code{@var{d}(i)} is the transition rate from state @math{(i+1)} to state @math{i}. Matrix @math{\bf Q} is therefore defined as: @tex $$ \pmatrix{ -\lambda_1 & \lambda_1 & & & & \cr \mu_1 & -(\mu_1 + \lambda_2) & \lambda_2 & & \cr & \mu_2 & -(\mu_2 + \lambda_3) & \lambda_3 & & \cr \cr & & \ddots & \ddots & \ddots & & \cr \cr & & & \mu_{N-2} & -(\mu_{N-2}+\lambda_{N-1}) & \lambda_{N-1} \cr & & & & \mu_{N-1} & -\mu_{N-1} } $$ @end tex @ifnottex @example @group / \ | -b(1) b(1) | | d(1) -(d(1)+b(2)) b(2) | | d(2) -(d(2)+b(3)) b(3) | | | | ... ... ... | | | | d(N-2) -(d(N-2)+b(N-1)) b(N-1) | | d(N-1) -d(N-1) | \ / @end group @end example @end ifnottex @noindent where @math{\lambda_i} and @math{\mu_i} are the birth and death rates, respectively. @xseealso{dtmcbd} @end deftypefn @c @c @c @node Expected sojourn times (CTMC) @subsection Expected Sojourn Times Given a @math{N} state continuous-time Markov Chain with infinitesimal generator matrix @math{\bf Q}, we define the vector @math{{\bf L}(t) = \left[L_1(t), @dots{}, L_N(t)\right]} such that @math{L_i(t)} is the expected sojourn time in state @math{i} during the interval @math{[0,t)}, assuming that the initial occupancy probabilities at time 0 were @math{{\bf \pi}(0)}. @math{{\bf L}(t)} can be expressed as the solution of the following differential equation: @iftex @tex $$ { d{\bf L}(t) \over dt} = {\bf L}(t){\bf Q} + {\bf \pi}(0), \qquad {\bf L}(0) = {\bf 0} $$ @end tex @end iftex @ifnottex @example @group dL --(t) = L(t) Q + pi(0), L(0) = 0 dt @end group @end example @end ifnottex Alternatively, @math{{\bf L}(t)} can also be expressed in integral form as: @iftex @tex $$ {\bf L}(t) = \int_0^t {\bf \pi}(u) du$$ @end tex @end iftex @ifnottex @example @group / t L(t) = | pi(u) du / 0 @end group @end example @end ifnottex @noindent where @math{{\bf \pi}(t) = {\bf \pi}(0) \exp({\bf Q}t)} is the state occupancy probability at time @math{t}; @math{\exp({\bf Q}t)} is the matrix exponential of @math{{\bf Q}t}. If there are absorbing states, we can define the vector of @emph{expected sojourn times until absorption} @math{{\bf L}(\infty)}, where for each transient state @math{i}, @math{L_i(\infty)} is the expected total time spent in state @math{i} until absorption, assuming that the system started with given state occupancy probabilities @math{{\bf \pi}(0)}. Let @math{\tau} be the set of transient (i.e., non absorbing) states; let @math{{\bf Q}_\tau} be the restriction of @math{\bf Q} to the transient sub-states only. Similarly, let @math{{\bf \pi}_\tau(0)} be the restriction of the initial state occupancy probability vector @math{{\bf \pi}(0)} to transient states @math{\tau}. The expected time to absorption @math{{\bf L}_\tau(\infty)} is defined as the solution of the following equation: @iftex @tex $$ {\bf L}_\tau(\infty){\bf Q}_\tau = -{\bf \pi}_\tau(0) $$ @end tex @end iftex @ifnottex @example @group L_T( inf ) Q_T = -pi_T(0) @end group @end example @end ifnottex @anchor{doc-ctmcexps} @deftypefn {Function File} {@var{L} =} ctmcexps (@var{Q}, @var{t}, @var{p} ) @deftypefnx {Function File} {@var{L} =} ctmcexps (@var{Q}, @var{p}) @cindex Markov chain, continuous time @cindex continuous time Markov chain @cindex expected sojourn time, CTMC @cindex CTMC With three arguments, compute the expected times @code{@var{L}(i)} spent in each state @math{i} during the time interval @math{[0,t]}, assuming that the initial occupancy vector is @var{p}. With two arguments, compute the expected time @code{@var{L}(i)} spent in each transient state @math{i} until absorption. @strong{Note:} In its current implementation, this function requires that an absorbing state is reachable from any non-absorbing state of @math{Q}. @strong{INPUTS} @table @code @item @var{Q}(i,j) @math{N \times N} infinitesimal generator matrix. @code{@var{Q}(i,j)} is the transition rate from state @math{i} to state @math{j}, @math{1 @leq{} i, j @leq{} N}, @math{i \neq j}. The matrix @var{Q} must also satisfy the condition @math{\sum_{j=1}^N Q_{i,j} = 0} for every @math{i=1, @dots{}, N}. @item @var{t} If given, compute the expected sojourn times in @math{[0,t]} @item @var{p}(i) Initial occupancy probability vector; @code{@var{p}(i)} is the probability the system is in state @math{i} at time 0, @math{i = 1, @dots{}, N} @end table @strong{OUTPUTS} @table @code @item @var{L}(i) If this function is called with three arguments, @code{@var{L}(i)} is the expected time spent in state @math{i} during the interval @math{[0,t]}. If this function is called with two arguments @code{@var{L}(i)} is the expected time spent in transient state @math{i} until absorption; if state @math{i} is absorbing, @code{@var{L}(i)} is zero. @end table @xseealso{dtmcexps} @end deftypefn @noindent @strong{EXAMPLE} Let us consider a 4-states pure birth continuous process where the transition rate from state @math{i} to state @math{(i+1)} is @math{\lambda_i = i \lambda} (@math{i=1, 2, 3}), with @math{\lambda = 0.5}. The following code computes the expected sojourn time for each state @math{i}, given initial occupancy probabilities @math{{\bf \pi}_0=[1, 0, 0, 0]}. @example @group @verbatim lambda = 0.5; N = 4; b = lambda*[1:N-1]; d = zeros(size(b)); Q = ctmcbd(b,d); t = linspace(0,10,100); p0 = zeros(1,N); p0(1)=1; L = zeros(length(t),N); for i=1:length(t) L(i,:) = ctmcexps(Q,t(i),p0); endfor plot( t, L(:,1), ";State 1;", "linewidth", 2, ... t, L(:,2), ";State 2;", "linewidth", 2, ... t, L(:,3), ";State 3;", "linewidth", 2, ... t, L(:,4), ";State 4;", "linewidth", 2 ); legend("location","northwest"); legend("boxoff"); xlabel("Time"); ylabel("Expected sojourn time"); @end verbatim @end group @end example @c @c @c @node Time-averaged expected sojourn times (CTMC) @subsection Time-Averaged Expected Sojourn Times @anchor{doc-ctmctaexps} @deftypefn {Function File} {@var{M} =} ctmctaexps (@var{Q}, @var{t}, @var{p0}) @deftypefnx {Function File} {@var{M} =} ctmctaexps (@var{Q}, @var{p0}) @cindex Markov chain, continuous time @cindex time-alveraged sojourn time, CTMC @cindex continuous time Markov chain @cindex CTMC Compute the @emph{time-averaged sojourn time} @code{@var{M}(i)}, defined as the fraction of the time interval @math{[0,t]} (or until absorption) spent in state @math{i}, assuming that the state occupancy probabilities at time 0 are @var{p}. @strong{INPUTS} @table @code @item @var{Q}(i,j) Infinitesimal generator matrix. @code{@var{Q}(i,j)} is the transition rate from state @math{i} to state @math{j}, @math{1 @leq{} i,j @leq{} N}, @math{i \neq j}. The matrix @var{Q} must also satisfy the condition @math{\sum_{j=1}^N Q_{i,j} = 0} @item @var{t} Time. If omitted, the results are computed until absorption. @item @var{p0}(i) initial state occupancy probabilities. @code{@var{p0}(i)} is the probability that the system is in state @math{i} at time 0, @math{i = 1, @dots{}, N} @end table @strong{OUTPUTS} @table @code @item @var{M}(i) When called with three arguments, @code{@var{M}(i)} is the expected fraction of the interval @math{[0,t]} spent in state @math{i} assuming that the state occupancy probability at time zero is @var{p}. When called with two arguments, @code{@var{M}(i)} is the expected fraction of time until absorption spent in state @math{i}; in this case the mean time to absorption is @code{sum(@var{M})}. @end table @xseealso{ctmcexps} @end deftypefn @noindent @strong{EXAMPLE} @example @group @verbatim lambda = 0.5; N = 4; birth = lambda*linspace(1,N-1,N-1); death = zeros(1,N-1); Q = diag(birth,1)+diag(death,-1); Q -= diag(sum(Q,2)); t = linspace(1e-5,30,100); p = zeros(1,N); p(1)=1; M = zeros(length(t),N); for i=1:length(t) M(i,:) = ctmctaexps(Q,t(i),p); endfor clf; plot(t, M(:,1), ";State 1;", "linewidth", 2, ... t, M(:,2), ";State 2;", "linewidth", 2, ... t, M(:,3), ";State 3;", "linewidth", 2, ... t, M(:,4), ";State 4 (absorbing);", "linewidth", 2 ); legend("location","east"); legend("boxoff"); xlabel("Time"); ylabel("Time-averaged Expected sojourn time"); @end verbatim @end group @end example @c @c @c @node Mean time to absorption (CTMC) @subsection Mean Time to Absorption @anchor{doc-ctmcmtta} @deftypefn {Function File} {@var{t} =} ctmcmtta (@var{Q}, @var{p}) @cindex Markov chain, continuous time @cindex continuous time Markov chain @cindex CTMC @cindex mean time to absorption, CTMC Compute the Mean-Time to Absorption (MTTA) of the CTMC described by the infinitesimal generator matrix @var{Q}, starting from initial occupancy probabilities @var{p}. If there are no absorbing states, this function fails with an error. @strong{INPUTS} @table @code @item @var{Q}(i,j) @math{N \times N} infinitesimal generator matrix. @code{@var{Q}(i,j)} is the transition rate from state @math{i} to state @math{j}, @math{i \neq j}. The matrix @var{Q} must satisfy the condition @math{\sum_{j=1}^N Q_{i,j} = 0} @item @var{p}(i) probability that the system is in state @math{i} at time 0, for each @math{i=1, @dots{}, N} @end table @strong{OUTPUTS} @table @code @item @var{t} Mean time to absorption of the process represented by matrix @var{Q}. If there are no absorbing states, this function fails. @end table @strong{REFERENCES} @itemize @item G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998. @end itemize @xseealso{ctmcexps} @end deftypefn @noindent @strong{EXAMPLE} Let us consider a simple model of redundant disk array. We assume that the array is made of 5 independent disks and can tolerate up to 2 disk failures without losing data. If three or more disks break, the array is dead and unrecoverable. We want to estimate the Mean-Time-To-Failure (MTTF) of the disk array. We model this system as a 4 states continuous Markov chain with state space @math{@{ 2, 3, 4, 5 @}}. In state @math{i} there are exactly @math{i} active (i.e., non failed) disks; state @math{2} is absorbing. Let @math{\mu} be the failure rate of a single disk. The system starts in state @math{5} (all disks are operational). We use a pure death process, where the death rate from state @math{i} to state @math{(i-1)} is @math{\mu i}, for @math{i = 3, 4, 5}). The MTTF of the disk array is the MTTA of the Markov Chain, and can be computed as follows: @example @group @verbatim mu = 0.01; death = [ 3 4 5 ] * mu; birth = 0*death; Q = ctmcbd(birth,death); t = ctmcmtta(Q,[0 0 0 1]) @end verbatim @result{} t = 78.333 @end group @end example @c @c @c @node First passage times (CTMC) @subsection First Passage Times @anchor{doc-ctmcfpt} @deftypefn {Function File} {@var{M} =} ctmcfpt (@var{Q}) @deftypefnx {Function File} {@var{m} =} ctmcfpt (@var{Q}, @var{i}, @var{j}) @cindex first passage times, CTMC @cindex CTMC @cindex continuous time Markov chain @cindex Markov chain, continuous time Compute mean first passage times for an irreducible continuous-time Markov chain. @strong{INPUTS} @table @code @item @var{Q}(i,j) Infinitesimal generator matrix. @var{Q} is a @math{N \times N} square matrix where @code{@var{Q}(i,j)} is the transition rate from state @math{i} to state @math{j}, for @math{1 @leq{} i, j @leq{} N}, @math{i \neq j}. Transition rates must be nonnegative, and @math{\sum_{j=1}^N Q_{i,j} = 0} @item @var{i} Initial state. @item @var{j} Destination state. @end table @strong{OUTPUTS} @table @code @item @var{M}(i,j) average time before state @var{j} is visited for the first time, starting from state @var{i}. We let @code{@var{M}(i,i) = 0}. @item m @var{m} is the average time before state @var{j} is visited for the first time, starting from state @var{i}. @end table @xseealso{ctmcmtta} @end deftypefn queueing/doc/qn_closed_single.pdf0000664000175000017500000001347714620415627017055 0ustar morenomoreno%PDF-1.5 %쏢 %%Invocation: gs -q -dSAFER -dNOPAUSE -dBATCH -dCompatibilityLevel=1.5 -sDEVICE=pdfwrite -sOutputFile=? -dPDFSETTINGS#/prepress -dMaxSubsetPct=100 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoRotatePages#/None - 5 0 obj <> stream x}UnT1 +!rP6, >`Ejqr$Fz''8jSw7oW}}Iap l6;u`R"oc_ZA,0R"CC\"vZ|tաEhKo)~Ko$՝wx'a2IY2WCYhwCHR-°ѱ dt=k@p>q)}4Kvc$Y loY =g82X,J kWI),s*SJ R(gؑUJ y#9l2ɖ'F׷ ȼs"|"TƁ3+&L\4 ٫A3yTϪbT۔T+!Z0qh`MV%g8YP.:;)q4aaMr=FN!'=xS1FLpM鿜H$y5:(lцrP#\3RJ K'~e8sG1EaQMlTqyq'&(-r&|#m*/}5~ 08L2@yL "Ƶm#3Ӫ|ԏ,s\?m|e5|TUT4\ebcoendstream endobj 6 0 obj 763 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 10 0 obj <> endobj 11 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> endobj 12 0 obj <>stream xT{PS$Z6*4BHvZfQa}"Au !$A@9Id <~vuVquY ٮ;춖N7sL/kgڿ97;# A{TB^R+2>$u"`$vaw~/+2W| ]#drSSZy*]!Wj(Ne|?RgE XK"K=. pïb5x"}F"L,'V'3›XA -p MC BpTZvka0 "h 2ZXk&ˏ7T[QǬb@ $瓝a{[8˜qCQK{`K@5aIojq l~կA ;~/s_ےMUZڲhnFLz*GoupB:NHhiiXR03N.Z17l꡹.˶ wuӶ0|5rNo `TU5|qUubG[C uq ?DPK~}@BV)22Rm]==gvG;-yQ8>71LҘ 7LXtY6{U= C@7Y/IYqVYyMӐ2nϥ?Z$!9:C\Awt kp`ЧJcp!Ă>`ZfI9Q(Udk4FϮG>h7%77=y}.>-e-ۚ!ޅ6PeU&J*tim#WG&]|-Gۜ]E߿8|b]L.5IP3Jg{ocX$}rY+V/+t23$P8ru{|ɮBC-s ~SK -{!97fe endstream endobj 13 0 obj <>stream 2024-05-13T15:54:31+02:00 2024-05-13T15:54:31+02:00 fig2dev Version 3.2.7a qn_closed_single.fig endstream endobj 2 0 obj <>endobj xref 0 14 0000000000 65535 f 0000001290 00000 n 0000005333 00000 n 0000001231 00000 n 0000001080 00000 n 0000000228 00000 n 0000001061 00000 n 0000001355 00000 n 0000001456 00000 n 0000001781 00000 n 0000001396 00000 n 0000001426 00000 n 0000002061 00000 n 0000003896 00000 n trailer << /Size 14 /Root 1 0 R /Info 2 0 R /ID [] >> startxref 5518 %%EOF queueing/doc/queueingnetworks.texi0000664000175000017500000035633514620415614017363 0ustar morenomoreno@c This file has been automatically generated from queueingnetworks.txi @c by proc.m. Do not edit this file, all changes will be lost @c -*- texinfo -*- @c Copyright (C) 2008, 2009, 2010, 2011, 2012, 2014, 2016, 2018 Moreno Marzolla @c @c This file is part of the queueing package. @c @c The queueing package is free software; you can redistribute it @c and/or modify it under the terms of the GNU General Public License @c as published by the Free Software Foundation; either version 3 of @c the License, or (at your option) any later version. @c @c The queueing package is distributed in the hope that it will be @c useful, but WITHOUT ANY WARRANTY; without even the implied warranty @c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @c GNU General Public License for more details. @c @c You should have received a copy of the GNU General Public License @c along with the queueing package; see the file COPYING. If not, see @c . @node Queueing Networks @chapter Queueing Networks @menu * Introduction to QNs:: A brief introduction to Queueing Networks * Single Class Models:: Queueing models with a single job class * Multiple Class Models:: Queueing models with multiple job classes * Generic Algorithms:: High-level functions for QN analysis * Bounds Analysis:: Computation of asymptotic performance bounds * QN Analysis Examples:: Queueing Networks analysis examples @end menu @cindex queueing networks @c @c INTRODUCTION @c @node Introduction to QNs @section Introduction to QNs Queueing Networks (QN) are a simple modeling notation that can be used to analyze many kinds of systems. In its simplest form, a QN is made of @math{K} service centers; center @math{k} has a queue connected to @math{m_k} (usually identical) servers. Arriving customers (requests) join the queue if there is at least one slot available. Requests are served according to a (de)queueing policy (e.g., FIFO). After service completes, requests leave the server and can join another queue or exit from the system. @cindex delay center @cindex infinite server Service centers where @math{m_k = \infty} are called @emph{delay centers} or @emph{infinite servers}. In this kind of centers, there is always one available server, so that queueing never occurs. Requests join the queue according to a @emph{queueing policy}, such as: @cindex First-Come-First-Served @cindex FCFS @cindex Last-Come-First-Served Preemptive Resume @cindex LCFS-PR @cindex Processor Sharing @cindex PS @cindex Infinite Server @cindex IS @table @strong @item FCFS First-Come-First-Served @item LCFS-PR Last-Come-First-Served, Preemptive Resume @item PS Processor Sharing @item IS Infinite Server (@math{m_k = \infty}). @end table Queueing networks can be @emph{open} or @emph{closed}. In open networks there is an infinite population of requests; new customers are generated outside the system, and eventually leave the network. In closed networks there is a fixed population of request that never leave the system. @cindex single class queueing network @cindex multiple class queueing network @cindex queueing network, single class @cindex queueing network, multiple class Queueing models can have a single request class (@emph{single class models}), meaning that all requests behave in the same way (e.g., they spend the same average time on each particular server). In @emph{multiple class models} there are multiple request classes, each with its own parameters (e.g., with different service times or different routing probabilities). Furthermore, in multiclass models there can be open and closed chains of requests at the same time. @cindex product-form queueing network @cindex queueing network, product-form A particular class of QN models, @emph{product-form} networks, is of particular interest. Product-form networks fulfill the following assumptions: @itemize @item The network can consist of open and closed job classes. @item The following queueing disciplines are allowed: FCFS, PS, LCFS-PR and IS. @item Service times for FCFS nodes must be exponentially distributed and class-independent. Service centers at PS, LCFS-PR and IS nodes can have any kind of service time distribution with a rational Laplace transform. Furthermore, for PS, LCFS-PR and IS nodes, different classes of customers can have different service times. @item The service rate of an FCFS node is only allowed to depend on the number of jobs at this node; in a PS, LCFS-PR and IS node the service rate for a particular job class can also depend on the number of jobs of that class at the node. @item In open networks two kinds of arrival processes are allowed: i) the arrival process is Poisson, with arrival rate @math{\lambda} that can depend on the number of jobs in the network. ii) the arrival process consists of @math{C} independent Poisson arrival streams where the @math{C} job sources are assigned to the @math{C} chains; the arrival rate can be load dependent. @end itemize Product-form networks are attractive because steady-state performance measures can be efficiently computed. @c @c Single Class Models @c @node Single Class Models @section Single Class Models @cindex single class queueing network @cindex queueing network, single class In single class models, all requests are indistinguishable and belong to the same class. This means that every request has the same average service time, and all requests move through the system with the same routing probabilities. @noindent @strong{Model Inputs} @cindex external arrival rate @cindex service time @cindex routing probability matrix @cindex average number of visits @table @asis @item @math{{@lambda}_k} (Open models only) External arrival rate to service center @math{k}. @item @math{@lambda} (Open models only) Overall external arrival rate to the system as a whole: @math{\lambda = \sum_k \lambda_k}. @item @math{N} (Closed models only) Total number of requests in the system. @item @math{S_k} Mean service time at center @math{k}. @math{S_k} is the average time elapsed from service start to service completion at center @math{k}. @item @math{P_{i, j}} Routing probability matrix. @math{{\bf P} = [P_{i, j}]} is a @math{K \times K} matrix where @math{P_{i, j}} is the probability that a request completing service at center @math{i} is routed to center @math{j}. The probability that a request leaves the system after being served at center @math{i} is @math{\left(1-\sum_{j=1}^K P_{i, j}\right)}. @item @math{V_k} Mean number of visits to center @math{k} (also called @emph{visit ratio} or @emph{relative arrival rate}). @end table @noindent @strong{Model Outputs} @cindex utilization @cindex response time @cindex average number of customers @cindex throughput @cindex system response time @cindex system throughput @table @math @item U_k Utilization of service center @math{k}. The utilization is defined as the fraction of time in which the resource is busy (i.e., the server is processing requests). If center @math{k} is a single-server or multiserver node, then @math{0 @leq{} U_k @leq{} 1}. If center @math{k} is an infinite server node (delay center), then @math{U_k} denotes the @emph{traffic intensity} and is defined as @math{U_k = X_k S_k}; in this case the utilization may be greater than one. @item R_k Average response time of service center @math{k}, defined as the mean time between the arrival of a request in the queue and service completion of the same request. @item Q_k Average number of requests in center @math{k}; this includes both the requests in the queue and those being served. @item X_k Throughput of service center @math{k}. The throughput is the rate of job completions, i.e., the average number of jobs completed over a given time interval. @end table @noindent Given the output parameters above, additional performance measures can be computed: @table @math @item X System throughput, @math{X = X_k / V_k} for any @math{k} for which @math{V_k \neq 0} @item R System response time, @math{R = \sum_{k=1}^K R_k V_k} @item Q Average number of requests in the system, @math{Q = \sum_{k=1}^K Q_k}; for closed systems, this can be written as @math{Q = N-XZ}; @end table For open, single class models, the scalar @math{\lambda} denotes the external arrival rate of requests to the system. The average number of visits @math{V_j} satisfy the following equation: @iftex @tex $$ V_j = P_{0, j} + \sum_{i=1}^K V_i P_{i, j} \quad j=1, \ldots, K $$ @end tex @end iftex @ifnottex @example @group K ___ \ V_j = P_(0, j) + > V_i P_(i, j) j=1,...,K /___ i=1 @end group @end example @end ifnottex @noindent where @math{P_{0, j}} is the probability that an external request goes to center @math{j}. If we denote with @math{\lambda_j} the external arrival rate to center @math{j}, and @math{\lambda = \sum_j \lambda_j} the overall external arrival rate, then @math{P_{0, j} = \lambda_j / \lambda}. For closed models, the visit ratios satisfy the following equation: @iftex @tex $$\left\{\eqalign{V_j & = \sum_{i=1}^K V_i P_{i, j} \quad j=1, \ldots, K \cr V_r & = 1 \quad \hbox{for a selected reference station $r$}}\right. $$ @end tex @end iftex @ifnottex @example / | K | ___ | \ | V_j = > V_i P_(i, j) j=1,...,K | /___ | i=1 | | V_r = 1 for a selected reference station r \ @end example @end ifnottex Note that the set of traffic equations @math{V_j = \sum_{i=1}^K V_i P_{i, j}} alone can only be solved up to a multiplicative constant; to get a unique solution we impose an additional constraint @math{V_r = 1} for some @math{1 @leq{} r @leq{} K}. This constraint is equivalent to defining station @math{r} as the @emph{reference station}; the default is @math{r=1}, @pxref{doc-qncsvisits}. A job that returns to the reference station is assumed to have completed its activity cycle. The network throughput is set to the throughput of the reference station. @anchor{doc-qncsvisits} @deftypefn {Function File} {@var{V} =} qncsvisits (@var{P}) @deftypefnx {Function File} {@var{V} =} qncsvisits (@var{P}, @var{r}) Compute the mean number of visits to the service centers of a single class, closed network with @math{K} service centers. @strong{INPUTS} @table @code @item @var{P}(i,j) probability that a request which completed service at center @math{i} is routed to center @math{j} (@math{K \times K} matrix). For closed networks it must hold that @code{sum(@var{P},2)==1}. The routing graph must be strongly connected, meaning that each node must be reachable from every other node. @item @var{r} Index of the reference station, @math{r \in @{1, @dots{}, K@}}; Default @code{@var{r}=1}. The traffic equations are solved by imposing the condition @code{@var{V}(r) = 1}. A request returning to the reference station completes its activity cycle. @end table @strong{OUTPUTS} @table @code @item @var{V}(k) average number of visits to service center @math{k}, assuming @math{r} as the reference station. @end table @end deftypefn @anchor{doc-qnosvisits} @deftypefn {Function File} {@var{V} =} qnosvisits (@var{P}, @var{lambda}) Compute the average number of visits to the service centers of a single class open Queueing Network with @math{K} service centers. @strong{INPUTS} @table @code @item @var{P}(i,j) is the probability that a request which completed service at center @math{i} is routed to center @math{j} (@math{K \times K} matrix). @item @var{lambda}(k) external arrival rate to center @math{k}. @end table @strong{OUTPUTS} @table @code @item @var{V}(k) average number of visits to server @math{k}. @end table @end deftypefn @c @c @c @noindent @strong{EXAMPLE} @float Figure,fig:qn_closed_single @center @image{qn_closed_single,3in} @caption{Closed network with a single class of requests} @end float @ref{fig:qn_closed_single} shows a closed queueing network with a single class of requests. The network has three service centers, labeled @emph{CPU}, @emph{Disk1} and @emph{Disk2}, and is known as a @emph{central server} model of a computer system. Requests spend some time at the CPU, which is represented by a PS (Processor Sharing) node. After that, requests are routed to Disk1 with probability @math{0.3}, and to Disk2 with probability @math{0.7}. Both Disk1 and Disk2 are FCFS nodes. If we label the servers as CPU=1, Disk1=2, Disk2=3, we can define the routing matrix as follows: @iftex @tex $$ {\bf P} = \pmatrix{ 0 & 0.3 & 0.7 \cr 1 & 0 & 0 \cr 1 & 0 & 0 } $$ @end tex @end iftex @ifnottex @example / 0 0.3 0.7 \ P = | 1 0 0 | \ 1 0 0 / @end example @end ifnottex The visit ratios @math{V}, using station 1 as the reference station, can be computed with: @example @verbatim P = [0 0.3 0.7; ... 1 0 0 ; ... 1 0 0 ]; V = qncsvisits(P) @end verbatim @result{} V = 1.00000 0.30000 0.70000 @end example @noindent @strong{EXAMPLE} @float Figure,fig:qn_open_single @center @image{qn_open_single,3in} @caption{Open Queueing Network with a single class of requests} @end float @ref{fig:qn_open_single} shows a open QN with a single class of requests. The network has the same structure as the one in @ref{fig:qn_closed_single}, with the difference that here we have a stream of jobs arriving from outside the system, at a rate @math{\lambda}. After service completion at the CPU, a job can leave the system with probability @math{0.2}, or be transferred to other nodes with the probabilities shown in the figure. The routing matrix is @iftex @tex $$ {\bf P} = \pmatrix{ 0 & 0.3 & 0.5 \cr 1 & 0 & 0 \cr 1 & 0 & 0 } $$ @end tex @end iftex @ifnottex @example / 0 0.3 0.5 \ P = | 1 0 0 | \ 1 0 0 / @end example @end ifnottex If we let @math{\lambda = 1.2}, we can compute the visit ratios @math{V} as follows: @example @verbatim p = 0.3; lambda = 1.2 P = [0 0.3 0.5; 1 0 0; 1 0 0]; V = qnosvisits(P,[1.2 0 0]) @end verbatim @result{} V = 5.0000 1.5000 2.5000 @end example Function @command{qnosvisits} expects a vector with @math{K} elements as a second parameter, for open networks only. The vector contains the arrival rates at each individual node; since in our example external arrivals exist only for node @math{S_1} with rate @math{\lambda = 1.2}, the second parameter is @code{[1.2, 0, 0]}. @c @c Open Networks @c @subsection Open Networks Jackson networks satisfy the following conditions: @itemize @item There is only one job class in the network; the total number of jobs in the system is unbounded. @item There are @math{K} service centers in the network. Each service center may have Poisson arrivals from outside the system. A job can leave the system from any node. @item Arrival rates as well as routing probabilities are independent from the number of nodes in the network. @item External arrivals and service times at the service centers are exponentially distributed, and in general can be load-dependent. @item Service discipline at each node is FCFS @end itemize We define the @emph{joint probability vector} @math{\pi(n_1, @dots{}, n_K)} as the steady-state probability that there are @math{n_k} requests at service center @math{k}, for all @math{k=1, @dots{}, N}. Jackson networks have the property that the joint probability is the product of the marginal probabilities @math{\pi_k}: @iftex @tex $$ \pi(n_1, \ldots, n_K) = \prod_{k=1}^K \pi_k(n_k) $$ @end tex @end iftex @ifnottex @example @var{joint_prob} = prod( @var{pi} ) @end example @end ifnottex @noindent where @math{\pi_k(n_k)} is the steady-state probability that there are @math{n_k} requests at service center @math{k}. @anchor{doc-qnos} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnos (@var{lambda}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnos (@var{lambda}, @var{S}, @var{V}, @var{m}) @cindex open network, single class @cindex BCMP network Analyze open, single class BCMP queueing networks with @math{K} service centers. This function works for a subset of BCMP single-class open networks satisfying the following properties: @itemize @item The allowed service disciplines at network nodes are: FCFS, PS, LCFS-PR, IS (infinite server); @item Service times are exponentially distributed and load-independent; @item Center @math{k} can consist of @code{@var{m}(k) @geq{} 1} identical servers. @item Routing is load-independent @end itemize @strong{INPUTS} @table @code @item @var{lambda} Overall external arrival rate (@code{@var{lambda}>0}). @item @var{S}(k) average service time at center @math{k} (@code{@var{S}(k)>0}). @item @var{V}(k) average number of visits to center @math{k} (@code{@var{V}(k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{i}. If @code{@var{m}(k) < 1}, enter @math{k} is a delay center (IS); otherwise it is a regular queueing center with @code{@var{m}(k)} servers. Default is @code{@var{m}(k) = 1} for all @math{k}. @end table @strong{OUTPUTS} @table @code @item @var{U}(k) If @math{k} is a queueing center, @code{@var{U}(k)} is the utilization of center @math{k}. If @math{k} is an IS node, then @code{@var{U}(k)} is the @emph{traffic intensity} defined as @code{@var{X}(k)*@var{S}(k)}. @item @var{R}(k) center @math{k} average response time. @item @var{Q}(k) average number of requests at center @math{k}. @item @var{X}(k) center @math{k} throughput. @end table @strong{REFERENCES} @itemize @item G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998 @end itemize @xseealso{qnopen,qnclosed,qnosvisits} @end deftypefn From the results computed by this function, it is possible to derive other quantities of interest as follows: @itemize @item @strong{System Response Time}: The overall system response time can be computed as @iftex @tex $R_s = \sum_{k=1}^K V_k R_k$ @end tex @end iftex @ifnottex @code{R_s = dot(V,R);} @end ifnottex @item @strong{Average number of requests}: The average number of requests in the system can be computed as: @iftex @tex $$Q_{avg} = \sum_{k=1}^K Q_k$$ @end tex @end iftex @ifnottex @code{Q_avg = sum(Q)} @end ifnottex @end itemize @noindent @strong{EXAMPLE} @example @verbatim lambda = 3; V = [16 7 8]; S = [0.01 0.02 0.03]; [U R Q X] = qnos( lambda, S, V ); R_s = dot(R,V) # System response time N = sum(Q) # Average number in system @end verbatim @print{} R_s = 1.4062 @print{} N = 4.2186 @end example @c @c Closed Networks @c @subsection Closed Networks @anchor{doc-qncsmva} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsmva (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsmva (@var{N}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsmva (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) @cindex Mean Value Analysys (MVA) @cindex closed network, single class @cindex normalization constant Analyze closed, single class queueing networks using the exact Mean Value Analysis (MVA) algorithm. The following queueing disciplines are supported: FCFS, LCFS-PR, PS and IS (Infinite Server). This function supports fixed-rate service centers or multiple server nodes. For general load-dependent service centers, use the function @code{qncsmvald} instead. Additionally, the normalization constant @math{G(n)}, @math{n=0, @dots{}, N} is computed; @math{G(n)} can be used in conjunction with the BCMP theorem to compute steady-state probabilities. @strong{INPUTS} @table @code @item @var{N} Population size (number of requests in the system, @code{@var{N} @geq{} 0}). If @code{@var{N} == 0}, this function returns @code{@var{U} = @var{R} = @var{Q} = @var{X} = 0} @item @var{S}(k) mean service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). @item @var{V}(k) average number of visits to service center @math{k} (@code{@var{V}(k) @geq{} 0}). @item @var{Z} External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. @item @var{m}(k) number of servers at center @math{k} (if @var{m} is a scalar, all centers have that number of servers). If @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); otherwise it is a regular queueing center (FCFS, LCFS-PR or PS) with @code{@var{m}(k)} servers. Default is @code{@var{m}(k) = 1} for all @math{k} (each service center has a single server). @end table @strong{OUTPUTS} @table @code @item @var{U}(k) If @math{k} is a FCFS, LCFS-PR or PS node (@code{@var{m}(k) @geq{} 1}), then @code{@var{U}(k)} is the utilization of center @math{k}, @math{0 @leq{} U(k) @leq{} 1}. If @math{k} is an IS node (@code{@var{m}(k) < 1}), then @code{@var{U}(k)} is the @emph{traffic intensity} defined as @code{@var{X}(k)*@var{S}(k)}. In this case the value of @code{@var{U}(k)} may be greater than one. @item @var{R}(k) center @math{k} response time. The @emph{Residence Time} at center @math{k} is @code{@var{R}(k) * @var{V}(k)}. The system response time @var{Rsys} can be computed either as @code{@var{Rsys} = @var{N}/@var{Xsys} - Z} or as @code{@var{Rsys} = dot(@var{R},@var{V})} @item @var{Q}(k) average number of requests at center @math{k}. The number of requests in the system can be computed either as @code{sum(@var{Q})}, or using the formula @code{@var{N}-@var{Xsys}*@var{Z}}. @item @var{X}(k) center @math{K} throughput. The system throughput @var{Xsys} can be computed as @code{@var{Xsys} = @var{X}(1) / @var{V}(1)} @item @var{G}(n) Normalization constants. @code{@var{G}(n+1)} contains the value of the normalization constant @math{G(n)}, @math{n=0, @dots{}, N} as array indexes in Octave start from 1. @math{G(n)} can be used in conjunction with the BCMP theorem to compute steady-state probabilities. @end table @strong{NOTES} In presence of load-dependent servers (i.e., if @code{@var{m}(k)>1} for some @math{k}), the MVA algorithm is known to be numerically unstable. Generally, this issue manifests itself as negative values for the response times or utilizations. This is not a problem of the @code{queueing} toolbox, but of the MVA algorithm, and has currently no known solution. This function prints a warning if numerical problems are detected; the warning can be disabled with the command @code{warning("off", "qn:numerical-instability")}. @strong{REFERENCES} @itemize @item M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, April 1980, pp. 313--322. @uref{http://doi.acm.org/10.1145/322186.322195, 10.1145/322186.322195} @end itemize This implementation is described in R. Jain , @cite{The Art of Computer Systems Performance Analysis}, Wiley, 1991, p. 577. Multi-server nodes are treated according to G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998, Section 8.2.1, "Single Class Queueing Networks". @xseealso{qncsmvald,qncscmva} @end deftypefn @noindent @strong{EXAMPLE} @example @verbatim S = [ 0.125 0.3 0.2 ]; V = [ 16 10 5 ]; N = 20; m = ones(1,3); Z = 4; [U R Q X] = qncsmva(N,S,V,m,Z); X_s = X(1)/V(1); # System throughput R_s = dot(R,V); # System response time printf("\t Util Qlen RespT Tput\n"); printf("\t-------- -------- -------- --------\n"); for k=1:length(S) printf("Dev%d\t%8.4f %8.4f %8.4f %8.4f\n", k, U(k), Q(k), R(k), X(k) ); endfor printf("\nSystem\t %8.4f %8.4f %8.4f\n\n", N-X_s*Z, R_s, X_s ); @end verbatim @end example @c @c MVA for single class, closed networks with load dependent servers @c @anchor{doc-qncsmvald} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvald (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvald (@var{N}, @var{S}, @var{V}, @var{Z}) @cindex Mean Value Analysys (MVA) @cindex MVA @cindex closed network, single class @cindex load-dependent service center Mean Value Analysis algorithm for closed, single class queueing networks with @math{K} service centers and load-dependent service times. This function supports FCFS, LCFS-PR, PS and IS nodes. For networks with only fixed-rate centers and multiple-server nodes, the function @code{qncsmva} is more efficient. @strong{INPUTS} @table @code @item @var{N} Population size (number of requests in the system, @code{@var{N} @geq{} 0}). If @code{@var{N} == 0}, this function returns @code{@var{U} = @var{R} = @var{Q} = @var{X} = 0} @item @var{S}(k,n) mean service time at center @math{k} where there are @math{n} requests, @math{1 @leq{} n @leq{} N}. @code{@var{S}(k,n)} @math{= 1 / \mu_{k}(n)}, where @math{\mu_{k}(n)} is the service rate of center @math{k} when there are @math{n} requests. @item @var{V}(k) average number of visits to service center @math{k} (@code{@var{V}(k) @geq{} 0}). @item @var{Z} external delay ("think time", @code{@var{Z} @geq{} 0}); default 0. @end table @strong{OUTPUTS} @table @code @item @var{U}(k) utilization of service center @math{k}. The utilization is defined as the probability that service center @math{k} is not empty, that is, @math{U_k = 1-\pi_k(0)} where @math{\pi_k(0)} is the steady-state probability that there are 0 jobs at service center @math{k}. @item @var{R}(k) response time on service center @math{k}. @item @var{Q}(k) average number of requests in service center @math{k}. @item @var{X}(k) throughput of service center @math{k}. @end table @strong{NOTES} In presence of load-dependent servers, the MVA algorithm is known to be numerically unstable. Generally this problem manifests itself as negative response times or utilization. @strong{REFERENCES} @itemize @item M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, April 1980, pp. 313--322. @uref{http://doi.acm.org/10.1145/322186.322195, 10.1145/322186.322195} @end itemize This implementation is described in G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998, Section 8.2.4.1, ``Networks with Load-Dependent Service: Closed Networks''. @xseealso{qncsmva} @end deftypefn @c @c CMVA for single class, closed networks with a single load dependent servers @c @anchor{doc-qncscmva} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncscmva (@var{N}, @var{S}, @var{Sld}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncscmva (@var{N}, @var{S}, @var{Sld}, @var{V}, @var{Z}) @cindex conditional MVA (CMVA) @cindex Mean Value Analysis, conditional (CMVA) @cindex closed network, single class @cindex CMVA Conditional MVA (CMVA) algorithm, a numerically stable variant of MVA. This function supports a network of @math{M @geq{} 1} service centers and a single delay center. Servers @math{1, @dots{}, (M-1)} are load-independent; server @math{M} is load-dependent. @strong{INPUTS} @table @code @item @var{N} Number of requests in the system, @code{@var{N} @geq{} 0}. If @code{@var{N} == 0}, this function returns @code{@var{U} = @var{R} = @var{Q} = @var{X} = 0} @item @var{S}(k) mean service time on server @math{k = 1, @dots{}, (M-1)} (@code{@var{S}(k) > 0}). If there are no fixed-rate servers, then @code{S = []} @item @var{Sld}(n) inverse service rate at server @math{M} (the load-dependent server) when there are @math{n} requests, @math{n=1, @dots{}, N}. @code{@var{Sld}(n) = } @math{1 / \mu(n)}. @item @var{V}(k) average number of visits to service center @math{k=1, @dots{}, M}, where @code{@var{V}(k) @geq{} 0}. @code{@var{V}(1:M-1)} are the visit rates to the fixed rate servers; @code{@var{V}(M)} is the visit rate to the load dependent server. @item @var{Z} External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. @end table @strong{OUTPUTS} @table @code @item @var{U}(k) center @math{k} utilization (@math{k=1, @dots{}, M}) @item @var{R}(k) response time of center @math{k} (@math{k=1, @dots{}, M}). The system response time @var{Rsys} can be computed as @code{@var{Rsys} = @var{N}/@var{Xsys} - Z} @item @var{Q}(k) average number of requests at center @math{k} (@math{k=1, @dots{}, M}). @item @var{X}(k) center @math{k} throughput (@math{k=1, @dots{}, M}). @end table @strong{REFERENCES} @itemize @item G. Casale. @cite{A note on stable flow-equivalent aggregation in closed networks}. Queueing Syst. Theory Appl., 60:193–-202, December 2008, @uref{http://dx.doi.org/10.1007/s11134-008-9093-6, 10.1007/s11134-008-9093-6} @end itemize @end deftypefn @c @c Approximate MVA for single class, closed networks @c @anchor{doc-qncsmvaap} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}, @var{iter_max}) @cindex Mean Value Analysys (MVA), approximate @cindex MVA, approximate @cindex approximate MVA @cindex closed network, single class @cindex closed network, approximate analysis Analyze closed, single class queueing networks using the Approximate Mean Value Analysis (MVA) algorithm. This function is based on approximating the number of customers seen at center @math{k} when a new request arrives as @math{Q_k(N) \times (N-1)/N}. This function only handles single-server and delay centers; if your network contains general load-dependent service centers, use the function @code{qncsmvald} instead. @strong{INPUTS} @table @code @item @var{N} Population size (number of requests in the system, @code{@var{N} > 0}). @item @var{S}(k) mean service time on server @math{k} (@code{@var{S}(k)>0}). @item @var{V}(k) average number of visits to service center @math{k} (@code{@var{V}(k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k} (if @var{m} is a scalar, all centers have that number of servers). If @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); if @code{@var{m}(k) == 1}, center @math{k} is a regular queueing center (FCFS, LCFS-PR or PS) with one server (default). This function does not support multiple server nodes (@code{@var{m}(k) > 1}). @item @var{Z} External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. @item @var{tol} Stopping tolerance. The algorithm stops when the maximum relative difference between the new and old value of the queue lengths @var{Q} becomes less than the tolerance. Default is @math{10^{-5}}. @item @var{iter_max} Maximum number of iterations (@code{@var{iter_max}>0}. The function aborts if convergenge is not reached within the maximum number of iterations. Default is 100. @end table @strong{OUTPUTS} @table @code @item @var{U}(k) If @math{k} is a FCFS, LCFS-PR or PS node (@code{@var{m}(k) == 1}), then @code{@var{U}(k)} is the utilization of center @math{k}. If @math{k} is an IS node (@code{@var{m}(k) < 1}), then @code{@var{U}(k)} is the @emph{traffic intensity} defined as @code{@var{X}(k)*@var{S}(k)}. @item @var{R}(k) response time at center @math{k}. The system response time @var{Rsys} can be computed as @code{@var{Rsys} = @var{N}/@var{Xsys} - Z} @item @var{Q}(k) average number of requests at center @math{k}. The number of requests in the system can be computed either as @code{sum(@var{Q})}, or using the formula @code{@var{N}-@var{Xsys}*@var{Z}}. @item @var{X}(k) center @math{k} throughput. The system throughput @var{Xsys} can be computed as @code{@var{Xsys} = @var{X}(1) / @var{V}(1)} @end table @strong{REFERENCES} This implementation is based on Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer System Analysis Using Queueing Network Models}, Prentice Hall, 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In particular, see section 6.4.2.2 ("Approximate Solution Techniques"). @xseealso{qncsmva,qncsmvald} @end deftypefn @c @c Convolution @c According to the BCMP theorem, the state probability of a closed single class queueing network with @math{K} nodes and @math{N} requests can be expressed as: @iftex @tex $$ \pi(n_1, \ldots, n_K) = {1 \over G(N)} \prod_{k=1}^K F_k(n_k) $$ @end tex @end iftex @ifnottex @example @group n = [n1, @dots{} nK]; @r{population vector} p = 1/G(N+1) \prod F(k,k); @end group @end example @end ifnottex Here @math{\pi(n_1, @dots{}, n_K)} is the joint probability of having @math{n_k} requests at node @math{k}, for all @math{k=1, @dots{}, K}; we have that @math{\sum_{k=1}^K n_k = N} The @emph{convolution algorithms} computes the normalization constants @math{{\bf G} = \left[G(0), @dots{}, G(N)\right]} for single-class, closed networks with @math{N} requests. The normalization constants are returned as vector @code{@var{G}=[@var{G}(1), @dots{} @var{G}(N+1)]} where @code{@var{G}(i+1)} is the value of @math{G(i)} (remember that Octave uses 1-base vectors). The normalization constant can be used to compute all performance measures of interest (utilization, average response time and so on). @command{queueing} implements the convolution algorithm, in the function @command{qncsconv} and @command{qncsconvld}. The first one supports single-station nodes, multiple-station nodes and IS nodes. The second one supports networks with general load-dependent service centers. @anchor{doc-qncsconv} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsconv (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsconv (@var{N}, @var{S}, @var{V}, @var{m}) @cindex closed network, single class @cindex normalization constant @cindex convolution algorithm Analyze product-form, single class closed networks with @math{K} service centers using the convolution algorithm. Load-independent service centers, multiple servers (@math{M/M/m} queues) and IS nodes are supported. For general load-dependent service centers, use @code{qncsconvld} instead. @strong{INPUTS} @table @code @item @var{N} Number of requests in the system (@code{@var{N}>0}). @item @var{S}(k) average service time on center @math{k} (@code{@var{S}(k) @geq{} 0}). @item @var{V}(k) visit count of service center @math{k} (@code{@var{V}(k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k}. If @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); if @code{@var{m}(k) @geq{} 1}, center @math{k} it is a regular @math{M/M/m} queueing center with @code{@var{m}(k)} identical servers. Default is @code{@var{m}(k) = 1} for all @math{k}. @end table @strong{OUTPUT} @table @code @item @var{U}(k) center @math{k} utilization. For IS nodes, @code{@var{U}(k)} is the @emph{traffic intensity} @code{@var{X}(k) * @var{S}(k)}. @item @var{R}(k) average response time of center @math{k}. @item @var{Q}(k) average number of customers at center @math{k}. @item @var{X}(k) throughput of center @math{k}. @item @var{G}(n) Vector of normalization constants. @code{@var{G}(n+1)} contains the value of the normalization constant with @math{n} requests @math{G(n)}, @math{n=0, @dots{}, N}. @end table @strong{NOTE} For a network with @math{K} service centers and @math{N} requests, this implementation of the convolution algorithm has time and space complexity @math{O(NK)}. @strong{REFERENCES} @itemize @item Jeffrey P. Buzen, @cite{Computational Algorithms for Closed Queueing Networks with Exponential Servers}, Communications of the ACM, volume 16, number 9, September 1973, pp. 527--531. @uref{http://doi.acm.org/10.1145/362342.362345, 10.1145/362342.362345} @end itemize This implementation is based on G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998, pp. 313--317. @xseealso{qncsconvld} @end deftypefn @noindent @strong{EXAMPLE} The normalization constant @math{G} can be used to compute the steady-state probabilities for a closed single class product-form Queueing Network with @math{K} nodes and @math{N} requests. Let @code{@var{n} = [@math{n_1, @dots{}, n_K}]} be a valid population vector, @math{\sum_{k=1}^K n_k = N}. Then, the steady-state probability @code{@var{p}(k)} to have @code{@var{n}(k)} requests at service center @math{k} can be computed as: @iftex @tex $$ p_k(n_k) = {(V_k S_k)^{n_k} \over G(N)} \left(G(N-n_k) - V_k S_k G(N-n_k-1)\right), \quad k=1, \ldots, K $$ @end tex @end iftex @example @verbatim n = [1 2 0]; N = sum(n); # Total population size S = [ 1/0.8 1/0.6 1/0.4 ]; m = [ 2 3 1 ]; V = [ 1 .667 .2 ]; [U R Q X G] = qncsconv( N, S, V, m ); p = [0 0 0]; # initialize p # Compute the probability to have n(k) jobs at service center k for k=1:3 p(k) = (V(k)*S(k))^n(k) / G(N+1) * ... (G(N-n(k)+1) - V(k)*S(k)*G(N-n(k)) ); printf("Prob( n(%d) = %d )=%f\n", k, n(k), p(k) ); endfor @end verbatim @print{} Prob( n(1) = 1 ) = 0.17975 @print{} Prob( n(2) = 2 ) = 0.48404 @print{} Prob( n(3) = 0 ) = 0.52779 @end example @noindent (recall that @code{@var{G}(@var{N}+1)} represents @math{G(N)}, since in Octave array indices start at one). @c @anchor{doc-qncsconvld} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsconvld (@var{N}, @var{S}, @var{V}) @cindex closed network @cindex normalization constant @cindex convolution algorithm @cindex load-dependent service center Convolution algorithm for product-form, single-class closed queueing networks with @math{K} general load-dependent service centers. This function computes steady-state performance measures for single-class, closed networks with load-dependent service centers using the convolution algorithm; the normalization constants are also computed. The normalization constants are returned as vector @code{@var{G}=[@var{G}(1), @dots{}, @var{G}(N+1)]} where @code{@var{G}(i+1)} is the value of @math{G(i)}. @strong{INPUTS} @table @code @item @var{N} Number of requests in the system (@code{@var{N}>0}). @item @var{S}(k,n) mean service time at center @math{k} where there are @math{n} requests, @math{1 @leq{} n @leq{} N}. @code{@var{S}(k,n)} @math{= 1 / \mu_{k,n}}, where @math{\mu_{k,n}} is the service rate of center @math{k} when there are @math{n} requests. @item @var{V}(k) visit count of service center @math{k} (@code{@var{V}(k) @geq{} 0}). The length of @var{V} is the number of servers @math{K} in the network. @end table @strong{OUTPUT} @table @code @item @var{U}(k) center @math{k} utilization. @item @var{R}(k) average response time at center @math{k}. @item @var{Q}(k) average number of requests in center @math{k}. @item @var{X}(k) center @math{k} throughput. @item @var{G}(n) Normalization constants (vector). @code{@var{G}(n+1)} corresponds to @math{G(n)}, as array indexes in Octave start from 1. @end table @strong{REFERENCES} @itemize @item Herb Schwetman, @cite{Some Computational Aspects of Queueing Network Models}, Technical Report @uref{http://docs.lib.purdue.edu/cstech/285/, CSD-TR-354}, Department of Computer Sciences, Purdue University, February 1981 (revised). @item M. Reiser, H. Kobayashi, @cite{On The Convolution Algorithm for Separable Queueing Networks}, In Proceedings of the 1976 ACM SIGMETRICS Conference on Computer Performance Modeling Measurement and Evaluation (Cambridge, Massachusetts, United States, March 29--31, 1976). SIGMETRICS '76. ACM, New York, NY, pp. 109--117. @uref{http://doi.acm.org/10.1145/800200.806187, 10.1145/800200.806187} @end itemize This implementation is based on G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998, pp. 313--317. Function @command{qncsconvld} is slightly different from the version described in Bolch et al. because it supports general load-dependent centers (while the version in the book does not). The modification is in the definition of function @code{F()} in @command{qncsconvld} which has been made similar to function @math{f_i} defined in Schwetman, @cite{Some Computational Aspects of Queueing Network Models}. @xseealso{qncsconv} @end deftypefn @c @c @c @subsection Non Product-Form QNs @anchor{Non Product-Form QNs} @c @c MVABLO algorithm for approximate analysis of closed, single class @c QN with blocking @c @anchor{doc-qncsmvablo} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvablo (@var{N}, @var{S}, @var{M}, @var{P} ) @cindex queueing network with blocking @cindex blocking queueing network @cindex closed network, finite capacity @cindex MVABLO Approximate MVA algorithm for closed queueing networks with blocking. @strong{INPUTS} @table @code @item @var{N} number of requests in the system. @var{N} must be strictly greater than zero, and less than the overall network capacity: @code{0 < @var{N} < sum(@var{M})}. @item @var{S}(k) average service time on server @math{k} (@code{@var{S}(k) > 0}). @item @var{M}(k) capacity of center @math{k}. The capacity is the maximum number of requests in a service center, including the request in service (@code{@var{M}(k) @geq{} 1}). @item @var{P}(i,j) probability that a request which completes service at server @math{i} will be transferred to server @math{j}. @end table @strong{OUTPUTS} @table @code @item @var{U}(k) center @math{k} utilization. @item @var{R}(k) average response time of service center @math{k}. @item @var{Q}(k) average number of requests in service center @math{k} (including the request in service). @item @var{X}(k) center @math{k} throughput. @end table @strong{REFERENCES} @itemize @item Ian F. Akyildiz, @cite{Mean Value Analysis for Blocking Queueing Networks}, IEEE Transactions on Software Engineering, vol. 14, n. 2, april 1988, pp. 418--428. @uref{http://dx.doi.org/10.1109/32.4663, 10.1109/32.4663} @end itemize @xseealso{qnopen, qnclosed} @end deftypefn @c @anchor{doc-qnmarkov} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{lambda}, @var{S}, @var{C}, @var{P}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{lambda}, @var{S}, @var{C}, @var{P}, @var{m}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{N}, @var{S}, @var{C}, @var{P}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{N}, @var{S}, @var{C}, @var{P}, @var{m}) @cindex closed network, single class @cindex open network, single class @cindex closed network, finite capacity @cindex blocking queueing network @cindex RS blocking Compute utilization, response time, average queue length and throughput for open or closed queueing networks with finite capacity and a single class of requests. Blocking type is Repetitive-Service (RS). This function explicitly generates and solve the underlying Markov chain, and thus might require a large amount of memory. More specifically, networks which can me analyzed by this function have the following properties: @itemize @bullet @item There exists only a single class of customers. @item The network has @math{K} service centers. Center @math{k \in @{1, @dots{}, K@}} has @math{m_k > 0} servers, and has a total (finite) capacity of @math{C_k \geq m_k} which includes both buffer space and servers. The buffer space at service center @math{k} is therefore @math{C_k - m_k}. @item The network can be open, with external arrival rate to center @math{k} equal to @math{\lambda_k}, or closed with fixed population size @math{N}. For closed networks, the population size @math{N} must be strictly less than the network capacity: @math{N < \sum_{k=1}^K C_k}. @item Average service times are load-independent. @item @math{P_{i, j}} is the probability that requests completing execution at center @math{i} are transferred to center @math{j}, @math{i \neq j}. For open networks, a request may leave the system from any node @math{i} with probability @math{1-\sum_{j=1}^K P_{i, j}}. @item Blocking type is Repetitive-Service (RS). Service center @math{j} is @emph{saturated} if the number of requests is equal to its capacity @math{C_j}. Under the RS blocking discipline, a request completing service at center @math{i} which is being transferred to a saturated server @math{j} is put back at the end of the queue of @math{i} and will receive service again. Center @math{i} then processes the next request in queue. External arrivals to a saturated servers are dropped. @end itemize @strong{INPUTS} @table @code @item @var{lambda}(k) @itemx @var{N} If the first argument is a vector @var{lambda}, it is considered to be the external arrival rate @code{@var{lambda}(k) @geq{} 0} to service center @math{k} of an open network. If the first argument is a scalar, it is considered as the population size @var{N} of a closed network; in this case @var{N} must be strictly less than the network capacity: @code{@var{N} < sum(@var{C})}. @item @var{S}(k) average service time at service center @math{k} @item @var{C}(k) capacity of service center @math{k}. The capacity includes both the buffer and server space @code{@var{m}(k)}. Thus the buffer space is @code{@var{C}(k)-@var{m}(k)}. @item @var{P}(i,j) transition probability from service center @math{i} to service center @math{j}. @item @var{m}(k) number of servers at service center @math{k}. Note that @code{@var{m}(k) @geq{} @var{C}(k)} for each @var{k}. If @var{m} is omitted, all service centers are assumed to have a single server (@code{@var{m}(k) = 1} for all @math{k}). @end table @strong{OUTPUTS} @table @code @item @var{U}(k) center @math{k} utilization. @item @var{R}(k) response time on service center @math{k}. @item @var{Q}(k) average number of customers in the service center @math{k}, @emph{including} the request in service. @item @var{X}(k) throughput of service center @math{k}. @end table @strong{NOTES} The space complexity of this implementation is @math{O(\prod_{k=1}^K (C_k + 1)^2)}. The time complexity is dominated by the time needed to solve a linear system with @math{\prod_{k=1}^K (C_k + 1)} unknowns. @end deftypefn @c @c @c @node Multiple Class Models @section Multiple Class Models @cindex multiple class queueing network @cindex queueing network, multiple class In multiple class queueing models, we assume that there exist @math{C} different classes of requests. Each request from class @math{c} spends on average time @math{S_{c, k}} in service at center @math{k}. For open models, we denote with @math{{\bf \lambda} = \lambda_{c, k}} the arrival rates, where @math{\lambda_{c, k}} is the external arrival rate of class @math{c} requests at center @math{k}. For closed models, we denote with @math{{\bf N} = \left[N_1, @dots{}, N_C\right]} the population vector, where @math{N_c} is the number of class @math{c} requests in the system. The transition probability matrix for multiple class networks is a @math{C \times K \times C \times K} matrix @math{{\bf P} = [P_{r, i, s, j}]} where @math{P_{r, i, s, j}} is the probability that a class @math{r} request which completes service at center @math{i} will join server @math{j} as a class @math{s} request. Model input and outputs can be adjusted by adding additional indexes for the customer classes. @noindent @strong{Model Inputs} @cindex external arrival rate @cindex service time @cindex routing probability matrix @cindex average number of visits @table @asis @item @math{@lambdack} (open networks) External arrival rate of class-@math{c} requests to service center @math{k} @item @math{@lambda} (open networks) Overall external arrival rate to the whole system: @math{\lambda = \sum_{c=1}^C \sum_{k=1}^K \lambda_{c, k}} @item @math{N_c} (closed networks) Number of class @math{c} requests in the system. @item @math{S_{c, k}} Average service time. @math{S_{c, k}} is the average service time on service center @math{k} for class @math{c} requests. @item @math{P_{r, i, s, j}} Routing probability matrix. @math{{\bf P} = [P_{r, i, s, j}]} is a @math{C \times K \times C \times K} matrix such that @math{P_{r, i, s, j}} is the probability that a class @math{r} request which completes service at server @math{i} will move to server @math{j} as a class @math{s} request. @item @math{V_{c, k}} Mean number of visits of class @math{c} requests to center @math{k}. @end table @noindent @strong{Model Outputs} @cindex utilization @cindex response time @cindex average number of customers @cindex throughput @cindex system response time @cindex system throughput @table @asis @item @math{U_{c, k}} Utilization of service center @math{k} by class @math{c} requests. The utilization is defined as the fraction of time in which the resource is busy (i.e., the server is processing requests). If center @math{k} is a single-server or multiserver node, then @math{0 @leq{} U_{c, k} @leq{} 1}. If center @math{k} is an infinite server node (delay center), then @math{U_{c, k}} denotes the @emph{traffic intensity} and is defined as @math{U_{c, k} = X_{c, k} S_{c, k}}; in this case the utilization may be greater than one. @item @math{R_{c, k}} Average response time experienced by class @math{c} requests on service center @math{k}. The average response time is defined as the average time between the arrival of a customer in the queue, and the completion of service. @item @math{Q_{c, k}} Average number of class @math{c} requests on service center @math{k}. This includes both the requests in the queue, and the request being served. @item @math{X_{c, k}} Throughput of service center @math{k} for class @math{c} requests. The throughput is defined as the rate of completion of class @math{c} requests. @end table @noindent It is possible to define aggregate performance measures as follows: @table @math @item U_k Utilization of service center @math{k}: @iftex @tex $U_k = \sum_{c=1}^C U_{c, k}$ @end tex @end iftex @ifnottex @code{Uk = sum(U,k);} @end ifnottex @item R_c System response time for class @math{c} requests: @iftex @tex $R_c = \sum_{k=1}^K R_{c, k} V_{c, k}$ @end tex @end iftex @ifnottex @code{Rc = sum( V.*R, 1 );} @end ifnottex @item Q_c Average number of class @math{c} requests in the system: @iftex @tex $Q_c = \sum_{k=1}^K Q_{c, k}$ @end tex @end iftex @ifnottex @code{Qc = sum( Q, 2 );} @end ifnottex @item X_c Class @math{c} throughput: @iftex @tex $X_c = X_{c, k} / V_{c, k}$ for any @math{k} for which @math{V_{c,k} \neq 0} @end tex @end iftex @ifnottex @code{X(c) = X(c,k) ./ V(c,k);} for any @math{k} for which @code{V(c,k) != 0} @end ifnottex @end table For closed networks, we can define the visit ratios @math{V_{s, j}} for class @math{s} customers at service center @math{j} as follows: @iftex @tex $$\left\{\eqalign{ V_{s, j} & = \sum_{r=1}^C \sum_{i=1}^K V_{r, i} P_{r, i, s, j}, \quad s=1, \ldots, C, j=1, \ldots, K \cr V_{s, r_s} & = 1, \quad s=1, \ldots, C}\right. $$ @end tex @end iftex @ifnottex @group V_sj = sum_r sum_i V_ri P_risj s=1,...,C, j=1,...,K V_s r_s = 1 s=1,...,C @end group @end ifnottex @noindent where @math{r_s} is the class @math{s} reference station. Similarly to single class models, the traffic equation for closed multiclass networks can be solved up to multiplicative constants unless we choose one reference station for each closed class and set its visit ratio to 1. For open networks the traffic equations are as follows: @iftex @tex $$V_{s, j} = P_{0, s, j} + \sum_{r=1}^C \sum_{i=1}^K V_{r, i} P_{r, i, s, j} \quad s=1, \ldots, C, j=1, \ldots, K$$ @end tex @end iftex @ifnottex @group V_sj = P_0sj + sum_r sum_i V_ri P_risj s=1,...,C, j=1,...,K @end group @end ifnottex @noindent where @math{P_{0, s, j}} is the probability that an external arrival goes to service center @math{j} as a class-@math{s} request. If @math{\lambda_{s, j}} is the external arrival rate of class @math{s} requests to service center @math{j}, and @math{\lambda = \sum_s \sum_j \lambda_{s, j}} is the overall external arrival rate, then @math{P_{0, s, j} = \lambda_{s, j} / \lambda}. @anchor{doc-qncmvisits} @deftypefn {Function File} {[@var{V} @var{ch}] =} qncmvisits (@var{P}) @deftypefnx {Function File} {[@var{V} @var{ch}] =} qncmvisits (@var{P}, @var{r}) Compute the average number of visits for the nodes of a closed multiclass network with @math{K} service centers and @math{C} customer classes. @strong{INPUTS} @table @code @item @var{P}(r,i,s,j) probability that a class @math{r} request which completed service at center @math{i} is routed to center @math{j} as a class @math{s} request. Class switching is allowed. @item @var{r}(c) index of class @math{c} reference station, @math{r(c) \in @{1, @dots{}, K@}}, @math{1 @leq{} c @leq{} C}. The class @math{c} visit count to server @code{@var{r}(c)} (@code{@var{V}(c,r(c))}) is conventionally set to 1. The reference station serves two purposes: (i) its throughput is assumed to be the system throughput, and (ii) a job returning to the reference station is assumed to have completed one cycle. Default is to consider station 1 as the reference station for all classes. @end table @strong{OUTPUTS} @table @code @item @var{V}(c,i) number of visits of class @math{c} requests at center @math{i}. @item @var{ch}(c) chain number that class @math{c} belongs to. Different classes can belong to the same chain. Chains are numbered sequentially starting from 1 (@math{1, 2, @dots{}}). The total number of chains is @code{max(@var{ch})}. @end table @end deftypefn @anchor{doc-qnomvisits} @deftypefn {Function File} {@var{V} =} qnomvisits (@var{P}, @var{lambda}) Compute the visit ratios to the service centers of an open multiclass network with @math{K} service centers and @math{C} customer classes. @strong{INPUTS} @table @code @item @var{P}(r,i,s,j) probability that a class @math{r} request which completed service at center @math{i} is routed to center @math{j} as a class @math{s} request. Class switching is supported. @item @var{lambda}(r,i) external arrival rate of class @math{r} requests to center @math{i}. @end table @strong{OUTPUTS} @table @code @item @var{V}(r,i) visit ratio of class @math{r} requests at center @math{i}. @end table @end deftypefn @c @c Open Networks @c @subsection Open Networks @c @c Open network with multiple classes @c @anchor{doc-qnom} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnom (@var{lambda}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnom (@var{lambda}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnom (@var{lambda}, @var{S}, @var{P}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnom (@var{lambda}, @var{S}, @var{P}, @var{m}) @cindex open network, multiple classes @cindex multiclass network, open Exact analysis of open, multiple-class BCMP networks. The network can be made of @emph{single-server} queueing centers (FCFS, LCFS-PR or PS) or delay centers (IS). This function assumes a network with @math{K} service centers and @math{C} customer classes. @strong{INPUTS} @table @code @item @var{lambda}(c) If this function is invoked as @code{qnom(lambda, S, V, @dots{})}, then @code{@var{lambda}(c)} is the external arrival rate of class @math{c} customers (@code{@var{lambda}(c) @geq{} 0}). If this function is invoked as @code{qnom(lambda, S, P, @dots{})}, then @code{@var{lambda}(c,k)} is the external arrival rate of class @math{c} customers at center @math{k} (@code{@var{lambda}(c,k) @geq{} 0}). @item @var{S}(c,k) mean service time of class @math{c} customers on the service center @math{k} (@code{@var{S}(c,k)>0}). For FCFS nodes, mean service times must be class-independent. @item @var{V}(c,k) visit ratio of class @math{c} customers to service center @math{k} (@code{@var{V}(c,k) @geq{} 0 }). @strong{If you pass this argument, class switching is not allowed} @item @var{P}(r,i,s,j) probability that a class @math{r} job completing service at center @math{i} is routed to center @math{j} as a class @math{s} job. @strong{If you pass argument @var{P}, class switching is allowed}; however, all servers must be fixed-rate or infinite-server nodes (@code{@var{m}(k) @leq{} 1} for all @math{k}). @item @var{m}(k) number of servers at center @math{k}. If @code{@var{m}(k) < 1}, enter @math{k} is a delay center (IS); otherwise it is a regular queueing center with @code{@var{m}(k)} servers. Default is @code{@var{m}(k) = 1} for all @math{k}. @end table @strong{OUTPUTS} @table @code @item @var{U}(c,k) If @math{k} is a queueing center, then @code{@var{U}(c,k)} is the class @math{c} utilization of center @math{k}. If @math{k} is an IS node, then @code{@var{U}(c,k)} is the class @math{c} @emph{traffic intensity} defined as @code{@var{X}(c,k)*@var{S}(c,k)}. @item @var{R}(c,k) class @math{c} response time at center @math{k}. The system response time for class @math{c} requests can be computed as @code{dot(@var{R}, @var{V}, 2)}. @item @var{Q}(c,k) average number of class @math{c} requests at center @math{k}. The average number of class @math{c} requests in the system @var{Qc} can be computed as @code{Qc = sum(@var{Q}, 2)} @item @var{X}(c,k) class @math{c} throughput at center @math{k}. @end table @strong{NOTES} If the function call specifies the visit ratios @var{V}, class switching is @strong{not} allowed. If the function call specifies the routing probability matrix @var{P}, then class switching @strong{is} allowed; however, all nodes are restricted to be fixed rate servers or delay centers: multiple-server and general load-dependent centers are not supported. Note that the meaning of parameter @var{lambda} is different from one case to the other (see below). @strong{REFERENCES} @itemize @item Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer System Analysis Using Queueing Network Models}, Prentice Hall, 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In particular, see section 7.4.1 ("Open Model Solution Techniques"). @end itemize @xseealso{qnopen,qnos,qnomvisits} @end deftypefn @c @c Closed Networks @c @subsection Closed Networks @c @anchor{doc-qncmpopmix} @deftypefn {Function File} {pop_mix =} qncmpopmix (@var{k}, @var{N}) @cindex population mix @cindex closed network, multiple classes Return the set of population mixes for a closed multiclass queueing network with exactly @var{k} customers. Specifically, given a closed multiclass QN with @math{C} customer classes, where there are @code{@var{N}(c)} class @math{c} requests, @math{c = 1, @dots{}, C} a @math{k}-mix @math{M} is a vector of length @math{C} with the following properties: @itemize @item @math{0 @leq{} M_c @leq{} @var{N}(c)} for all @math{c = 1, @dots{}, C}; @item @math{\sum_{c=1}^C M_c = k} @end itemize In other words, a @math{k}-mix is an allocation of @math{k} requests to @math{C} classes such that the number of requests assigned to class @math{c} does not exceed the maximum value @code{@var{N}(c)}. @var{pop_mix} is a matrix with @math{C} columns, such that each row represents a valid mix. @strong{INPUTS} @table @code @item @var{k} Size of the requested mix (scalar, @code{@var{k} @geq{} 0}). @item @var{N}(c) number of class @math{c} requests (@code{@var{k} @leq{} sum(@var{N})}). @end table @strong{OUTPUTS} @table @code @item @var{pop_mix}(i,c) number of class @math{c} requests in the @math{i}-th population mix. The number of mixes is @code{rows(@var{pop_mix})}. @end table If you are interested in the number of @math{k}-mixes only, you can use the funcion @code{qnmvapop}. @strong{REFERENCES} @itemize @item Herb Schwetman, @cite{Implementing the Mean Value Algorithm for the Solution of Queueing Network Models}, Technical Report @uref{http://docs.lib.purdue.edu/cstech/286/, 80-355}, Department of Computer Sciences, Purdue University, revised February 15, 1982. @end itemize The slightly different problem of enumerating all tuples @math{k_1, @dots{}, k_N} such that @math{\sum_i k_i = k} and @math{k_i @geq{} 0}, for a given @math{k @geq{} 0} has been described in S. Santini, @cite{Computing the Indices for a Complex Summation}, unpublished report, available at @url{http://arantxa.ii.uam.es/~ssantini/writing/notes/s668_summation.pdf} @xseealso{qncmnpop} @end deftypefn @noindent @strong{EXAMPLE} Let us consider a multiclass network with @math{C=2} customer classes; the maximum number of class 1 requests is 2, and the maximum number of class 2 requests is 3. How is it possible to allocate 3 requests to the two classes so that the maximum number of requests per class is not exceeded? @example @verbatim N = [2 3]; mix = qncmpopmix(3, N) @end verbatim @print{} mix = [ [2 1] [1 2] [0 3] ] @end example @c @anchor{doc-qncmnpop} @deftypefn {Function File} {@var{H} =} qncmnpop (@var{N}) @cindex population mix @cindex closed network, multiple classes Given a network with @math{C} customer classes, this function computes the number of @math{k}-mixes @code{@var{H}(r,k)} that can be constructed by the multiclass MVA algorithm by allocating @math{k} customers to the first @math{r} classes. @xref{doc-qncmpopmix} for the definition of @math{k}-mix. @strong{INPUTS} @table @code @item @var{N}(c) number of class-@math{c} requests in the system. The total number of requests in the network is @code{sum(@var{N})}. @end table @strong{OUTPUTS} @table @code @item @var{H}(r,k) is the number of @math{k} mixes that can be constructed allocating @math{k} customers to the first @math{r} classes. @end table @strong{REFERENCES} @itemize @item Zahorjan, J. and Wong, E. @cite{The solution of separable queueing network models using mean value analysis}. SIGMETRICS Perform. Eval. Rev. 10, 3 (Sep. 1981), 80-85. DOI @uref{http://doi.acm.org/10.1145/1010629.805477, 10.1145/1010629.805477} @end itemize @xseealso{qncmmva,qncmpopmix} @end deftypefn @c @c MVA for multiple class, closed networks @c @anchor{doc-qncmmva} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S} ) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{P}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{P}, @var{r}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{P}, @var{r}, @var{m}) @cindex Mean Value Analysys (MVA) @cindex closed network, multiple classes @cindex multiclass network, closed Compute steady-state performance measures for closed, multiclass queueing networks using the Mean Value Analysys (MVA) algorithm. Queueing policies at service centers can be any of the following: @table @strong @item FCFS (First-Come-First-Served) customers are served in order of arrival; multiple servers are allowed. For this kind of queueing discipline, average service times must be class-independent. @item PS (Processor Sharing) customers are served in parallel by a single server, each customer receiving an equal share of the service rate. @item LCFS-PR (Last-Come-First-Served, Preemptive Resume) customers are served in reverse order of arrival by a single server and the last arrival preempts the customer in service who will later resume service at the point of interruption. @item IS (Infinite Server) customers are delayed independently of other customers at the service center (there is effectively an infinite number of servers). @end table @strong{INPUTS} @table @code @item @var{N}(c) number of class @math{c} requests; @code{@var{N}(c) @geq{} 0}. If class @math{c} has no requests (@code{@var{N}(c) == 0}), then for all @var{k}, this function returns @code{@var{U}(c,k) = @var{R}(c,k) = @var{Q}(c,k) = @var{X}(c,k) = 0} @item @var{S}(c,k) mean service time for class @math{c} requests at center @math{k} (@code{@var{S}(c,k) @geq{} 0}). If the service time at center @math{k} is class-dependent, then center @math{k} is assumed to be of type @math{-/G/1}--PS (Processor Sharing). If center @math{k} is a FCFS node (@code{@var{m}(k)>1}), then the service times @strong{must} be class-independent, i.e., all classes @strong{must} have the same service time. @item @var{V}(c,k) average number of visits of class @math{c} requests at center @math{k}; @code{@var{V}(c,k) @geq{} 0}, default is 1. @strong{If you pass this argument, class switching is not allowed} @item @var{P}(r,i,s,j) probability that a class @math{r} request completing service at center @math{i} is routed to center @math{j} as a class @math{s} request; the reference stations for each class are specified with the paramter @var{r}. @strong{If you pass argument @var{P}, class switching is allowed}; however, you can not specify any external delay (i.e., @var{Z} must be zero) and all servers must be fixed-rate or infinite-server nodes (@code{@var{m}(k) @leq{} 1} for all @math{k}). @item @var{r}(c) reference station for class @math{c}. If omitted, station 1 is the reference station for all classes. See @command{qncmvisits}. @item @var{m}(k) If @code{@var{m}(k)<1}, then center @math{k} is assumed to be a delay center (IS node @math{-/G/\infty}). If @code{@var{m}(k)==1}, then service center @math{k} is a regular queueing center (@math{M/M/1}--FCFS, @math{-/G/1}--LCFS-PR or @math{-/G/1}--PS). Finally, if @code{@var{m}(k)>1}, center @math{k} is a @math{M/M/m}--FCFS center with @code{@var{m}(k)} identical servers. Default is @code{@var{m}(k)=1} for each @math{k}. @item @var{Z}(c) class @math{c} external delay (think time); @code{@var{Z}(c) @geq{} 0}. Default is 0. This parameter can not be used if you pass a routing matrix as the second parameter of @code{qncmmva}. @end table @strong{OUTPUTS} @table @code @item @var{U}(c,k) If @math{k} is a FCFS, LCFS-PR or PS node (@code{@var{m}(k) @geq{} 1}), then @code{@var{U}(c,k)} is the class @math{c} utilization at center @math{k}, @math{0 @leq{} U(c,k) @leq{} 1}. If @math{k} is an IS node, then @code{@var{U}(c,k)} is the class @math{c} @emph{traffic intensity} at center @math{k}, defined as @code{@var{U}(c,k) = @var{X}(c,k)*@var{S}(c,k)}. In this case the value of @code{@var{U}(c,k)} may be greater than one. @item @var{R}(c,k) class @math{c} response time at center @math{k}. The class @math{c} @emph{residence time} at center @math{k} is @code{@var{R}(c,k) * @var{C}(c,k)}. The total class @math{c} system response time is @code{dot(@var{R}, @var{V}, 2)}. @item @var{Q}(c,k) average number of class @math{c} requests at center @math{k}. The total number of requests at center @math{k} is @code{sum(@var{Q}(:,k))}. The total number of class @math{c} requests in the system is @code{sum(@var{Q}(c,:))}. @item @var{X}(c,k) class @math{c} throughput at center @math{k}. The class @math{c} throughput can be computed as @code{@var{X}(c,1) / @var{V}(c,1)}. @end table @strong{NOTES} If the function call specifies the visit ratios @var{V}, then class switching is @strong{not} allowed. If the function call specifies the routing probability matrix @var{P}, then class switching @strong{is} allowed; however, in this case all nodes are restricted to be fixed rate servers or delay centers: multiple-server and general load-dependent centers are not supported. In presence of load-dependent servers (e.g., if @code{@var{m}(i)>1} for some @math{i}), the MVA algorithm is known to be numerically unstable. Generally this problem shows up as negative values for the computed response times or utilizations. This is not a problem with the @code{queueing} package, but with the MVA algorithm; as such, there is no known workaround at the moment (aoart from using a different solution technique, if available). This function prints a warning if it detects numerical problems; you can disable the warning with the command @code{warning("off", "qn:numerical-instability")}. Given a network with @math{K} service centers, @math{C} job classes and population vector @math{{\bf N}=\left[N_1, @dots{}, N_C\right]}, the MVA algorithm requires space @math{O(C \prod_i (N_i + 1))}. The time complexity is @math{O(CK\prod_i (N_i + 1))}. This implementation is slightly more space-efficient (see details in the code). While the space requirement can be mitigated by using some optimizations, the time complexity can not. If you need to analyze large closed networks you should consider the @command{qncmmvaap} function, which implements the approximate MVA algorithm. Note however that @command{qncmmvaap} will only provide approximate results. @strong{REFERENCES} @itemize @item M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, April 1980, pp. 313--322. @uref{http://doi.acm.org/10.1145/322186.322195, 10.1145/322186.322195} @end itemize This implementation is based on G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998 and Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer System Analysis Using Queueing Network Models}, Prentice Hall, 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In particular, see section 7.4.2.1 ("Exact Solution Techniques"). @xseealso{qnclosed, qncmmvaapprox, qncmvisits} @end deftypefn @c @c Approximate MVA, with Bard-Schweitzer approximation @c @anchor{doc-qncmmvabs} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}, @var{iter_max}) @cindex Mean Value Analysys (MVA), approximate @cindex MVA, approximate @cindex closed network, multiple classes @cindex multiclass network, closed Approximate Mean Value Analysis (MVA) for closed, multiclass queueing networks with @math{K} service centers and @math{C} customer classes. This implementation uses Bard and Schweitzer approximation. It is based on the assumption that the queue length at service center @math{k} with population set @math{{\bf N}-{\bf 1}_c} is approximated with @tex $$Q_k({\bf N}-{\bf 1}_c) \approx {n-1 \over n} Q_k({\bf N})$$ @end tex @ifnottex @example @group Q_k(N-1c) ~ (n-1)/n Q_k(N) @end group @end example @end ifnottex where @math{\bf N} is a valid population mix, @math{{\bf N}-{\bf 1}_c} is the population mix @math{\bf N} with one class @math{c} customer removed, and @math{n = \sum_c N_c} is the total number of requests. This implementation works for networks with infinite server (IS) and single-server nodes only. @strong{INPUTS} @table @code @item @var{N}(c) number of class @math{c} requests in the system (@code{@var{N}(c) @geq{} 0}). @item @var{S}(c,k) mean service time for class @math{c} customers at center @math{k} (@code{@var{S}(c,k) @geq{} 0}). @item @var{V}(c,k) average number of visits of class @math{c} requests to center @math{k} (@code{@var{V}(c,k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k}. If @code{@var{m}(k) < 1}, then the service center @math{k} is assumed to be a delay center (IS). If @code{@var{m}(k) == 1}, service center @math{k} is a regular queueing center (FCFS, LCFS-PR or PS) with a single server node. If omitted, each service center has a single server. Note that multiple server nodes are not supported. @item @var{Z}(c) class @math{c} external delay (@code{@var{Z} @geq{} 0}). Default is 0. @item @var{tol} Stopping tolerance (@code{@var{tol}>0}). The algorithm stops if the queue length computed on two subsequent iterations are less than @var{tol}. Default is @math{10^{-5}}. @item @var{iter_max} Maximum number of iterations (@code{@var{iter_max}>0}. The function aborts if convergenge is not reached within the maximum number of iterations. Default is 100. @end table @strong{OUTPUTS} @table @code @item @var{U}(c,k) If @math{k} is a FCFS, LCFS-PR or PS node, then @code{@var{U}(c,k)} is the utilization of class @math{c} requests on service center @math{k}. If @math{k} is an IS node, then @code{@var{U}(c,k)} is the class @math{c} @emph{traffic intensity} at device @math{k}, defined as @code{@var{U}(c,k) = @var{X}(c)*@var{S}(c,k)} @item @var{R}(c,k) response time of class @math{c} requests at service center @math{k}. @item @var{Q}(c,k) average number of class @math{c} requests at service center @math{k}. @item @var{X}(c,k) class @math{c} throughput at service center @math{k}. @end table @strong{REFERENCES} @itemize @item Y. Bard, @cite{Some Extensions to Multiclass Queueing Network Analysis}, proc. 4th Int. Symp. on Modelling and Performance Evaluation of Computer Systems, Feb 1979, pp. 51--62. @item P. Schweitzer, @cite{Approximate Analysis of Multiclass Closed Networks of Queues}, Proc. Int. Conf. on Stochastic Control and Optimization, jun 1979, pp. 25--29. @end itemize This implementation is based on Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer System Analysis Using Queueing Network Models}, Prentice Hall, 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In particular, see section 7.4.2.2 ("Approximate Solution Techniques"). This implementation is slightly different from the one described above, as it computes the average response times @math{R} instead of the residence times. @xseealso{qncmmva} @end deftypefn @c @c Mixed networks @c @subsection Mixed Networks @c @c MVA for mixed networks @c @anchor{doc-qnmix} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmix (@var{lambda}, @var{N}, @var{S}, @var{V}, @var{m}) @cindex Mean Value Analysys (MVA) @cindex mixed network Mean Value Analysis for mixed queueing networks. The network consists of @math{K} service centers (single-server or delay centers) and @math{C} independent customer chains. Both open and closed chains are possible. @var{lambda} is the vector of per-chain arrival rates (open classes); @var{N} is the vector of populations for closed chains. Class switching is @strong{not} allowed. Each customer class @emph{must} correspond to an independent chain. If the network is made of open or closed classes only, then this function calls @code{qnom} or @code{qncmmva} respectively, and prints a warning message. @strong{INPUTS} @table @code @item @var{lambda}(c) @itemx @var{N}(c) For each customer chain @math{c}: @itemize @item if @math{c} is a closed chain, then @code{@var{N}(c)>0} is the number of class @math{c} requests and @code{@var{lambda}(c)} must be zero; @item If @math{c} is an open chain, @code{@var{lambda}(c)>0} is the arrival rate of class @math{c} requests and @code{@var{N}(c)} must be zero; @end itemize @noindent In other words, for each class @math{c} the following must hold: @example (@var{lambda}(c)>0 && @var{N}(c)==0) || (@var{lambda}(c)==0 && @var{N}(c)>0) @end example @item @var{S}(c,k) mean class @math{c} service time at center @math{k}, @code{@var{S}(c,k) @geq{} 0}. For FCFS nodes, service times must be class-independent. @item @var{V}(c,k) average number of visits of class @math{c} customers to center @math{k} (@code{@var{V}(c,k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k}. Only single-server (@code{@var{m}(k)==1}) or IS (Infinite Server) nodes (@code{@var{m}(k)<1}) are supported. If omitted, each center is assumed to be of type @math{M/M/1}-FCFS. Queueing discipline for single-server nodes can be FCFS, PS or LCFS-PR. @end table @strong{OUTPUTS} @table @code @item @var{U}(c,k) class @math{c} utilization at center @math{k}. @item @var{R}(c,k) class @math{c} response time at center @math{k}. @item @var{Q}(c,k) average number of class @math{c} requests at center @math{k}. @item @var{X}(c,k) class @math{c} throughput at center @math{k}. @end table @strong{REFERENCES} @itemize @item Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer System Analysis Using Queueing Network Models}, Prentice Hall, 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In particular, see section 7.4.3 ("Mixed Model Solution Techniques"). Note that in this function we compute the mean response time @math{R} instead of the mean residence time as in the reference. @item Herb Schwetman, @cite{Implementing the Mean Value Algorithm for the Solution of Queueing Network Models}, Technical Report @uref{http://docs.lib.purdue.edu/cstech/286/, CSD-TR-355}, Department of Computer Sciences, Purdue University, revised Feb 15, 1982. @end itemize @xseealso{qncmmva, qncm} @end deftypefn @c @c @c @node Generic Algorithms @section Generic Algorithms The @code{queueing} package provides a high-level function @command{qnsolve} for analyzing QN models. @command{qnsolve} takes as input a high-level description of the queueing model, and delegates the actual solution of the model to one of the lower-level function. @command{qnsolve} supports single or multiclass models, but at the moment only product-form networks can be analyzed. For non product-form networks @xref{Non Product-Form QNs}. @command{qnsolve} accepts two input parameters. The first one is the list of nodes, encoded as an Octave @emph{cell array}. The second parameter is the vector of visit ratios @var{V}, which can be either a vector (for single-class models) or a two-dimensional matrix (for multiple-class models). Individual nodes in the network are structures build using the @command{qnmknode} function. @anchor{doc-qnmknode} @deftypefn {Function File} {@var{Q} =} qnmknode (@var{"m/m/m-fcfs"}, @var{S}) @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"m/m/m-fcfs"}, @var{S}, @var{m}) @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"m/m/1-lcfs-pr"}, @var{S}) @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/1-ps"}, @var{S}) @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/1-ps"}, @var{S}, @var{s2}) @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/inf"}, @var{S}) @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/inf"}, @var{S}, @var{s2}) Creates a node; this function can be used together with @code{qnsolve}. It is possible to create either single-class nodes (where there is only one customer class), or multiple-class nodes (where the service time is given per-class). Furthermore, it is possible to specify load-dependent service times. String literals are case-insensitive, so for example @var{"-/g/inf"}, @var{"-/G/inf"} and @var{"-/g/INF"} are all equivalent. @strong{INPUTS} @table @code @item @var{S} Mean service time. @itemize @item If @math{S} is a scalar, it is assumed to be a load-independent, class-independent service time. @item If @math{S} is a column vector, then @code{@var{S}(c)} is assumed to the the load-independent service time for class @math{c} customers. @item If @math{S} is a row vector, then @code{@var{S}(n)} is assumed to be the class-independent service time at the node, when there are @math{n} requests. @item Finally, if @var{S} is a two-dimensional matrix, then @code{@var{S}(c,n)} is assumed to be the class @math{c} service time when there are @math{n} requests at the node. @end itemize @item @var{m} Number of identical servers at the node. Default is @code{@var{m}=1}. @item @var{s2} Squared coefficient of variation for the service time. Default is 1.0. @end table The returned struct @var{Q} should be considered opaque to the client. @c The returned struct @var{Q} has the following fields: @c @table @var @c @item Q.node @c (String) type of the node; valid values are @code{"m/m/m-fcfs"}, @c @code{"-/g/1-lcfs-pr"}, @code{"-/g/1-ps"} (Processor-Sharing) @c and @code{"-/g/inf"} (Infinite Server, or delay center). @c @item Q.S @c Average service time. If @code{@var{Q}.S} is a vector, then @c @code{@var{Q}.S(i)} is the average service time at that node @c if there are @math{i} requests. @c @item Q.m @c Number of identical servers at a @code{"m/m/m-fcfs"}. Default is 1. @c @item Q.c @c Number of customer classes. Default is 1. @c @end table @xseealso{qnsolve} @end deftypefn After the network has been defined, it is possible to solve it using @command{qnsolve}. @anchor{doc-qnsolve} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"closed"}, @var{N}, @var{QQ}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"closed"}, @var{N}, @var{QQ}, @var{V}, @var{Z}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"open"}, @var{lambda}, @var{QQ}, @var{V}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"mixed"}, @var{lambda}, @var{N}, @var{QQ}, @var{V}) High-level function for analyzing QN models. @itemize @item For @strong{closed} networks, the following server types are supported: @math{M/M/m}--FCFS, @math{-/G/\infty}, @math{-/G/1}--LCFS-PR, @math{-/G/1}--PS and load-dependent variants. @item For @strong{open} networks, the following server types are supported: @math{M/M/m}--FCFS, @math{-/G/\infty} and @math{-/G/1}--PS. General load-dependent nodes are @emph{not} supported. Multiclass open networks do not support multiple server @math{M/M/m} nodes, but only single server @math{M/M/1}--FCFS. @item For @strong{mixed} networks, the following server types are supported: @math{M/M/1}--FCFS, @math{-/G/\infty} and @math{-/G/1}--PS. General load-dependent nodes are @emph{not} supported. @end itemize @strong{INPUTS} @table @code @item @var{N} @itemx @var{N}(c) Number of requests in the system for closed networks. For single-class networks, @var{N} must be a scalar. For multiclass networks, @code{@var{N}(c)} is the population size of closed class @math{c}. @item @var{lambda} @itemx @var{lambda}(c) External arrival rate (scalar) for open networks. For single-class networks, @var{lambda} must be a scalar. For multiclass networks, @code{@var{lambda}(c)} is the class @math{c} overall arrival rate. @item @var{QQ}@{i@} List of queues in the network. This must be a cell array with @math{N} elements, such that @code{@var{QQ}@{i@}} is a struct produced by the @code{qnmknode} function. @item @var{Z} External delay ("think time") for closed networks. Default 0. @end table @strong{OUTPUTS} @table @code @item @var{U}(k) If @math{k} is a FCFS node, then @code{@var{U}(k)} is the utilization of service center @math{k}. If @math{k} is an IS node, then @code{@var{U}(k)} is the @emph{traffic intensity} defined as @code{@var{X}(k)*@var{S}(k)}. @item @var{R}(k) average response time of service center @math{k}. @item @var{Q}(k) average number of customers in service center @math{k}. @item @var{X}(k) throughput of service center @math{k}. @end table Note that for multiclass networks, the computed results are per-class utilization, response time, number of customers and throughput: @code{@var{U}(c,k)}, @code{@var{R}(c,k)}, @code{@var{Q}(c,k)}, @code{@var{X}(c,k)}. String literals are case-insensitive, so @var{"closed"}, @var{"Closed"} and @var{"CLoSEd"} are all equivalent. @end deftypefn @noindent @strong{EXAMPLE} Let us consider a closed, multiclass network with @math{C=2} classes and @math{K=3} service center. Let the population be @math{M=(2, 1)} (class 1 has 2 requests, and class 2 has 1 request). The nodes are as follows: @itemize @item Node 1 is a @math{M/M/1}--FCFS node, with load-dependent service times. Service times are class-independent, and are defined by the matrix @code{[0.2 0.1 0.1; 0.2 0.1 0.1]}. Thus, @code{@var{S}(1,2) = 0.2} means that service time for class 1 customers where there are 2 requests in 0.2. Note that service times are class-independent; @item Node 2 is a @math{-/G/1}--PS node, with service times @math{S_{1, 2} = 0.4} for class 1, and @math{S_{2, 2} = 0.6} for class 2 requests; @item Node 3 is a @math{-/G/\infty} node (delay center), with service times @math{S_{1, 3}=1} and @math{S_{2, 3}=2} for class 1 and 2 respectively. @end itemize After defining the per-class visit count @var{V} such that @code{@var{V}(c,k)} is the visit count of class @math{c} requests to service center @math{k}. We can define and solve the model as follows: @example @verbatim QQ = { qnmknode( "m/m/m-fcfs", [0.2 0.1 0.1; 0.2 0.1 0.1] ), ... qnmknode( "-/g/1-ps", [0.4; 0.6] ), ... qnmknode( "-/g/inf", [1; 2] ) }; V = [ 1 0.6 0.4; ... 1 0.3 0.7 ]; N = [ 2 1 ]; [U R Q X] = qnsolve( "closed", N, QQ, V ); @end verbatim @end example @anchor{doc-qnclosed} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosed (@var{N}, @var{S}, @var{V}, @dots{}) @cindex closed network, single class @cindex closed network, multiple classes This function computes steady-state performance measures of closed queueing networks using the Mean Value Analysis (MVA) algorithm. The qneneing network is allowed to contain fixed-capacity centers, delay centers or general load-dependent centers. Multiple request classes are supported. This function dispatches the computation to one of @code{qncsemva}, @code{qncsmvald} or @code{qncmmva}. @itemize @item If @var{N} is a scalar, the network is assumed to have a single class of requests; in this case, the exact MVA algorithm is used to analyze the network. If @var{S} is a vector, then @code{@var{S}(k)} is the average service time of center @math{k}, and this function calls @code{qncsmva} which supports load-independent service centers. If @var{S} is a matrix, @code{@var{S}(k,i)} is the average service time at center @math{k} when @math{i=1, @dots{}, N} jobs are present; in this case, the network is analyzed with the @code{qncmmvald} function. @item If @var{N} is a vector, the network is assumed to have multiple classes of requests, and is analyzed using the exact multiclass MVA algorithm as implemented in the @code{qncmmva} function. @end itemize @xseealso{qncsmva, qncsmvald, qncmmva} @end deftypefn @noindent @strong{EXAMPLE} @example @verbatim P = [0 0.3 0.7; 1 0 0; 1 0 0]; # Transition probability matrix S = [1 0.6 0.2]; # Average service times m = ones(size(S)); # All centers are single-server Z = 2; # External delay N = 15; # Maximum population to consider V = qncsvisits(P); # Compute number of visits X_bsb_lower = X_bsb_upper = X_ab_lower = X_ab_upper = X_mva = zeros(1,N); for n=1:N [X_bsb_lower(n) X_bsb_upper(n)] = qncsbsb(n, S, V, m, Z); [X_ab_lower(n) X_ab_upper(n)] = qncsaba(n, S, V, m, Z); [U R Q X] = qnclosed( n, S, V, m, Z ); X_mva(n) = X(1)/V(1); endfor close all; plot(1:N, X_ab_lower,"g;Asymptotic Bounds;", ... 1:N, X_bsb_lower,"k;Balanced System Bounds;", ... 1:N, X_mva,"b;MVA;", "linewidth", 2, ... 1:N, X_bsb_upper,"k", 1:N, X_ab_upper,"g" ); axis([1,N,0,1]); legend("location","southeast"); legend("boxoff"); xlabel("Number of Requests n"); ylabel("System Throughput X(n)"); @end verbatim @end example @anchor{doc-qnopen} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopen (@var{lambda}, @var{S}, @var{V}, @dots{}) @cindex open network Compute utilization, response time, average number of requests in the system, and throughput for open queueing networks. If @var{lambda} is a scalar, the network is considered a single-class QN and is solved using @code{qnopensingle}. If @var{lambda} is a vector, the network is considered as a multiclass QN and solved using @code{qnopenmulti}. @xseealso{qnos, qnom} @end deftypefn @c @c @c @node Bounds Analysis @section Bounds Analysis @c @anchor{doc-qnosaba} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosaba (@var{lambda}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosaba (@var{lambda}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosaba (@var{lambda}, @var{S}, @var{V}, @var{m}) @cindex bounds, asymptotic @cindex open network Compute Asymptotic Bounds for open, single-class networks with @math{K} service centers. @strong{INPUTS} @table @code @item @var{lambda} Arrival rate of requests (scalar, @code{@var{lambda} @geq{} 0}). @item @var{D}(k) service demand at center @math{k}. (vector of length @math{K}, @code{@var{D}(k) @geq{} 0}). @item @var{S}(k) mean service time at center @math{k}. (vector of length @math{K}, @code{@var{S}(k) @geq{} 0}). @item @var{V}(k) mean number of visits to center @math{k}. (vector of length @math{K}, @code{@var{V}(k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k}. This function only supports @math{M/M/1} queues, therefore @var{m} must be @code{ones(size(S))}. @end table @strong{OUTPUTS} @table @code @item @var{Xl} @item @var{Xu} Lower and upper bounds on the system throughput. @var{Xl} is always set to @math{0} since there can be no lower bound on the throughput of open networks (scalar). @item @var{Rl} @item @var{Ru} Lower and upper bounds on the system response time. @var{Ru} is always set to @code{+inf} since there can be no upper bound on the throughput of open networks (scalar). @end table @xseealso{qnomaba} @end deftypefn @c @anchor{doc-qnomaba} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnomaba (@var{lambda}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Rl}] =} qnomaba (@var{lambda}, @var{S}, @var{V}) @cindex bounds, asymptotic @cindex open network @cindex multiclass network, open Compute Asymptotic Bounds for open, multiclass networks with @math{K} service centers and @math{C} customer classes. @strong{INPUTS} @table @code @item @var{lambda}(c) class @math{c} arrival rate to the system (vector of length @math{C}, @code{@var{lambda}(c) > 0}). @item @var{D}(c, k) class @math{c} service demand at center @math{k} (@math{C \times K} matrix, @code{@var{D}(c, k) @geq{} 0}). @item @var{S}(c, k) mean service time of class @math{c} requests at center @math{k} (@math{C \times K} matrix, @code{@var{S}(c, k) @geq{} 0}). @item @var{V}(c, k) mean number of visits of class @math{c} requests at center @math{k} (@math{C \times K} matrix, @code{@var{V}(c, k) @geq{} 0}). @end table @strong{OUTPUTS} @table @code @item @var{Xl}(c) @item @var{Xu}(c) lower and upper bounds of class @math{c} throughput. @code{@var{Xl}(c)} is always @math{0} since there can be no lower bound on the throughput of open networks (vector of length @math{C}). @item @var{Rl}(c) @item @var{Ru}(c) lower and upper bounds of class @math{c} response time. @code{@var{Ru}(c)} is always @code{+inf} since there can be no upper bound on the response time of open networks (vector of length @math{C}). @end table @end deftypefn @c @anchor{doc-qncsaba} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsaba (@var{N}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsaba (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsaba (@var{N}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsaba (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) @cindex bounds, asymptotic @cindex asymptotic bounds @cindex closed network, single class Compute Asymptotic Bounds for the system throughput and response time of closed, single-class networks with @math{K} service centers. Single-server and infinite-server nodes are supported. Multiple-server nodes and general load-dependent servers are not supported. @strong{INPUTS} @table @code @item @var{N} number of requests in the system (scalar, @code{@var{N}>0}). @item @var{D}(k) service demand at center @math{k} (@code{@var{D}(k) @geq{} 0}). @item @var{S}(k) mean service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). @item @var{V}(k) average number of visits to center @math{k} (@code{@var{V}(k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k} (if @var{m} is a scalar, all centers have that number of servers). If @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); if @code{@var{m}(k) = 1}, center @math{k} is a M/M/1-FCFS server. This function does not support multiple-server nodes. Default is 1. @item @var{Z} External delay (scalar, @code{@var{Z} @geq{} 0}). Default is 0. @end table @strong{OUTPUTS} @table @code @item @var{Xl} @itemx @var{Xu} Lower and upper bounds on the system throughput. @item @var{Rl} @itemx @var{Ru} Lower and upper bounds on the system response time. @end table @xseealso{qncmaba} @end deftypefn @c @anchor{doc-qncmaba} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmaba (@var{N}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmaba (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmaba (@var{N}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmaba (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) @cindex bounds, asymptotic @cindex asymptotic bounds @cindex closed network @cindex multiclass network, closed @cindex closed multiclass network Compute Asymptotic Bounds for closed, multiclass networks with @math{K} service centers and @math{C} customer classes. Single-server and infinite-server nodes are supported. Multiple-server nodes and general load-dependent servers are not supported. @strong{INPUTS} @table @code @item @var{N}(c) number of class @math{c} requests in the system (vector of length @math{C}, @code{@var{N}(c) @geq{} 0}). @item @var{D}(c, k) class @math{c} service demand at center @math{k} (@math{C \times K} matrix, @code{@var{D}(c,k) @geq{} 0}). @item @var{S}(c, k) mean service time of class @math{c} requests at center @math{k} (@math{C \times K} matrix, @code{@var{S}(c,k) @geq{} 0}). @item @var{V}(c,k) average number of visits of class @math{c} requests to center @math{k} (@math{C \times K} matrix, @code{@var{V}(c,k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k} (if @var{m} is a scalar, all centers have that number of servers). If @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); if @code{@var{m}(k) = 1}, center @math{k} is a M/M/1-FCFS server. This function does not support multiple-server nodes. Default is 1. @item @var{Z}(c) class @math{c} external delay (vector of length @math{C}, @code{@var{Z}(c) @geq{} 0}). Default is 0. @end table @strong{OUTPUTS} @table @code @item @var{Xl}(c) @itemx @var{Xu}(c) Lower and upper bounds for class @math{c} throughput. @item @var{Rl}(c) @itemx @var{Ru}(c) Lower and upper bounds for class @math{c} response time. @end table @strong{REFERENCES} @itemize @item Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer System Analysis Using Queueing Network Models}, Prentice Hall, 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In particular, see section 5.2 ("Asymptotic Bounds"). @end itemize @xseealso{qncsaba} @end deftypefn @c @anchor{doc-qnosbsb} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosbsb (@var{lambda}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosbsb (@var{lambda}, @var{S}, @var{V}) @cindex bounds, balanced system @cindex open network Compute Balanced System Bounds for single-class, open networks with @math{K} service centers. @strong{INPUTS} @table @code @item @var{lambda} overall arrival rate to the system (scalar, @code{@var{lambda} @geq{} 0}). @item @var{D}(k) service demand at center @math{k} (@code{@var{D}(k) @geq{} 0}). @item @var{S}(k) service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). @item @var{V}(k) mean number of visits at center @math{k} (@code{@var{V}(k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k}. This function only supports @math{M/M/1} queues, therefore @var{m} must be @code{ones(size(S))}. @end table @strong{OUTPUTS} @table @code @item @var{Xl} @item @var{Xu} Lower and upper bounds on the system throughput. @var{Xl} is always set to @math{0}, since there can be no lower bound on open networks throughput. @item @var{Rl} @itemx @var{Ru} Lower and upper bounds on the system response time. @end table @xseealso{qnosaba} @end deftypefn @c @anchor{doc-qncsbsb} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsbsb (@var{N}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsbsb (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsbsb (@var{N}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsbsb (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) @cindex bounds, balanced system @cindex closed network, single class @cindex balanced system bounds Compute Balanced System Bounds on system throughput and response time for closed, single-class networks with @math{K} service centers. @strong{INPUTS} @table @code @item @var{N} number of requests in the system (scalar, @code{@var{N} @geq{} 0}). @item @var{D}(k) service demand at center @math{k} (@code{@var{D}(k) @geq{} 0}). @item @var{S}(k) mean service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). @item @var{V}(k) average number of visits to center @math{k} (@code{@var{V}(k) @geq{} 0}). Default is 1. @item @var{m}(k) number of servers at center @math{k}. This function supports @code{@var{m}(k) = 1} only (single-eserver FCFS nodes); this parameter is only for compatibility with @code{qncsaba}. Default is 1. @item @var{Z} External delay (@code{@var{Z} @geq{} 0}). Default is 0. @end table @strong{OUTPUTS} @table @code @item @var{Xl} @itemx @var{Xu} Lower and upper bound on the system throughput. @item @var{Rl} @itemx @var{Ru} Lower and upper bound on the system response time. @end table @strong{REFERENCES} @itemize @item Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer System Analysis Using Queueing Network Models}, Prentice Hall, 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In particular, see section 5.4 ("Balanced Systems Bounds"). @end itemize @xseealso{qncmbsb} @end deftypefn @c @anchor{doc-qncmbsb} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmbsb (@var{N}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmbsb (@var{N}, @var{S}, @var{V}) @cindex bounds, balanced system @cindex balanced system bounds @cindex multiclass network, closed @cindex closed multiclass network Compute Balanced System Bounds for closed, multiclass networks with @math{K} service centers and @math{C} customer classes. Only single-server nodes are supported. @strong{INPUTS} @table @code @item @var{N}(c) number of class @math{c} requests in the system (vector of length @math{C}). @item @var{D}(c, k) class @math{c} service demand at center @math{k} (@math{C \times K} matrix, @code{@var{D}(c,k) @geq{} 0}). @item @var{S}(c, k) mean service time of class @math{c} requests at center @math{k} (@math{C \times K} matrix, @code{@var{S}(c,k) @geq{} 0}). @item @var{V}(c,k) average number of visits of class @math{c} requests to center @math{k} (@math{C \times K} matrix, @code{@var{V}(c,k) @geq{} 0}). @end table @strong{OUTPUTS} @table @code @item @var{Xl}(c) @itemx @var{Xu}(c) Lower and upper class @math{c} throughput bounds (vector of length @math{C}). @item @var{Rl}(c) @itemx @var{Ru}(c) Lower and upper class @math{c} response time bounds (vector of length @math{C}). @end table @xseealso{qncsbsb} @end deftypefn @c @anchor{doc-qncmcb} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmcb (@var{N}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmcb (@var{N}, @var{S}, @var{V}) @cindex multiclass network, closed @cindex closed multiclass network @cindex bounds, composite @cindex composite bounds Compute Composite Bounds (CB) on system throughput and response time for closed multiclass networks. @strong{INPUTS} @table @code @item @var{N}(c) number of class @math{c} requests in the system. @item @var{D}(c, k) class @math{c} service demand at center @math{k} (@code{@var{S}(c,k) @geq{} 0}). @item @var{S}(c, k) mean service time of class @math{c} requests at center @math{k} (@code{@var{S}(c,k) @geq{} 0}). @item @var{V}(c,k) average number of visits of class @math{c} requests to center @math{k} (@code{@var{V}(c,k) @geq{} 0}). @end table @strong{OUTPUTS} @table @code @item @var{Xl}(c) @itemx @var{Xu}(c) Lower and upper bounds on class @math{c} throughput. @item @var{Rl}(c) @itemx @var{Ru}(c) Lower and upper bounds on class @math{c} response time. @end table @strong{REFERENCES} @itemize @item Teemu Kerola, @cite{The Composite Bound Method (CBM) for Computing Throughput Bounds in Multiple Class Environments}, Performance Evaluation Vol. 6, Issue 1, March 1986, DOI @uref{http://dx.doi.org/10.1016/0166-5316(86)90002-7, 10.1016/0166-5316(86)90002-7}. Also available as @uref{http://docs.lib.purdue.edu/cstech/395/, Technical Report CSD-TR-475}, Department of Computer Sciences, Purdue University, mar 13, 1984 (Revised Aug 27, 1984). @end itemize @end deftypefn @c @anchor{doc-qncspb} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncspb (@var{N}, @var{D} ) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncspb (@var{N}, @var{S}, @var{V} ) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncspb (@var{N}, @var{S}, @var{V}, @var{m} ) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncspb (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z} ) @cindex bounds, PB @cindex PB bounds @cindex closed network, single class Compute PB Bounds (C. H. Hsieh and S. Lam, 1987) for single-class, closed networks with @math{K} service centers. @strong{INPUTS} @table @code @item @var{} number of requests in the system (scalar, @code{@var{N} > 0}). @item @var{D}(k) service demand of service center @math{k} (@code{@var{D}(k) @geq{} 0}). @item @var{S}(k) mean service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). @item @var{V}(k) visit ratio to center @math{k} (@code{@var{V}(k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k}. This function only supports @math{M/M/1} queues, therefore @var{m} must be @code{ones(size(S))}. @item @var{Z} external delay (think time, @code{@var{Z} @geq{} 0}). Default 0. @end table @strong{OUTPUTS} @table @code @item @var{Xl} @itemx @var{Xu} Lower and upper bounds on the system throughput. @item @var{Rl} @itemx @var{Ru} Lower and upper bounds on the system response time. @end table @strong{REFERENCES} @itemize @item C. H. Hsieh and S. Lam, @cite{Two classes of performance bounds for closed queueing networks}, Performance Evaluation, Vol. 7 Issue 1, pp. 3--30, February 1987, DOI @uref{http://dx.doi.org/10.1016/0166-5316(87)90054-X, 10.1016/0166-5316(87)90054-X}. Also available as @uref{ftp://ftp.cs.utexas.edu/pub/techreports/tr85-09.pdf, Technical Report TR-85-09}, Department of Computer Science, University of Texas at Austin, June 1985 @end itemize This function implements the non-iterative variant described in G. Casale, R. R. Muntz, G. Serazzi, @cite{Geometric Bounds: a Non-Iterative Analysis Technique for Closed Queueing Networks}, IEEE Transactions on Computers, 57(6):780-794, June 2008. @xseealso{qncsaba, qbcsbsb, qncsgb} @end deftypefn @c @anchor{doc-qncsgb} @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}, @var{Ql}, @var{Qu}] =} qncsgb (@var{N}, @var{D}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}, @var{Ql}, @var{Qu}] =} qncsgb (@var{N}, @var{S}, @var{V}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}, @var{Ql}, @var{Qu}] =} qncsgb (@var{N}, @var{S}, @var{V}, @var{m}) @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}, @var{Ql}, @var{Qu}] =} qncsgb (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) @cindex bounds, geometric @cindex geometric bounds @cindex closed network Compute Geometric Bounds (GB) on system throughput, system response time and server queue lenghts for closed, single-class networks with @math{K} service centers and @math{N} requests. @strong{INPUTS} @table @code @item @var{N} number of requests in the system (scalar, @code{@var{N} > 0}). @item @var{D}(k) service demand of service center @math{k} (vector of length @math{K}, @code{@var{D}(k) @geq{} 0}). @item @var{S}(k) mean service time at center @math{k} (vector of length @math{K}, @code{@var{S}(k) @geq{} 0}). @item @var{V}(k) visit ratio to center @math{k} (vector of length @math{K}, @code{@var{V}(k) @geq{} 0}). @item @var{m}(k) number of servers at center @math{k}. This function only supports @math{M/M/1} queues, therefore @var{m} must be @code{ones(size(S))}. @item @var{Z} external delay (think time, @code{@var{Z} @geq{} 0}, scalar). Default is 0. @end table @strong{OUTPUTS} @table @code @item @var{Xl} @itemx @var{Xu} Lower and upper bound on the system throughput. If @code{@var{Z}>0}, these bounds are computed using @emph{Geometric Square-root Bounds} (GSB). If @code{@var{Z}==0}, these bounds are computed using @emph{Geometric Bounds} (GB) @item @var{Rl} @itemx @var{Ru} Lower and upper bound on the system response time. These bounds are derived from @var{Xl} and @var{Xu} using Little's Law: @code{@var{Rl} = @var{N} / @var{Xu} - @var{Z}}, @code{@var{Ru} = @var{N} / @var{Xl} - @var{Z}} @item @var{Ql}(k) @itemx @var{Qu}(k) lower and upper bounds of center @math{K} queue length. @end table @strong{REFERENCES} @itemize @item G. Casale, R. R. Muntz, G. Serazzi, @cite{Geometric Bounds: a Non-Iterative Analysis Technique for Closed Queueing Networks}, IEEE Transactions on Computers, 57(6):780-794, June 2008. @uref{http://doi.ieeecomputersociety.org/10.1109/TC.2008.37, 10.1109/TC.2008.37} @end itemize In this implementation we set @math{X^+} and @math{X^-} as the upper and lower Asymptotic Bounds as computed by the @command{qncsab} function, respectively. @end deftypefn @c @c Examples @c @node QN Analysis Examples @section QN Analysis Examples In this section we illustrate with a few examples how the @code{queueing} package can be used to analyze queueing network models. Further examples can be found in the functions demo blocks, and can be inspected with the @code{demo @emph{function}} Octave command. @subsection Closed, Single Class Network Let us consider again the network shown in @ref{fig:qn_closed_single}. We denote with @math{S_k} the average service time at center @math{k}, @math{k=1, 2, 3}. Let the service times be @math{S_1 = 1.0}, @math{S_2 = 2.0} and @math{S_3 = 0.8}. The routing of jobs within the network is described with a @emph{routing probability matrix} @math{\bf P}: a request completing service at center @math{i} is enqueued at center @math{j} with probability @math{P_{i, j}}. We use the following routing matrix: @iftex @tex $$ {\bf P} = \pmatrix{ 0 & 0.3 & 0.7 \cr 1 & 0 & 0 \cr 1 & 0 & 0 } $$ @end tex @end iftex @ifnottex @example / 0 0.3 0.7 \ P = | 1 0 0 | \ 1 0 0 / @end example @end ifnottex The network above can be analyzed with the @command{qnclosed} function @pxref{doc-qnclosed}. @command{qnclosed} requires the following parameters: @table @var @item N Number of requests in the network (since we are considering a closed network, the number of requests is fixed) @item S Array of average service times at the centers: @code{@var{S}(k)} is the average service time at center @math{k}. @item V Array of visit ratios: @code{@var{V}(k)} is the average number of visits to center @math{k}. @end table We can compute @math{V_k} from the routing probability matrix @math{P_{i, j}} using the @command{qncsvisits} function @pxref{doc-qncsvisits}. Therefore, we can analyze the network for a given population size @math{N} (e.g., @math{N=10}) as follows: @example @group @kbd{N = 10;} @kbd{S = [1 2 0.8];} @kbd{P = [0 0.3 0.7; 1 0 0; 1 0 0];} @kbd{V = qncsvisits(P);} @kbd{[U R Q X] = qnclosed( N, S, V )} @result{} U = 0.99139 0.59483 0.55518 @result{} R = 7.4360 4.7531 1.7500 @result{} Q = 7.3719 1.4136 1.2144 @result{} X = 0.99139 0.29742 0.69397 @end group @end example The output of @command{qnclosed} includes the vectors of utilizations @math{U_k} at center @math{k}, response time @math{R_k}, average number of customers @math{Q_k} and throughput @math{X_k}. In our example, the throughput of center 1 is @math{X_1 = 0.99139}, and the average number of requests in center 3 is @math{Q_3 = 1.2144}. The utilization of center 1 is @math{U_1 = 0.99139}, which is the highest among the service centers. Thus, center 1 is the @emph{bottleneck device}. This network can also be analyzed with the @command{qnsolve} function @pxref{doc-qnsolve}. @command{qnsolve} can handle open, closed or mixed networks, and allows the network to be described in a very flexible way. First, let @var{Q1}, @var{Q2} and @var{Q3} be the variables describing the service centers. Each variable is instantiated with the @command{qnmknode} function. @example @group @kbd{Q1 = qnmknode( "m/m/m-fcfs", 1 );} @kbd{Q2 = qnmknode( "m/m/m-fcfs", 2 );} @kbd{Q3 = qnmknode( "m/m/m-fcfs", 0.8 );} @end group @end example The first parameter of @command{qnmknode} is a string describing the type of the node; @code{"m/m/m-fcfs"} denotes a @math{M/M/m}--FCFS center (this parameter is case-insensitive). The second parameter gives the average service time. An optional third parameter can be used to specify the number @math{m} of service centers. If omitted, it is assumed @math{m=1} (single-server node). Now, the network can be analyzed as follows: @example @group @kbd{N = 10;} @kbd{V = [1 0.3 0.7];} @kbd{[U R Q X] = qnsolve( "closed", N, @{ Q1, Q2, Q3 @}, V )} @result{} U = 0.99139 0.59483 0.55518 @result{} R = 7.4360 4.7531 1.7500 @result{} Q = 7.3719 1.4136 1.2144 @result{} X = 0.99139 0.29742 0.69397 @end group @end example @subsection Open, Single Class Network Let us consider an open network with @math{K=3} service centers and the following routing probabilities: @iftex @tex $$ {\bf P} = \pmatrix{ 0 & 0.3 & 0.5 \cr 1 & 0 & 0 \cr 1 & 0 & 0 } $$ @end tex @end iftex @ifnottex @example / 0 0.3 0.5 \ P = ! 1 0 0 | \ 1 0 0 / @end example @end ifnottex In this network, requests can leave the system from center 1 with probability @math{1-(0.3+0.5) = 0.2}. We suppose that external jobs arrive at center 1 with rate @math{\lambda_1 = 0.15}; there are no arrivals at centers 2 and 3. Similarly to closed networks, we first compute the visit counts @math{V_k} to center @math{k}, @math{k = 1, 2, 3}. We use the @command{qnosvisits} function as follows: @example @group @kbd{P = [0 0.3 0.5; 1 0 0; 1 0 0];} @kbd{lambda = [0.15 0 0];} @kbd{V = qnosvisits(P, lambda)} @result{} V = 5.00000 1.50000 2.50000 @end group @end example @noindent where @code{@var{lambda}(k)} is the arrival rate at center @math{k}, and @math{\bf P} is the routing matrix. Assuming the same service times as in the previous example, the network can be analyzed with the @command{qnopen} function @pxref{doc-qnopen}, as follows: @example @group @kbd{S = [1 2 0.8];} @kbd{[U R Q X] = qnopen( sum(lambda), S, V )} @result{} U = 0.75000 0.45000 0.30000 @result{} R = 4.0000 3.6364 1.1429 @result{} Q = 3.00000 0.81818 0.42857 @result{} X = 0.75000 0.22500 0.37500 @end group @end example The first parameter of the @command{qnopen} function is the (scalar) aggregate arrival rate. Again, it is possible to use the @command{qnsolve} high-level function: @example @group @kbd{Q1 = qnmknode( "m/m/m-fcfs", 1 );} @kbd{Q2 = qnmknode( "m/m/m-fcfs", 2 );} @kbd{Q3 = qnmknode( "m/m/m-fcfs", 0.8 );} @kbd{lambda = [0.15 0 0];} @kbd{[U R Q X] = qnsolve( "open", sum(lambda), @{ Q1, Q2, Q3 @}, V )} @result{} U = 0.75000 0.45000 0.30000 @result{} R = 4.0000 3.6364 1.1429 @result{} Q = 3.00000 0.81818 0.42857 @result{} X = 0.75000 0.22500 0.37500 @end group @end example @subsection Closed Multiclass Network/1 The following example is taken from Herb Schwetman, @cite{Implementing the Mean Value Algorithm for the Solution of Queueing Network Models}, Technical Report CSD-TR-355, Department of Computer Sciences, Purdue University, Feb 15, 1982. Let us consider the following multiclass QN with three servers and two classes @float Figure,fig:apl @center @image{qn_closed_multi_apl} @end float Servers 1 and 2 (labeled @emph{APL} and @emph{IMS}, respectively) are infinite server nodes; server 3 (labeled @emph{SYS}) is Processor Sharing (PS). Mean service times are given in the following table: @multitable @columnfractions .15 .15 .15 .15 @headitem @tab APL @tab IMS @tab SYS @item Class 1 @tab 1 @tab - @tab 0.025 @item Class 2 @tab - @tab 15 @tab 0.500 @end multitable There is no class switching. If we assume a population of 15 requests for class 1, and 5 requests for class 2, then the model can be analyzed as follows: @example @verbatim S = [1 0 .025; 0 15 .5]; P = zeros(2,3,2,3); P(1,1,1,3) = P(1,3,1,1) = 1; P(2,2,2,3) = P(2,3,2,2) = 1; V = qncmvisits(P,[3 3]); # reference station is station 3 N = [15 5]; m = [-1 -1 1]; [U R Q X] = qncmmva(N,S,V,m) @end verbatim @result{} U = 14.32312 0.00000 0.35808 0.00000 4.70699 0.15690 R = 1.00000 0.00000 0.04726 0.00000 15.00000 0.93374 Q = 14.32312 0.00000 0.67688 0.00000 4.70699 0.29301 X = 14.32312 0.00000 14.32312 0.00000 0.31380 0.31380 @end example @subsection Closed Multiclass Network/2 The following example is from M. Marzolla, @cite{The qnetworks Toolbox: A Software Package for Queueing Networks Analysis}, Technical Report @uref{https://www.moreno.marzolla.name/publications/papers/UBLCS-2010-04.pdf, UBLCS-2010-04}, Department of Computer Science, University of Bologna, Italy, February 2010. @float Figure,fig:web_model @center @image{qn_web_model,3in} @caption{Three-tier enterprise system model} @end float The model shown in @ref{fig:web_model} shows a three-tier enterprise system with @math{K=6} service centers. The first tier contains the @emph{Web server} (node 1), which is responsible for generating Web pages and transmitting them to clients. The application logic is implemented by nodes 2 and 3, and the storage tier is made of nodes 4--6.The system is subject to two workload classes, both represented as closed populations of @math{N_1} and @math{N_2} requests, respectively. Let @math{D_{c, k}} denote the service demand of class @math{c} requests at center @math{k}. We use the parameter values: @multitable @columnfractions .2 .33 .1 .1 @headitem Serv. no. @tab Name @tab Class 1 @tab Class 2 @item 1 @tab Web Server @tab 12 @tab 2 @item 2 @tab App. Server 1 @tab 14 @tab 20 @item 3 @tab App. Server 2 @tab 23 @tab 14 @item 4 @tab DB Server 1 @tab 20 @tab 90 @item 5 @tab DB Server 2 @tab 80 @tab 30 @item 6 @tab DB Server 3 @tab 31 @tab 33 @end multitable We set the total number of requests to 100, that is @math{N_1 + N_2 = N = 100}, and we study how different population mixes @math{(N_1, N_2)} affect the system throughput and response time. Let @math{0 < \beta_1 < 1} denote the fraction of class 1 requests: @math{N_1 = \beta_1 N}, @math{N_2 = (1-\beta_1)N}. The following Octave code defines the model for @math{\beta_1 = 0.1}: @example @group N = 100; # total population size beta1 = 0.1; # fraction of class 1 reqs. S = [12 14 23 20 80 31; ... 2 20 14 90 30 33 ]; V = ones(size(S)); pop = [fix(beta1*N) N-fix(beta1*N)]; [U R Q X] = qncmmva(pop, S, V); @end group @end example The @command{qncmmva(pop, S, V)} function invocation uses the multiclass MVA algorithm to compute per-class utilizations @math{U_{c, k}}, response times @math{R_{c,k}}, mean queue lengths @math{Q_{c,k}} and throughputs @math{X_{c,k}} at each service center @math{k}, given a population vector @var{pop}, mean service times @var{S} and visit ratios @var{V}. Since we are given the service demands @math{D_{c, k} = S_{c, k} V_{c,k}}, but function @command{qncmmva} requires separate service times and visit ratios, we set the service times equal to the demands, and all visit ratios equal to one. Overall class and system throughputs and response times can also be computed: @example @group X1 = X(1,1) / V(1,1) # class 1 throughput @result{} X1 = 0.0044219 X2 = X(2,1) / V(2,1) # class 2 throughput @result{} X2 = 0.010128 XX = X1 + X2 # system throughput @result{} XX = 0.014550 R1 = dot(R(1,:), V(1,:)) # class 1 resp. time @result{} R1 = 2261.5 R2 = dot(R(2,:), V(2,:)) # class 2 resp. time @result{} R2 = 8885.9 RR = N / XX # system resp. time @result{} RR = 6872.7 @end group @end example @code{dot(X,Y)} computes the dot product of two vectors. @code{R(1,:)} is the first row of matrix @var{R} and @code{V(1,:)} is the first row of matrix @var{V}, so @code{dot(R(1,:), V(1,:))} computes @math{\sum_k R_{1,k} V_{1,k}}. @float Figure,fig:web @center @image{web,5in} @caption{Throughput and Response Times as a function of the population mix} @end float We can also compute the system power @math{\Phi = X / R}, which defines how efficiently resources are being used: high values of @math{\Phi} denote the desirable situation of high throughput and low response time. @ref{fig:power} shows @math{\Phi} as a function of @math{\beta_1}. We observe a ``plateau'' of the global system power, corresponding to values of @math{\beta_1} which approximately lie between @math{0.3} and @math{0.7}. The per-class power exhibits an interesting (although not completely surprising) pattern, where the class with higher population exhibits worst efficiency as it produces higher contention on the resources. @float Figure,fig:power @center @image{power,5in} @caption{System Power as a function of the population mix} @end float @subsection Closed Multiclass Network/3 We now consider an example of multiclass network with class switching. The example is taken from @ref{Sch82}, and is shown in Figure @ref{fig:class_switching}. @float Figure,fig:class_switching @center @image{qn_closed_multi_cs,3in} @caption{Multiclass Model with Class Switching} @end float The system consists of three devices and two job classes. The CPU node is a PS server, while the two nodes labeled I/O are FCFS. Class 1 mean service time at the CPU is @math{0.01}; class 2 mean service time at the CPU is @math{0.05}. The mean service time at node 2 is @math{0.1}, and is class-independent. Similarly, the mean service time at node 3 is @math{0.07}. Jobs in class 1 leave the CPU and join class 2 with probability @math{0.1}; jobs of class 2 leave the CPU and join class 1 with probability @math{0.2}. There are @math{N=3} jobs, which are initially allocated to class 1. However, note that since class switching is allowed, the total number of jobs in each class does not remain constant; however the total number of jobs does. @example @verbatim C = 2; K = 3; S = [.01 .07 .10; ... .05 .07 .10 ]; P = zeros(C,K,C,K); P(1,1,1,2) = .7; P(1,1,1,3) = .2; P(1,1,2,1) = .1; P(2,1,2,2) = .3; P(2,1,2,3) = .5; P(2,1,1,1) = .2; P(1,2,1,1) = P(2,2,2,1) = 1; P(1,3,1,1) = P(2,3,2,1) = 1; N = [3 0]; [U R Q X] = qncmmva(N, S, P) @end verbatim @result{} U = 0.12609 0.61784 0.25218 0.31522 0.13239 0.31522 R = 0.014653 0.133148 0.163256 0.073266 0.133148 0.163256 Q = 0.18476 1.17519 0.41170 0.46190 0.25183 0.51462 X = 12.6089 8.8262 2.5218 6.3044 1.8913 3.1522 @end example queueing/doc/queueing.html0000664000175000017500000145650314620415626015563 0ustar morenomoreno queueing

queueing

Copyright © 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2018, 2020, 2024 Moreno Marzolla.

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.

Table of Contents

Next:   [Contents][Index]

This manual documents how to install and run the Queueing package. It corresponds to version 1.2.8 of the package.


Next: , Previous: , Up: Top   [Contents][Index]

1 Summary


1.1 About the Queueing Package

This document describes the queueing package for GNU Octave (queueing in short). The queueing package, previously known as qnetworks toolbox, is a collection of functions for analyzing queueing networks and Markov chains written for GNU Octave. Specifically, queueing contains functions for analyzing Jackson networks, open, closed or mixed product-form BCMP networks, and computing performance bounds. The following algorithms are available

  • Convolution for closed, single-class product-form networks with load-dependent service centers;
  • Exact and approximate Mean Value Analysis (MVA) for single and multiple class product-form closed networks;
  • MVA for mixed, multiple class product-form networks with load-independent service centers;
  • Approximate MVA for closed, single-class networks with blocking (MVABLO algorithm by F. Akyildiz);
  • Asymptotic Bounds, Balanced System Bounds and Geometric Bounds;

queueing provides functions for analyzing the following types of single-station queueing systems:

  • M/M/1
  • M/M/m
  • M/M/\infty
  • M/M/1/k single-server, finite capacity system
  • M/M/m/k multiple-server, finite capacity system
  • Asymmetric M/M/m
  • M/G/1 (general service time distribution)
  • M/H_m/1 (Hyperexponential service time distribution)

Functions for Markov chain analysis are also provided (discrete- and continuous-time chains are supported):

  • Birth-death processes;
  • Transient and stationary state occupancy probabilities;
  • Mean time to absorption;
  • Expected sojourn times and time-averaged sojourn times;
  • Mean first passage times;

The queueing package is distributed under the terms of the GNU General Public License (GPL), version 3 or later (see Copying). You are encouraged to share this software with others, and improve this package by contributing additional functions and reporting bugs. See Contributing Guidelines.

If you use the queueing package in a technical paper, please cite it as:

Moreno Marzolla, The qnetworks Toolbox: A Software Package for Queueing Networks Analysis. Khalid Al-Begain, Dieter Fiems and William J. Knottenbelt, Editors, Proceedings 17th International Conference on Analytical and Stochastic Modeling Techniques and Applications (ASMTA 2010) Cardiff, UK, June 14–16, 2010, volume 6148 of Lecture Notes in Computer Science, Springer, pp. 102–116, ISBN 978-3-642-13567-5

If you use BibTeX, this is the citation block:

@inproceedings{queueing,
  author    = {Moreno Marzolla},
  title     = {The qnetworks Toolbox: A Software Package for Queueing 
               Networks Analysis},
  booktitle = {Analytical and Stochastic Modeling Techniques and 
               Applications, 17th International Conference, 
               ASMTA 2010, Cardiff, UK, June 14-16, 2010. Proceedings},
  editor    = {Khalid Al-Begain and Dieter Fiems and William J. Knottenbelt},
  year      = {2010},
  publisher = {Springer},
  series    = {Lecture Notes in Computer Science},
  volume    = {6148},
  pages     = {102--116},
  ee        = {http://dx.doi.org/10.1007/978-3-642-13568-2_8},
  isbn      = {978-3-642-13567-5}
}

An early draft of the paper above is available as Technical Report UBLCS-2010-04, February 2010, Department of Computer Science, University of Bologna, Italy.


1.2 Contributing Guidelines

Contributions and bug reports are always welcome. If you want to contribute to the queueing package, here are some guidelines:

  • If you are contributing a new function, please embed proper documentation within the function itself. The documentation must be in texinfo format, so that it can be extracted and included into the printable manual. See the existing functions for the documentation style.
  • Make sure that each new function validates its input parameters. For example, a function accepting vectors should check whether the dimensions match.
  • Provide bibliographic references for each new algorithm you contribute. Document any significant difference from the reference. Update the doc/references.txi file if appropriate.
  • Include test and demo blocks. Test blocks are particularly important, since most algorithms are tricky to implement correctly. If appropriate, test blocks should also verify that the function fails on incorrect inputs.

Send your contribution to Moreno Marzolla (moreno.marzolla@unibo.it). If you are a user of this package and find it useful, let me know by dropping me a line. Thanks.


1.3 Acknowledgments

The following people (listed alphabetically) contributed to the queueing package, either by providing feedback, reporting bugs or contributing code: Philip Carinhas, Phil Colbourn, Diego Didona, Yves Durand, Marco Guazzone, Dmitry Kolesnikov, Michele Mazzucco, Marco Paolieri.


Next: , Previous: , Up: Top   [Contents][Index]

2 Installation and Getting Started


2.1 Installation through Octave package management system

The most recent version of queueing is 1.2.8 and can be downloaded from

https://gnu-octave.github.io/packages/queueing/

Additional information can be found at

https://www.moreno.marzolla.name/software/queueing/

To install queueing, follow these steps:

  1. If you have a recent version of GNU Octave and a network connection, you can install queueing from Octave command prompt using this command:
    octave:1> pkg install pkg install "https://github.com/mmarzolla/queueing/releases/download/1.2.8/queueing-1.2.8.tar.gz"
    

    The command above will download and install the latest version of the queueing package from the source repository, and install it on your machine.

    If you do not have root access, you can perform a local install with:

    octave:1> pkg install -local "https://github.com/mmarzolla/queueing/releases/download/1.2.8/queueing-1.2.8.tar.gz"
    

    This will install queueing in your home directory, and the package will be available to the current user only.

  2. Alternatively, you can first download the queueing tarball; to install the package in the system-wide location issue this command at the Octave prompt:
    octave:1> pkg install queueing-1.2.8.tar.gz
    

    (you may need to start Octave as root in order to allow the installation to copy the files to the target locations). After this, all functions will be available each time Octave starts, without the need to tweak the search path.

    If you do not have root access, you can do a local install using:

    octave:1> pkg install -local queueing-1.2.8.tar.gz
    
  3. Use the pkg list command at the Octave prompt to check that the queueing package has been succesfully installed; you should see something like:
    octave:1>pkg list queueing
    Package Name  | Version | Installation directory
    --------------+---------+-----------------------
        queueing  |   1.2.8 | /home/moreno/octave/queueing-1.2.8
    
  4. Starting from version 1.1.1, queueing is no longer automatically loaded on Octave start. To make the functions available for use, you need to issue the command
    octave:1>pkg load queueing
    

    at the Octave prompt. To automatically load queueing each time Octave starts, you can add the command above to the startup script (usually, ~/.octaverc on Unix systems).

  5. To completely remove queueing from your system, use the pkg uninstall command:
    octave:1> pkg uninstall queueing
    

2.2 Manual installation

If you want to manually install queueing in a custom location, you can download the tarball and unpack it somewhere:

tar xvfz queueing-1.2.8.tar.gz
cd queueing-1.2.8/

Copy all .m files from the inst/ directory to some target location. Then, start Octave with the -p option to add the target location to the search path, so that Octave will find all queueing functions automatically:

octave -p /path/to/queueing

For example, if all queueing m-files are in /usr/local/queueing, you can start Octave as follows:

octave -p /usr/local/queueing

If you want, you can add the following line to ~/.octaverc:

addpath("/path/to/queueing");

so that the path /path/to/queueing is automatically added to the search path each time Octave is started, and you no longer need to specify the -p option on the command line.


2.3 Development sources

The source code of the queueing package can be found in the Git repository at the URL:

https://github.com/mmarzolla/queueing

The source distribution contains additional development files that are not present in the installation tarball. This section briefly describes the content of the source tree. This is only relevant for developers who want to modify the code or the documentation.

The source distribution contains the following directories:

doc/

Documentation sources. Most of the documentation is extracted from the comment blocks of function files from the inst/ directory.

inst/

This directory contains the m-files which implement the various algorithms provided by queueing. As a notational convention, the names of functions for Queueing Networks begin with the ‘qn’ prefix; the name of functions for Continuous-Time Markov Chains (CTMCs) begin with the ‘ctmc’ prefix, and the names of functions for Discrete-Time Markov Chains (DTMCs) begin with the ‘dtmc’ prefix.

test/

This directory contains the scripts used to run all function tests.

devel/

This directory contains functions that are either not working properly, or need additional testing before they are moved to the inst/ directory.

The queueing package ships with a Makefile which can be used to produce the documentation (in PDF and HTML format), and automatically execute all tests. The following targets are defined:

all

Running ‘make’ (or ‘make all’) on the top-level directory builds the programs used to extract the documentation from the comments embedded in the m-files, and then produce the documentation in PDF and HTML format (doc/queueing.pdf and doc/queueing.html, respectively).

check

Running ‘make check’ will execute all tests contained in the m-files. If you modify the code of any function in the inst/ directory, you should run the tests to ensure that no errors have been introduced. You are also encouraged to contribute new tests, especially for functions that are not adequately validated.

clean
distclean
dist

The ‘make clean’, ‘make distclean’ and ‘make dist’ commands are used to clean up the source directory and prepare the distribution archive in compressed tar format.


2.4 Testing and Demos

The queueing package makes extensive use of test and demo blocks. These are GNU Octave features that allow tests and demos to be embedded within the source code of m-files. Multiple test blocks can be defined using the ‘%!test’ directive:

%!test
%! # test code
%!
%!test
%! # another test code

Test blocks rely on the assert built-in function to check che correctness of computation, e.g., by comparing the results with known “good” values or by cross-checking with other functions. The tests for a given function can be manually executed with the test command: for example, test("qsmm1") executes all tests in the script file qsmm1.m and prints a diagnostic message:

test("qsmm1");
-| PASSES 3 out of 3 tests

A quick way to run all tests for all functions in the queueing package is using the runtests built-in command at the GNU Octave prompt, passing as parameter the full path where the .m files are stored:

runtests("/path/to/queueing/inst");
-| Processing files in /path/to/queueing/inst:
-|
-|  ctmc.m .............................................. PASS 9/9
-|  ctmcbd.m ............................................ PASS 1/1
…

A better way for Unix users is to use the Makefile provided in the top-level directory of the development sources. As described in Development sources, the Makefile defines a target ‘check’ that runs all tests over all functions in the inst/ directory. Simply run the

make check

command from the Unix shell to run all tests.

The source files include small demos that show how the function defined there can be used. Similarly to test blocks, demos are embedded in the source files using the ‘%!demo’ directive. Demos can be displayed and run using the demo built-in command at the GNU Octave prompt:

demo("qsmm1");

 ## Given a M/M/1 queue, compute the steady-state probability pk
 ## of having k requests in the systen.
 lambda = 0.2;
 mu = 0.25;
 k = 0:10;
 pk = qsmm1(lambda, mu, k);
 plot(k, pk, "-o", "linewidth", 2);
 xlabel("N. of requests (k)");
 ylabel("p_k");
 title(sprintf("M/M/1 system, \\lambda = %g, \\mu = %g", lambda, mu));

2.5 Naming Conventions

Most of the functions in the queueing package obey a common naming convention. Function names are made of several parts; the first part is a prefix which indicates the class of problems the function addresses:

ctmc-

Functions for continuous-time Markov chains

dtmc-

Functions for discrete-time Markov chains

qs-

Functions for analyzing single-station queueing systems (individual service centers)

qn-

Functions for analyzing queueing networks

Functions dealing with Markov chains start with either the ctmc or dtmc prefix; the prefix is optionally followed by an additional string which hints at what the function does:

-bd

Birth-Death process

-mtta

Mean Time to Absorption

-fpt

First Passage Times

-exps

Expected Sojourn Times

-taexps

Time-Averaged Expected Sojourn Times

For example, function ctmcbd returns the infinitesimal generator matrix for a continuous birth-death process, while dtmcbd returns the transition probability matrix for a discrete birth-death process. Note that there exist functions ctmc and dtmc (without any suffix) that compute steady-state and transient state occupancy probabilities for CTMCs and DTMCs, respectively. See Markov Chains.

Functions whose name starts with qs- deal with single station queueing systems. The suffix describes the type of system, e.g., qsmm1 for M/M/1, qnmmm for M/M/m and so on. See Single Station Queueing Systems.

Finally, functions whose name starts with qn- deal with queueing networks. The character that follows indicates whether the function handles open ('o') or closed ('c') networks, and whether there is a single customer class ('s') or multiple classes ('m'). The string mix indicates that the function supports mixed networks with both open and closed customer classes.

-os-

Open, single-class network: open network with a single class of customers

-om-

Open, multiclass network: open network with multiple job classes

-cs-

Closed, single-class network

-cm-

Closed, multiclass network

-mix-

Mixed network with open and closed classes of customers

The last part of the function name indicates the algorithm implemented by the function. See Queueing Networks.

-aba

Asymptotic Bounds Analysis

-bsb

Balanced System Bounds

-gb

Geometric Bounds

-pb

PB Bounds

-cb

Composite Bounds (CB)

-mva

Mean Value Analysis (MVA) algorithm

-cmva

Conditional MVA

-mvald

MVA with general load-dependent servers

-mvaap

Approximate MVA

-mvablo

MVABLO approximation for blocking queueing networks

-conv

Convolution algorithm

-convld

Convolution algorithm with general load-dependent servers

Some deprecated functions may be present in the queueing package; generally, these are functions that have been renamed, and the old name is kept for a while for backward compatibility. Deprecated functions are not documented and will be removed in future releases. Calling a deprecated functions displays a warning message that appears only once per session. The warning message can be turned off with the command:

octave:1> warning ("off", "qn:deprecated-function");

However, you are strongly recommended to update your code to the new API. To help catching usages of deprecated functions, you can transform warnings into errors so that your application stops immediately:

octave:1> warning ("error", "qn:deprecated-function");

2.6 Quick start Guide

You can use all functions by simply invoking their name with the appropriate parameters; an error is shown in case of missing/wrong parameters. Extensive documentation is provided for each function, and can be displayed with the help command. For example:

octave:2> help qncsmvablo

shows the documentation for the qncsmvablo function. Additional information can be found in the queueing manual, that is available in PDF format in doc/queueing.pdf and in HTML format in doc/queueing.html.

Ad sicussed above, many functions have demo blocks showing usage examples. To execute the demos for the qnclosed function, use the demo command:

octave:4> demo qnclosed

We now illustrate a few examples of how the queueing package can be used. More examples are provided in the manual.

Example 1 Compute the stationary state occupancy probabilities of a continuous-time Markov chain with infinitesimal generator matrix

    / -0.8   0.6   0.2 \
Q = |  0.3  -0.7   0.4 |
    \  0.2   0.2  -0.4 /
Q = [ -0.8  0.6  0.2; ...
       0.3 -0.7  0.4; ...
       0.2  0.2 -0.4 ];
q = ctmc(Q)
    ⇒ q = 0.23256   0.32558   0.44186

Example 2 Compute the transient state occupancy probability after n=3 transitions of a three state discrete-time birth-death process, with birth probabilities \lambda_{01} = 0.3 and \lambda_{12} = 0.5 and death probabilities \mu_{10} = 0.5 and \mu_{21} = 0.7, assuming that the system is initially in state zero (i.e., the initial state occupancy probabilities are [1, 0, 0]).

n = 3;
p0 = [1 0 0];
P = dtmcbd( [0.3 0.5], [0.5 0.7] );
p = dtmc(P,n,p0)
    ⇒ p = 0.55300   0.29700   0.15000

Example 3 Compute server utilization, response time, mean number of requests and throughput of a closed queueing network with N=4 requests and three M/M/1–FCFS queues with mean service times S = [1.0, 0.8, 1.4] and average number of visits V = [1.0, 0.8, 0.8]

S = [1.0 0.8 1.4];
V = [1.0 0.8 0.8];
N = 4;
[U R Q X] = qncsmva(N, S, V)
    ⇒
     U = 0.70064   0.44841   0.78471
     R = 2.1030    1.2642    3.2433
     Q = 1.47346   0.70862   1.81792
     X = 0.70064   0.56051   0.56051

Example 4 Compute server utilization, response time, mean number of requests and throughput of an open queueing network with three M/M/1–FCFS queues with mean service times S = [1.0, 0.8, 1.4] and average number of visits V = [1.0, 0.8, 0.8]. The overall arrival rate is \lambda = 0.8 requests/second.

S = [1.0 0.8 1.4];
V = [1.0 0.8 0.8];
lambda = 0.8;
[U R Q X] = qnos(lambda, S, V)
    ⇒
     U = 0.80000   0.51200   0.89600
     R = 5.0000    1.6393   13.4615
     Q = 4.0000    1.0492    8.6154
     X = 0.80000   0.64000   0.64000

3 Markov Chains


3.1 Discrete-Time Markov Chains

Let X_0, X_1, …, X_n, … be a sequence of random variables defined over the discrete state space 1, 2, …. The sequence X_0, X_1, …, X_n, … is a stochastic process with discrete time 0, 1, 2, …. A Markov chain is a stochastic process {X_n, n=0, 1, …} which satisfies the following Markov property:

P(X_{n+1} = x_{n+1} | X_n = x_n, X_{n-1} = x_{n-1}, …, X_0 = x_0) = P(X_{n+1} = x_{n+1} | X_n = x_n)

which basically means that the probability that the system is in a particular state at time n+1 only depends on the state the system was at time n.

The evolution of a Markov chain with finite state space {1, …, N} can be fully described by a stochastic matrix {\bf P}(n) = [ P_{i,j}(n) ] where P_{i, j}(n) = P( X_{n+1} = j\ |\ X_n = i ). If the Markov chain is homogeneous (that is, the transition probability matrix {\bf P}(n) is time-independent), we can write {\bf P} = [P_{i, j}], where P_{i, j} = P( X_{n+1} = j\ |\ X_n = i ) for all n=0, 1, ….

The transition probability matrix \bf P must be a stochastic matrix, meaning that it must satisfy the following two properties:

  1. P_{i, j} ≥ 0 for all 1 ≤ i, j ≤ N;
  2. \sum_{j=1}^N P_{i,j} = 1 for all i

Property 1 requires that all probabilities are nonnegative; property 2 requires that the outgoing transition probabilities from any state i sum to one.

Function File: [r err] = dtmcchkP (P)

Check whether P is a valid transition probability matrix.

If P is valid, r is the size (number of rows or columns) of P. If P is not a transition probability matrix, r is set to zero, and err to an appropriate error string.

A DTMC is irreducible if every state can be reached with non-zero probability starting from every other state.

Function File: [r s] = dtmcisir (P)

Check if P is irreducible, and identify Strongly Connected Components (SCC) in the transition graph of the DTMC with transition matrix P.

INPUTS

P(i,j)

transition probability from state i to state j. P must be an N \times N stochastic matrix.

OUTPUTS

r

1 if P is irreducible (i.e., the state transition graph is strongly connected), 0 otherwise (scalar)

s(i)

strongly connected component (SCC) that state i belongs to (vector of length N). SCCs are numbered 1, 2, …. The number of SCCs is max(s). If the graph is strongly connected, then there is a single SCC and the predicate all(s == 1) evaluates to true


3.1.1 State occupancy probabilities

Given a discrete-time Markov chain with state space {1, …, N}, we denote with {\bf \pi}(n) = \left[\pi_1(n), … \pi_N(n) \right] the state occupancy probability vector at step n = 0, 1, …. \pi_i(n) is the probability that the system is in state i after n transitions.

Given the transition probability matrix \bf P and the initial state occupancy probability vector {\bf \pi}(0) = \left[\pi_1(0), …, \pi_N(0)\right], {\bf \pi}(n) can be computed as:

\pi(n) = \pi(0) P^n

Under certain conditions, there exists a stationary state occupancy probability {\bf \pi} = \lim_{n \rightarrow +\infty} {\bf \pi}(n), which is independent from {\bf \pi}(0). The vector \bf \pi is the solution of the following linear system:

/
| \pi P   = \pi
| \pi 1^T = 1
\

where \bf 1 is the row vector of ones, and ( \cdot )^T the transpose operator.

Function File: p = dtmc (P)
Function File: p = dtmc (P, n, p0)

Compute stationary or transient state occupancy probabilities for a discrete-time Markov chain.

With a single argument, compute the stationary state occupancy probabilities p(1), …, p(N) for a discrete-time Markov chain with finite state space {1, …, N} and with N \times N transition matrix P. With three arguments, compute the transient state occupancy probabilities p(1), …, p(N) that the system is in state i after n steps, given initial occupancy probabilities p0(1), …, p0(N).

INPUTS

P(i,j)

transition probabilities from state i to state j. P must be an N \times N irreducible stochastic matrix, meaning that the sum of each row must be 1 (\sum_{j=1}^N P_{i, j} = 1), and the rank of P must be N.

n

Number of transitions after which state occupancy probabilities are computed (scalar, n ≥ 0)

p0(i)

probability that at step 0 the system is in state i (vector of length N).

OUTPUTS

p(i)

If this function is called with a single argument, p(i) is the steady-state probability that the system is in state i. If this function is called with three arguments, p(i) is the probability that the system is in state i after n transitions, given the probabilities p0(i) that the initial state is i.


See also: ctmc.

EXAMPLE

The following example is from GrSn97. Let us consider a maze with nine rooms, as shown in the following figure

+-----+-----+-----+
|     |     |     |
|  1     2     3  |
|     |     |     |
+-   -+-   -+-   -+
|     |     |     |
|  4     5     6  |
|     |     |     |
+-   -+-   -+-   -+
|     |     |     |
|  7     8     9  |
|     |     |     |
+-----+-----+-----+

A mouse is placed in one of the rooms and can wander around. At each step, the mouse moves from the current room to a neighboring one with equal probability. For example, if it is in room 1, it can move to room 2 and 4 with probability 1/2, respectively; if the mouse is in room 8, it can move to either 7, 5 or 9 with probability 1/3.

The transition probabilities P_{i, j} from room i to room j can be summarized in the following matrix:

        / 0     1/2   0     1/2   0     0     0     0     0   \
        | 1/3   0     1/3   0     1/3   0     0     0     0   |
        | 0     1/2   0     0     0     1/2   0     0     0   |
        | 1/3   0     0     0     1/3   0     1/3   0     0   |
    P = | 0     1/4   0     1/4   0     1/4   0     1/4   0   |
        | 0     0     1/3   0     1/3   0     0     0     1/3 |
        | 0     0     0     1/2   0     0     0     1/2   0   |
        | 0     0     0     0     1/3   0     1/3   0     1/3 |
        \ 0     0     0     0     0     1/2   0     1/2   0   /

The stationary state occupancy probabilities can then be computed with the following code:

 P = zeros(9,9);
 P(1,[2 4]    ) = 1/2;
 P(2,[1 5 3]  ) = 1/3;
 P(3,[2 6]    ) = 1/2;
 P(4,[1 5 7]  ) = 1/3;
 P(5,[2 4 6 8]) = 1/4;
 P(6,[3 5 9]  ) = 1/3;
 P(7,[4 8]    ) = 1/2;
 P(8,[7 5 9]  ) = 1/3;
 P(9,[6 8]    ) = 1/2;
 p = dtmc(P);
 disp(p)
    ⇒ 0.083333   0.125000   0.083333   0.125000   
       0.166667   0.125000   0.083333   0.125000   
       0.083333

3.1.2 Birth-death process

Function File: P = dtmcbd (b, d)

Returns the transition probability matrix P for a discrete birth-death process over state space {1, …, N}. For each i=1, …, (N-1), b(i) is the transition probability from state i to (i+1), and d(i) is the transition probability from state (i+1) to i.

Matrix \bf P is defined as:

/                                                             \
| 1-b(1)     b(1)                                             |
|  d(1)  (1-d(1)-b(2))     b(2)                               |
|            d(2)      (1-d(2)-b(3))     b(3)                 |
|                                                             |
|                 ...           ...          ...              |
|                                                             |
|                         d(N-2)   (1-d(N-2)-b(N-1))  b(N-1)  |
|                                        d(N-1)      1-d(N-1) |
\                                                             /

where \lambda_i and \mu_i are the birth and death probabilities, respectively.


See also: ctmcbd.


3.1.3 Expected Number of Visits

Given a N state discrete-time Markov chain with transition matrix \bf P and an integer n ≥ 0, we let L_i(n) be the the expected number of visits to state i during the first n transitions. The vector {\bf L}(n) = \left[ L_1(n), …, L_N(n) \right] is defined as

         n            n
        ___          ___
       \            \           i
L(n) =  >   pi(i) =  >   pi(0) P
       /___         /___
        i=0          i=0

where {\bf \pi}(i) = {\bf \pi}(0){\bf P}^i is the state occupancy probability after i transitions, and {\bf \pi}(0) = \left[\pi_1(0), …, \pi_N(0) \right] are the initial state occupancy probabilities.

If \bf P is absorbing, i.e., the stochastic process eventually enters a state with no outgoing transitions, then we can compute the expected number of visits until absorption \bf L. To do so, we first rearrange the states by rewriting \bf P as

    / Q | R \
P = |---+---|
    \ 0 | I /

where the first t states are transient and the last r states are absorbing (t+r = N). The matrix {\bf N} = ({\bf I} - {\bf Q})^{-1} is called the fundamental matrix; N_{i,j} is the expected number of times the process is in the j-th transient state assuming it started in the i-th transient state. If we reshape \bf N to the size of \bf P (filling missing entries with zeros), we have that, for absorbing chains, {\bf L} = {\bf \pi}(0){\bf N}.

Function File: L = dtmcexps (P, n, p0)
Function File: L = dtmcexps (P, p0)

Compute the expected number of visits to each state during the first n transitions, or until abrosption.

INPUTS

P(i,j)

N \times N transition matrix. P(i,j) is the transition probability from state i to state j.

n

Number of steps during which the expected number of visits are computed (n ≥ 0). If n=0, returns p0. If n > 0, returns the expected number of visits after exactly n transitions.

p0(i)

Initial state occupancy probabilities; p0(i) is the probability that the system is in state i at step 0.

OUTPUTS

L(i)

When called with two arguments, L(i) is the expected number of visits to state i before absorption. When called with three arguments, L(i) is the expected number of visits to state i during the first n transitions.

REFERENCES

  • Grinstead, Charles M.; Snell, J. Laurie (July 1997). Introduction to Probability, Ch. 11: Markov Chains. American Mathematical Society. ISBN 978-0821807491.

See also: ctmcexps.


3.1.4 Time-averaged expected sojourn times

Function File: M = dtmctaexps (P, n, p0)
Function File: M = dtmctaexps (P, p0)

Compute the time-averaged sojourn times M(i), defined as the fraction of time spent in state i during the first n transitions (or until absorption), assuming that the state occupancy probabilities at time 0 are p0.

INPUTS

P(i,j)

N \times N transition probability matrix.

n

Number of transitions during which the time-averaged expected sojourn times are computed (scalar, n ≥ 0). if n = 0, returns p0.

p0(i)

Initial state occupancy probabilities (vector of length N).

OUTPUTS

M(i)

If this function is called with three arguments, M(i) is the expected fraction of steps {0, …, n} spent in state i, assuming that the state occupancy probabilities at time zero are p0. If this function is called with two arguments, M(i) is the expected fraction of steps spent in state i until absorption. M is a vector of length N.


See also: dtmcexps.


3.1.5 Mean Time to Absorption

The mean time to absorption is defined as the average number of transitions that are required to enter an absorbing state, starting from a transient state or given initial state occupancy probabilities {\bf \pi}(0).

Let t_i be the expected number of transitions before being absorbed in any absorbing state, starting from state i. The vector {\bf t} = [t_1, …, t_N] can be computed from the fundamental matrix \bf N (see Expected number of visits (DTMC)) as

t = N c

where \bf c is a column vector of 1’s.

Let {\bf B} = [ B_{i, j} ] be a matrix where B_{i, j} is the probability of being absorbed in state j, starting from transient state i. Again, using matrices \bf N and \bf R (see Expected number of visits (DTMC)) we can write

B = N R

Function File: [t N B] = dtmcmtta (P)
Function File: [t N B] = dtmcmtta (P, p0)

Compute the expected number of steps before absorption for a DTMC with state space {1, …, N} and transition probability matrix P.

INPUTS

P(i,j)

N \times N transition probability matrix. P(i,j) is the transition probability from state i to state j.

p0(i)

Initial state occupancy probabilities (vector of length N).

OUTPUTS

t
t(i)

When called with a single argument, t is a vector of length N such that t(i) is the expected number of steps before being absorbed in any absorbing state, starting from state i; if i is absorbing, t(i) = 0. When called with two arguments, t is a scalar, and represents the expected number of steps before absorption, starting from the initial state occupancy probability p0.

N(i)
N(i,j)

When called with a single argument, N is the N \times N fundamental matrix for P. N(i,j) is the expected number of visits to transient state j before absorption, if the system started in transient state i. The initial state is counted if i = j. When called with two arguments, N is a vector of length N such that N(j) is the expected number of visits to transient state j before absorption, given initial state occupancy probability P0.

B(i)
B(i,j)

When called with a single argument, B is a N \times N matrix where B(i,j) is the probability of being absorbed in state j, starting from transient state i; if j is not absorbing, B(i,j) = 0; if i is absorbing, B(i,i) = 1 and B(i,j) = 0 for all i \neq j. When called with two arguments, B is a vector of length N where B(j) is the probability of being absorbed in state j, given initial state occupancy probabilities p0.

REFERENCES

  • Grinstead, Charles M.; Snell, J. Laurie (July 1997). Introduction to Probability, Ch. 11: Markov Chains. American Mathematical Society. ISBN 978-0821807491.

See also: ctmcmtta.


3.1.6 First Passage Times

The First Passage Time M_{i, j} is the average number of transitions needed to enter state j for the first time, starting from state i. Matrix \bf M satisfies the property

           ___
          \
M_ij = 1 + >   P_ij * M_kj
          /___
          k!=j

To compute {\bf M} = [ M_{i, j}] a different formulation is used. Let \bf W be the N \times N matrix having each row equal to the stationary state occupancy probability vector \bf \pi for \bf P; let \bf I be the N \times N identity matrix (i.e., the matrix of all ones). Define \bf Z as follows:

               -1
Z = (I - P + W)

Then, we have that

       Z_jj - Z_ij
M_ij = -----------
          \pi_j

According to the definition above, M_{i,i} = 0. We arbitrarily set M_{i,i} to the mean recurrence time r_i for state i, that is the average number of transitions needed to return to state i starting from it. r_i is:

        1
r_i = -----
      \pi_i
Function File: M = dtmcfpt (P)

Compute mean first passage times and mean recurrence times for an irreducible discrete-time Markov chain over the state space {1, …, N}.

INPUTS

P(i,j)

transition probability from state i to state j. P must be an irreducible stochastic matrix, which means that the sum of each row must be 1 (\sum_{j=1}^N P_{i j} = 1), and the rank of P must be N.

OUTPUTS

M(i,j)

For all 1 ≤ i, j ≤ N, i \neq j, M(i,j) is the average number of transitions before state j is entered for the first time, starting from state i. M(i,i) is the mean recurrence time of state i, and represents the average time needed to return to state i.

REFERENCES

  • Grinstead, Charles M.; Snell, J. Laurie (July 1997). Introduction to Probability, Ch. 11: Markov Chains. American Mathematical Society. ISBN 978-0821807491.

See also: ctmcfpt.


3.2 Continuous-Time Markov Chains

A stochastic process {X(t), t ≥ 0} is a continuous-time Markov chain if, for all integers n, and for any sequence t_0, t_1 , …, t_n, t_{n+1} such that t_0 < t_1 < … < t_n < t_{n+1}, we have

P(X_{n+1} = x_{n+1} | X_n = x_n, X_{n-1} = x_{n-1}, ..., X_0 = x_0) = P(X_{n+1} = x_{n+1} | X_n = x_n)

A continuous-time Markov chain is defined according to an infinitesimal generator matrix {\bf Q} = [Q_{i,j}], where for each i \neq j, Q_{i, j} is the transition rate from state i to state j. The matrix \bf Q must satisfy the property that, for all i, \sum_{j=1}^N Q_{i, j} = 0.

Function File: [result err] = ctmcchkQ (Q)

If Q is a valid infinitesimal generator matrix, return the size (number of rows or columns) of Q. If Q is not an infinitesimal generator matrix, set result to zero, and err to an appropriate error string.

Similarly to the DTMC case, a CTMC is irreducible if every state is eventually reachable from every other state in finite time.

Function File: [r s] = ctmcisir (P)

Check if Q is irreducible, and identify Strongly Connected Components (SCC) in the transition graph of the DTMC with infinitesimal generator matrix Q.

INPUTS

Q(i,j)

Infinitesimal generator matrix. Q is a N \times N square matrix where Q(i,j) is the transition rate from state i to state j, for 1 ≤ i, j ≤ N, i \neq j.

OUTPUTS

r

1 if Q is irreducible, 0 otherwise.

s(i)

strongly connected component (SCC) that state i belongs to. SCCs are numbered 1, 2, …. If the graph is strongly connected, then there is a single SCC and the predicate all(s == 1) evaluates to true.


3.2.1 State occupancy probabilities

Similarly to the discrete case, we denote with {\bf \pi}(t) = \left[\pi_1(t), …, \pi_N(t) \right] the state occupancy probability vector at time t. \pi_i(t) is the probability that the system is in state i at time t ≥ 0.

Given the infinitesimal generator matrix \bf Q and initial state occupancy probabilities {\bf \pi}(0) = \left[\pi_1(0), …, \pi_N(0)\right], the occupancy probabilities {\bf \pi}(t) at time t can be computed as:

\pi(t) = \pi(0) exp(Qt)

where \exp( {\bf Q} t ) is the matrix exponential of {\bf Q} t. Under certain conditions, there exists a stationary state occupancy probability {\bf \pi} = \lim_{t \rightarrow +\infty} {\bf \pi}(t) that is independent from {\bf \pi}(0). \bf \pi is the solution of the following linear system:

/
| \pi Q   = 0
| \pi 1^T = 1
\
Function File: p = ctmc (Q)
Function File: p = ctmc (Q, t, p0)

Compute stationary or transient state occupancy probabilities for a continuous-time Markov chain.

With a single argument, compute the stationary state occupancy probabilities p(1), …, p(N) for a continuous-time Markov chain with finite state space {1, …, N} and N \times N infinitesimal generator matrix Q. With three arguments, compute the state occupancy probabilities p(1), …, p(N) that the system is in state i at time t, given initial state occupancy probabilities p0(1), …, p0(N) at time 0.

INPUTS

Q(i,j)

Infinitesimal generator matrix. Q is a N \times N square matrix where Q(i,j) is the transition rate from state i to state j, for 1 ≤ i \neq j ≤ N. Q must satisfy the property that \sum_{j=1}^N Q_{i, j} = 0

t

Time at which to compute the transient probability (t ≥ 0). If omitted, the function computes the steady state occupancy probability vector.

p0(i)

probability that the system is in state i at time 0.

OUTPUTS

p(i)

If this function is invoked with a single argument, p(i) is the steady-state probability that the system is in state i, i = 1, …, N. If this function is invoked with three arguments, p(i) is the probability that the system is in state i at time t, given the initial occupancy probabilities p0(1), …, p0(N).


See also: dtmc.

EXAMPLE

Consider a two-state CTMC where all transition rates between states are equal to 1. The stationary state occupancy probabilities can be computed as follows:

 Q = [ -1  1; ...
        1 -1  ];
 q = ctmc(Q)
    ⇒ q = 0.50000   0.50000

3.2.2 Birth-Death Process

Function File: Q = ctmcbd (b, d)

Returns the infinitesimal generator matrix Q for a continuous birth-death process over the finite state space {1, …, N}. For each i=1, …, (N-1), b(i) is the transition rate from state i to state (i+1), and d(i) is the transition rate from state (i+1) to state i.

Matrix \bf Q is therefore defined as:

/                                                          \
| -b(1)     b(1)                                           |
|  d(1) -(d(1)+b(2))     b(2)                              |
|           d(2)     -(d(2)+b(3))        b(3)              |
|                                                          |
|                ...           ...          ...            |
|                                                          |
|                       d(N-2)    -(d(N-2)+b(N-1))  b(N-1) |
|                                       d(N-1)     -d(N-1) |
\                                                          /

where \lambda_i and \mu_i are the birth and death rates, respectively.


See also: dtmcbd.


3.2.3 Expected Sojourn Times

Given a N state continuous-time Markov Chain with infinitesimal generator matrix \bf Q, we define the vector {\bf L}(t) = \left[L_1(t), …, L_N(t)\right] such that L_i(t) is the expected sojourn time in state i during the interval [0,t), assuming that the initial occupancy probabilities at time 0 were {\bf \pi}(0). {\bf L}(t) can be expressed as the solution of the following differential equation:

 dL
 --(t) = L(t) Q + pi(0),    L(0) = 0
 dt

Alternatively, {\bf L}(t) can also be expressed in integral form as:

       / t
L(t) = |   pi(u) du
       / 0

where {\bf \pi}(t) = {\bf \pi}(0) \exp({\bf Q}t) is the state occupancy probability at time t; \exp({\bf Q}t) is the matrix exponential of {\bf Q}t.

If there are absorbing states, we can define the vector of expected sojourn times until absorption {\bf L}(\infty), where for each transient state i, L_i(\infty) is the expected total time spent in state i until absorption, assuming that the system started with given state occupancy probabilities {\bf \pi}(0). Let \tau be the set of transient (i.e., non absorbing) states; let {\bf Q}_\tau be the restriction of \bf Q to the transient sub-states only. Similarly, let {\bf \pi}_\tau(0) be the restriction of the initial state occupancy probability vector {\bf \pi}(0) to transient states \tau.

The expected time to absorption {\bf L}_\tau(\infty) is defined as the solution of the following equation:

L_T( inf ) Q_T = -pi_T(0)
Function File: L = ctmcexps (Q, t, p )
Function File: L = ctmcexps (Q, p)

With three arguments, compute the expected times L(i) spent in each state i during the time interval [0,t], assuming that the initial occupancy vector is p. With two arguments, compute the expected time L(i) spent in each transient state i until absorption.

Note: In its current implementation, this function requires that an absorbing state is reachable from any non-absorbing state of Q.

INPUTS

Q(i,j)

N \times N infinitesimal generator matrix. Q(i,j) is the transition rate from state i to state j, 1 ≤ i, j ≤ N, i \neq j. The matrix Q must also satisfy the condition \sum_{j=1}^N Q_{i,j} = 0 for every i=1, …, N.

t

If given, compute the expected sojourn times in [0,t]

p(i)

Initial occupancy probability vector; p(i) is the probability the system is in state i at time 0, i = 1, …, N

OUTPUTS

L(i)

If this function is called with three arguments, L(i) is the expected time spent in state i during the interval [0,t]. If this function is called with two arguments L(i) is the expected time spent in transient state i until absorption; if state i is absorbing, L(i) is zero.


See also: dtmcexps.

EXAMPLE

Let us consider a 4-states pure birth continuous process where the transition rate from state i to state (i+1) is \lambda_i = i \lambda (i=1, 2, 3), with \lambda = 0.5. The following code computes the expected sojourn time for each state i, given initial occupancy probabilities {\bf \pi}_0=[1, 0, 0, 0].

 lambda = 0.5;
 N = 4;
 b = lambda*[1:N-1];
 d = zeros(size(b));
 Q = ctmcbd(b,d);
 t = linspace(0,10,100);
 p0 = zeros(1,N); p0(1)=1;
 L = zeros(length(t),N);
 for i=1:length(t)
   L(i,:) = ctmcexps(Q,t(i),p0);
 endfor
 plot( t, L(:,1), ";State 1;", "linewidth", 2, ...
       t, L(:,2), ";State 2;", "linewidth", 2, ...
       t, L(:,3), ";State 3;", "linewidth", 2, ...
       t, L(:,4), ";State 4;", "linewidth", 2 );
 legend("location","northwest"); legend("boxoff");
 xlabel("Time");
 ylabel("Expected sojourn time");

3.2.4 Time-Averaged Expected Sojourn Times

Function File: M = ctmctaexps (Q, t, p0)
Function File: M = ctmctaexps (Q, p0)

Compute the time-averaged sojourn time M(i), defined as the fraction of the time interval [0,t] (or until absorption) spent in state i, assuming that the state occupancy probabilities at time 0 are p.

INPUTS

Q(i,j)

Infinitesimal generator matrix. Q(i,j) is the transition rate from state i to state j, 1 ≤ i,j ≤ N, i \neq j. The matrix Q must also satisfy the condition \sum_{j=1}^N Q_{i,j} = 0

t

Time. If omitted, the results are computed until absorption.

p0(i)

initial state occupancy probabilities. p0(i) is the probability that the system is in state i at time 0, i = 1, …, N

OUTPUTS

M(i)

When called with three arguments, M(i) is the expected fraction of the interval [0,t] spent in state i assuming that the state occupancy probability at time zero is p. When called with two arguments, M(i) is the expected fraction of time until absorption spent in state i; in this case the mean time to absorption is sum(M).


See also: ctmcexps.

EXAMPLE

 lambda = 0.5;
 N = 4;
 birth = lambda*linspace(1,N-1,N-1);
 death = zeros(1,N-1);
 Q = diag(birth,1)+diag(death,-1);
 Q -= diag(sum(Q,2));
 t = linspace(1e-5,30,100);
 p = zeros(1,N); p(1)=1;
 M = zeros(length(t),N);
 for i=1:length(t)
   M(i,:) = ctmctaexps(Q,t(i),p);
 endfor
 clf;
 plot(t, M(:,1), ";State 1;", "linewidth", 2, ...
      t, M(:,2), ";State 2;", "linewidth", 2, ...
      t, M(:,3), ";State 3;", "linewidth", 2, ...
      t, M(:,4), ";State 4 (absorbing);", "linewidth", 2 );
 legend("location","east"); legend("boxoff");
 xlabel("Time");
 ylabel("Time-averaged Expected sojourn time");

3.2.5 Mean Time to Absorption

Function File: t = ctmcmtta (Q, p)

Compute the Mean-Time to Absorption (MTTA) of the CTMC described by the infinitesimal generator matrix Q, starting from initial occupancy probabilities p. If there are no absorbing states, this function fails with an error.

INPUTS

Q(i,j)

N \times N infinitesimal generator matrix. Q(i,j) is the transition rate from state i to state j, i \neq j. The matrix Q must satisfy the condition \sum_{j=1}^N Q_{i,j} = 0

p(i)

probability that the system is in state i at time 0, for each i=1, …, N

OUTPUTS

t

Mean time to absorption of the process represented by matrix Q. If there are no absorbing states, this function fails.

REFERENCES

  • G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998.

See also: ctmcexps.

EXAMPLE

Let us consider a simple model of redundant disk array. We assume that the array is made of 5 independent disks and can tolerate up to 2 disk failures without losing data. If three or more disks break, the array is dead and unrecoverable. We want to estimate the Mean-Time-To-Failure (MTTF) of the disk array.

We model this system as a 4 states continuous Markov chain with state space { 2, 3, 4, 5 }. In state i there are exactly i active (i.e., non failed) disks; state 2 is absorbing. Let \mu be the failure rate of a single disk. The system starts in state 5 (all disks are operational). We use a pure death process, where the death rate from state i to state (i-1) is \mu i, for i = 3, 4, 5).

The MTTF of the disk array is the MTTA of the Markov Chain, and can be computed as follows:

 mu = 0.01;
 death = [ 3 4 5 ] * mu;
 birth = 0*death;
 Q = ctmcbd(birth,death);
 t = ctmcmtta(Q,[0 0 0 1])
    ⇒ t = 78.333

3.2.6 First Passage Times

Function File: M = ctmcfpt (Q)
Function File: m = ctmcfpt (Q, i, j)

Compute mean first passage times for an irreducible continuous-time Markov chain.

INPUTS

Q(i,j)

Infinitesimal generator matrix. Q is a N \times N square matrix where Q(i,j) is the transition rate from state i to state j, for 1 ≤ i, j ≤ N, i \neq j. Transition rates must be nonnegative, and \sum_{j=1}^N Q_{i,j} = 0

i

Initial state.

j

Destination state.

OUTPUTS

M(i,j)

average time before state j is visited for the first time, starting from state i. We let M(i,i) = 0.

m

m is the average time before state j is visited for the first time, starting from state i.


See also: ctmcmtta.


Next: , Previous: , Up: Top   [Contents][Index]

4 Single Station Queueing Systems

Single Station Queueing Systems contain a single station, and can usually be analyzed easily. The queueing package contains functions for handling the following types of queues:


4.1 The M/M/1 System

The M/M/1 system contains a single server connected to an unbounded FCFS queue. Requests arrive according to a Poisson process with rate \lambda; the service time is exponentially distributed with average service rate \mu. The system is stable if \lambda < \mu.

Function File: [U, R, Q, X, p0] = qsmm1 (lambda, mu)
Function File: pk = qsmm1 (lambda, mu, k)

Compute utilization, response time, average number of requests and throughput for a M/M/1 queue.

INPUTS

lambda

Arrival rate (lambda ≥ 0).

mu

Service rate (mu > lambda).

k

Number of requests in the system (k ≥ 0).

OUTPUTS

U

Server utilization

R

Server response time

Q

Average number of requests in the system

X

Server throughput. If the system is ergodic (mu > lambda), we always have X = lambda

p0

Steady-state probability that there are no requests in the system.

pk

Steady-state probability that there are k requests in the system. (including the one being served).

If this function is called with less than three input parameters, lambda and mu can be vectors of the same size. In this case, the results will be vectors as well.

REFERENCES

  • G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998, Section 6.3

See also: qsmmm, qsmminf, qsmmmk.


4.2 The M/M/m System

The M/M/m system is similar to the M/M/1 system, except that there are m \geq 1 identical servers connected to a shared FCFS queue. Thus, at most m requests can be served at the same time. The M/M/m system can be seen as a single server with load-dependent service rate \mu(n), which is a function of the number n of requests in the system:

mu(n) = min(m,n)*mu

where \mu is the service rate of each individual server.

Function File: [U, R, Q, X, p0, pm] = qsmmm (lambda, mu)
Function File: [U, R, Q, X, p0, pm] = qsmmm (lambda, mu, m)
Function File: pk = qsmmm (lambda, mu, m, k)

Compute utilization, response time, average number of requests in service and throughput for a M/M/m queue, a queueing system with m identical servers connected to a single FCFS queue.

INPUTS

lambda

Arrival rate (lambda>0).

mu

Service rate (mu>lambda).

m

Number of servers (m ≥ 1). Default is m=1.

k

Number of requests in the system (k ≥ 0).

OUTPUTS

U

Service center utilization, U = \lambda / (m \mu).

R

Service center mean response time

Q

Average number of requests in the system

X

Service center throughput. If the system is ergodic, we will always have X = lambda

p0

Steady-state probability that there are 0 requests in the system

pm

Steady-state probability that an arriving request has to wait in the queue

pk

Steady-state probability that there are k requests in the system (including the one being served).

If this function is called with less than four parameters, lambda, mu and m can be vectors of the same size. In this case, the results will be vectors as well.

REFERENCES

  • G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998, Section 6.5

See also: erlangc,qsmm1,qsmminf,qsmmmk.


4.3 The Erlang-B Formula

Function File: B = erlangb (A, m)

Compute the steady-state blocking probability in the Erlang loss model.

The Erlang-B formula E_B(A, m) gives the probability that an open system with m identical servers, arrival rate \lambda, individual service rate \mu and offered load A = \lambda / \mu has all servers busy. This corresponds to the rejection probability of an M/M/m/0 system with m servers and no queue.

INPUTS

A

Offered load, defined as A = \lambda / \mu where \lambda is the mean arrival rate and \mu the mean service rate of each individual server (real, A > 0).

m

Number of identical servers (integer, m ≥ 1). Default m = 1

OUTPUTS

B

The value E_B(A, m)

A or m can be vectors, and in this case, the results will be vectors as well.

REFERENCES

  • G. Zeng, Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296

See also: erlangc,engset,qsmmm.


4.4 The Erlang-C Formula

Function File: C = erlangc (A, m)

Compute the steady-state probability of delay in the Erlang delay model.

The Erlang-C formula E_C(A, m) gives the probability that an open queueing system with m identical servers, infinite wating space, arrival rate \lambda, individual service rate \mu and offered load A = \lambda / \mu has all the servers busy. This is the waiting probability in an M/M/m/\infty system with m servers and an infinite queue.

INPUTS

A

Offered load. A = \lambda / \mu where \lambda is the mean arrival rate and \mu the mean service rate of each individual server (real, 0 < A < m).

m

Number of identical servers (integer, m ≥ 1). Default m = 1

OUTPUTS

B

The value E_C(A, m)

A or m can be vectors, and in this case, the results will be vectors as well.

REFERENCES

  • G. Zeng, Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296

See also: erlangb,engset,qsmmm.


4.5 The Engset Formula

Function File: B = engset (A, m, n)

Evaluate the Engset loss formula.

The Engset formula computes the blocking probability P_b(A,m,n) for a system with a finite population of n users, m identical servers, no queue, individual service rate \mu, individual arrival rate \lambda (i.e., the time until a user tries to request service is exponentially distributed with mean 1/\lambda), and offered load A=\lambda/\mu.

INPUTS

A

Offered load, defined as A = \lambda / \mu where \lambda is the mean arrival rate and \mu the mean service rate of each individual server (real, A > 0).

m

Number of identical servers (integer, m ≥ 1). Default m = 1

n

Number of requests (integer, n ≥ 1). Default n = 1

OUTPUTS

B

The value P_b(A, m, n)

A, m or n can be vectors, and in this case, the results will be vectors as well.

REFERENCES

  • G. Zeng, Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296

See also: erlangb, erlangc.


4.6 The M/M/inf System

The M/M/\infty system is a special case of M/M/m system with infinitely many identical servers (i.e., m = \infty). Each new request is always assigned to a new server, so that queueing never occurs. The M/M/\infty system is always stable.

Function File: [U, R, Q, X, p0] = qsmminf (lambda, mu)
Function File: pk = qsmminf (lambda, mu, k)

Compute utilization, response time, average number of requests and throughput for an infinite-server queue.

The M/M/\infty system has an infinite number of identical servers. Such a system is always stable (i.e., the mean queue length is always finite) for any arrival and service rates.

INPUTS

lambda

Arrival rate (lambda>0).

mu

Service rate (mu>0).

k

Number of requests in the system (k ≥ 0).

OUTPUTS

U

Traffic intensity (defined as \lambda/\mu). Note that this is different from the utilization, which in the case of M/M/\infty centers is always zero.

R

Service center response time.

Q

Average number of requests in the system (which is equal to the traffic intensity \lambda/\mu).

X

Throughput (which is always equal to X = lambda).

p0

Steady-state probability that there are no requests in the system

pk

Steady-state probability that there are k requests in the system (including the one being served).

If this function is called with less than three arguments, lambda and mu can be vectors of the same size. In this case, the results will be vectors as well.

REFERENCES

  • G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998, Section 6.4

See also: qsmm1,qsmmm,qsmmmk.


4.7 The M/M/1/K System

In a M/M/1/K finite capacity system there is a single server, and there can be at most K jobs at any time (including the job currently in service), K > 1. If a new request tries to join the system when there are already K other requests, the request is lost. The queue has K-1 slots. The M/M/1/K system is always stable, regardless of the arrival and service rates.

Function File: [U, R, Q, X, p0, pK] = qsmm1k (lambda, mu, K)
Function File: pn = qsmm1k (lambda, mu, K, n)

Compute utilization, response time, average number of requests and throughput for a M/M/1/K finite capacity system.

In a M/M/1/K queue there is a single server and a queue with finite capacity: the maximum number of requests in the system (including the request being served) is K, and the maximum queue length is therefore K-1.

INPUTS

lambda

Arrival rate (lambda>0).

mu

Service rate (mu>0).

K

Maximum number of requests allowed in the system (K ≥ 1).

n

Number of requests in the (0 ≤ n ≤ K).

OUTPUTS

U

Service center utilization, which is defined as U = 1-p0

R

Service center response time

Q

Average number of requests in the system

X

Service center throughput

p0

Steady-state probability that there are no requests in the system

pK

Steady-state probability that there are K requests in the system (i.e., that the system is full)

pn

Steady-state probability that there are n requests in the system (including the one being served).

If this function is called with less than four arguments, lambda, mu and K can be vectors of the same size. In this case, the results will be vectors as well.


See also: qsmm1,qsmminf,qsmmm.


4.8 The M/M/m/K System

The M/M/m/K finite capacity system is similar to the M/M/1/k system except that the number of servers is m, where 1 \leq m \leq K. The queue has K-m slots. The M/M/m/K system is always stable.

Function File: [U, R, Q, X, p0, pK] = qsmmmk (lambda, mu, m, K)
Function File: pn = qsmmmk (lambda, mu, m, K, n)

Compute utilization, response time, average number of requests and throughput for a M/M/m/K finite capacity system. In a M/M/m/K system there are m \geq 1 identical service centers sharing a fixed-capacity queue. At any time, at most K ≥ m requests can be in the system, including those being served. The maximum queue length is K-m. This function generates and solves the underlying CTMC.

INPUTS

lambda

Arrival rate (lambda>0)

mu

Service rate (mu>0)

m

Number of servers (m ≥ 1)

K

Maximum number of requests allowed in the system, including those being served (Km)

n

Number of requests in the (0 ≤ n ≤ K).

OUTPUTS

U

Service center utilization

R

Service center response time

Q

Average number of requests in the system

X

Service center throughput

p0

Steady-state probability that there are no requests in the system.

pK

Steady-state probability that there are K requests in the system (i.e., probability that the system is full).

pn

Steady-state probability that there are n requests in the system (including those being served).

If this function is called with less than five arguments, lambda, mu, m and K can be either scalars, or vectors of the same size. In this case, the results will be vectors as well.

REFERENCES

  • G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998, Section 6.6

See also: qsmm1,qsmminf,qsmmm.


4.9 The Asymmetric M/M/m System

The Asymmetric M/M/m system contains m servers connected to a single queue. Differently from the M/M/m system, in the asymmetric M/M/m each server may have a different service time.

Function File: [U, R, Q, X] = qsammm (lambda, mu)

Compute approximate utilization, response time, average number of requests in service and throughput for an asymmetric M/M/m queue. In this type of system there are m different servers connected to a single queue. Each server has its own (possibly different) service rate. If there is more than one server available, requests are routed to a randomly-chosen one.

INPUTS

lambda

Arrival rate (lambda>0)

mu

mu(i) is the service rate of server i, 1 ≤ i ≤ m. The system must be ergodic (lambda < sum(mu)).

OUTPUTS

U

Approximate service center utilization, U = \lambda / ( \sum_{i=1}^m \mu_i ).

R

Approximate service center response time

Q

Approximate number of requests in the system

X

Approximate system throughput. If the system is ergodic, X = lambda

REFERENCES

  • G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998

See also: qsmmm.


4.10 The M/G/1 System

Function File: [U, R, Q, X, p0] = qsmg1 (lambda, xavg, x2nd)

Compute utilization, response time, average number of requests and throughput for a M/G/1 system. The service time distribution is described by its mean xavg, and by its second moment x2nd. The computations are based on results from L. Kleinrock, Queuing Systems, Wiley, Vol 2, and Pollaczek-Khinchine formula.

INPUTS

lambda

Arrival rate

xavg

Average service time

x2nd

Second moment of service time distribution

OUTPUTS

U

Service center utilization

R

Service center response time

Q

Average number of requests in the system

X

Service center throughput

p0

Probability that there is not any request at system

lambda, xavg, t2nd can be vectors of the same size. In this case, the results will be vectors as well.


See also: qsmh1.


4.11 The M/H_m/1 System

Function File: [U, R, Q, X, p0] = qsmh1 (lambda, mu, alpha)

Compute utilization, response time, average number of requests and throughput for a M/H_m/1 system. In this system, the customer service times have hyper-exponential distribution:

       ___ m
       \
B(x) =  >  alpha(j) * (1-exp(-mu(j)*x))   x>0
       /__
           j=1

where \alpha_j is the probability that the request is served at phase j, in which case the average service rate is \mu_j. After completing service at phase j, for some j, the request exits the system.

INPUTS

lambda

Arrival rate

mu

mu(j) is the phase j service rate. The total number of phases m is length(mu).

alpha

alpha(j) is the probability that a request is served at phase j. alpha must have the same size as mu.

OUTPUTS

U

Service center utilization

R

Service center response time

Q

Average number of requests in the system

X

Service center throughput


5 Queueing Networks


5.1 Introduction to QNs

Queueing Networks (QN) are a simple modeling notation that can be used to analyze many kinds of systems. In its simplest form, a QN is made of K service centers; center k has a queue connected to m_k (usually identical) servers. Arriving customers (requests) join the queue if there is at least one slot available. Requests are served according to a (de)queueing policy (e.g., FIFO). After service completes, requests leave the server and can join another queue or exit from the system.

Service centers where m_k = \infty are called delay centers or infinite servers. In this kind of centers, there is always one available server, so that queueing never occurs.

Requests join the queue according to a queueing policy, such as:

FCFS

First-Come-First-Served

LCFS-PR

Last-Come-First-Served, Preemptive Resume

PS

Processor Sharing

IS

Infinite Server (m_k = \infty).

Queueing networks can be open or closed. In open networks there is an infinite population of requests; new customers are generated outside the system, and eventually leave the network. In closed networks there is a fixed population of request that never leave the system.

Queueing models can have a single request class (single class models), meaning that all requests behave in the same way (e.g., they spend the same average time on each particular server). In multiple class models there are multiple request classes, each with its own parameters (e.g., with different service times or different routing probabilities). Furthermore, in multiclass models there can be open and closed chains of requests at the same time.

A particular class of QN models, product-form networks, is of particular interest. Product-form networks fulfill the following assumptions:

  • The network can consist of open and closed job classes.
  • The following queueing disciplines are allowed: FCFS, PS, LCFS-PR and IS.
  • Service times for FCFS nodes must be exponentially distributed and class-independent. Service centers at PS, LCFS-PR and IS nodes can have any kind of service time distribution with a rational Laplace transform. Furthermore, for PS, LCFS-PR and IS nodes, different classes of customers can have different service times.
  • The service rate of an FCFS node is only allowed to depend on the number of jobs at this node; in a PS, LCFS-PR and IS node the service rate for a particular job class can also depend on the number of jobs of that class at the node.
  • In open networks two kinds of arrival processes are allowed: i) the arrival process is Poisson, with arrival rate \lambda that can depend on the number of jobs in the network. ii) the arrival process consists of C independent Poisson arrival streams where the C job sources are assigned to the C chains; the arrival rate can be load dependent.

Product-form networks are attractive because steady-state performance measures can be efficiently computed.


5.2 Single Class Models

In single class models, all requests are indistinguishable and belong to the same class. This means that every request has the same average service time, and all requests move through the system with the same routing probabilities.

Model Inputs

{lambda}_k

(Open models only) External arrival rate to service center k.

lambda

(Open models only) Overall external arrival rate to the system as a whole: \lambda = \sum_k \lambda_k.

N

(Closed models only) Total number of requests in the system.

S_k

Mean service time at center k. S_k is the average time elapsed from service start to service completion at center k.

P_{i, j}

Routing probability matrix. {\bf P} = [P_{i, j}] is a K \times K matrix where P_{i, j} is the probability that a request completing service at center i is routed to center j. The probability that a request leaves the system after being served at center i is \left(1-\sum_{j=1}^K P_{i, j}\right).

V_k

Mean number of visits to center k (also called visit ratio or relative arrival rate).

Model Outputs

U_k

Utilization of service center k. The utilization is defined as the fraction of time in which the resource is busy (i.e., the server is processing requests). If center k is a single-server or multiserver node, then 0 ≤ U_k ≤ 1. If center k is an infinite server node (delay center), then U_k denotes the traffic intensity and is defined as U_k = X_k S_k; in this case the utilization may be greater than one.

R_k

Average response time of service center k, defined as the mean time between the arrival of a request in the queue and service completion of the same request.

Q_k

Average number of requests in center k; this includes both the requests in the queue and those being served.

X_k

Throughput of service center k. The throughput is the rate of job completions, i.e., the average number of jobs completed over a given time interval.

Given the output parameters above, additional performance measures can be computed:

X

System throughput, X = X_k / V_k for any k for which V_k \neq 0

R

System response time, R = \sum_{k=1}^K R_k V_k

Q

Average number of requests in the system, Q = \sum_{k=1}^K Q_k; for closed systems, this can be written as Q = N-XZ;

For open, single class models, the scalar \lambda denotes the external arrival rate of requests to the system. The average number of visits V_j satisfy the following equation:

                  K
                 ___
                \
V_j = P_(0, j) + >   V_i P_(i, j)    j=1,...,K
                /___
                 i=1

where P_{0, j} is the probability that an external request goes to center j. If we denote with \lambda_j the external arrival rate to center j, and \lambda = \sum_j \lambda_j the overall external arrival rate, then P_{0, j} = \lambda_j / \lambda.

For closed models, the visit ratios satisfy the following equation:

/
|         K
|        ___
|       \
| V_j =  >   V_i P_(i, j)     j=1,...,K
|       /___
|        i=1
|
| V_r = 1                     for a selected reference station r
\

Note that the set of traffic equations V_j = \sum_{i=1}^K V_i P_{i, j} alone can only be solved up to a multiplicative constant; to get a unique solution we impose an additional constraint V_r = 1 for some 1 ≤ r ≤ K. This constraint is equivalent to defining station r as the reference station; the default is r=1, see doc-qncsvisits. A job that returns to the reference station is assumed to have completed its activity cycle. The network throughput is set to the throughput of the reference station.

Function File: V = qncsvisits (P)
Function File: V = qncsvisits (P, r)

Compute the mean number of visits to the service centers of a single class, closed network with K service centers.

INPUTS

P(i,j)

probability that a request which completed service at center i is routed to center j (K \times K matrix). For closed networks it must hold that sum(P,2)==1. The routing graph must be strongly connected, meaning that each node must be reachable from every other node.

r

Index of the reference station, r \in {1, …, K}; Default r=1. The traffic equations are solved by imposing the condition V(r) = 1. A request returning to the reference station completes its activity cycle.

OUTPUTS

V(k)

average number of visits to service center k, assuming r as the reference station.

Function File: V = qnosvisits (P, lambda)

Compute the average number of visits to the service centers of a single class open Queueing Network with K service centers.

INPUTS

P(i,j)

is the probability that a request which completed service at center i is routed to center j (K \times K matrix).

lambda(k)

external arrival rate to center k.

OUTPUTS

V(k)

average number of visits to server k.

EXAMPLE

qn_closed_single

Figure 5.1: Closed network with a single class of requests

Figure 5.1 shows a closed queueing network with a single class of requests. The network has three service centers, labeled CPU, Disk1 and Disk2, and is known as a central server model of a computer system. Requests spend some time at the CPU, which is represented by a PS (Processor Sharing) node. After that, requests are routed to Disk1 with probability 0.3, and to Disk2 with probability 0.7. Both Disk1 and Disk2 are FCFS nodes.

If we label the servers as CPU=1, Disk1=2, Disk2=3, we can define the routing matrix as follows:

    / 0  0.3  0.7 \
P = | 1  0    0   |
    \ 1  0    0   /

The visit ratios V, using station 1 as the reference station, can be computed with:

 P = [0 0.3 0.7; ...
      1 0   0  ; ...
      1 0   0  ];
 V = qncsvisits(P)
   ⇒ V = 1.00000   0.30000   0.70000

EXAMPLE

qn_open_single

Figure 5.2: Open Queueing Network with a single class of requests

Figure 5.2 shows a open QN with a single class of requests. The network has the same structure as the one in Figure 5.1, with the difference that here we have a stream of jobs arriving from outside the system, at a rate \lambda. After service completion at the CPU, a job can leave the system with probability 0.2, or be transferred to other nodes with the probabilities shown in the figure.

The routing matrix is

    / 0  0.3  0.5 \
P = | 1  0    0   |
    \ 1  0    0   /

If we let \lambda = 1.2, we can compute the visit ratios V as follows:

 p = 0.3;
 lambda = 1.2
 P = [0 0.3 0.5; 1 0 0; 1 0 0];
 V = qnosvisits(P,[1.2 0 0])
   ⇒ V = 5.0000   1.5000   2.5000

Function qnosvisits expects a vector with K elements as a second parameter, for open networks only. The vector contains the arrival rates at each individual node; since in our example external arrivals exist only for node S_1 with rate \lambda = 1.2, the second parameter is [1.2, 0, 0].

5.2.1 Open Networks

Jackson networks satisfy the following conditions:

  • There is only one job class in the network; the total number of jobs in the system is unbounded.
  • There are K service centers in the network. Each service center may have Poisson arrivals from outside the system. A job can leave the system from any node.
  • Arrival rates as well as routing probabilities are independent from the number of nodes in the network.
  • External arrivals and service times at the service centers are exponentially distributed, and in general can be load-dependent.
  • Service discipline at each node is FCFS

We define the joint probability vector \pi(n_1, …, n_K) as the steady-state probability that there are n_k requests at service center k, for all k=1, …, N. Jackson networks have the property that the joint probability is the product of the marginal probabilities \pi_k:

joint_prob = prod( pi )

where \pi_k(n_k) is the steady-state probability that there are n_k requests at service center k.

Function File: [U, R, Q, X] = qnos (lambda, S, V)
Function File: [U, R, Q, X] = qnos (lambda, S, V, m)

Analyze open, single class BCMP queueing networks with K service centers.

This function works for a subset of BCMP single-class open networks satisfying the following properties:

  • The allowed service disciplines at network nodes are: FCFS, PS, LCFS-PR, IS (infinite server);
  • Service times are exponentially distributed and load-independent;
  • Center k can consist of m(k) ≥ 1 identical servers.
  • Routing is load-independent

INPUTS

lambda

Overall external arrival rate (lambda>0).

S(k)

average service time at center k (S(k)>0).

V(k)

average number of visits to center k (V(k) ≥ 0).

m(k)

number of servers at center i. If m(k) < 1, enter k is a delay center (IS); otherwise it is a regular queueing center with m(k) servers. Default is m(k) = 1 for all k.

OUTPUTS

U(k)

If k is a queueing center, U(k) is the utilization of center k. If k is an IS node, then U(k) is the traffic intensity defined as X(k)*S(k).

R(k)

center k average response time.

Q(k)

average number of requests at center k.

X(k)

center k throughput.

REFERENCES

  • G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998

See also: qnopen,qnclosed,qnosvisits.

From the results computed by this function, it is possible to derive other quantities of interest as follows:

  • System Response Time: The overall system response time can be computed as R_s = dot(V,R);
  • Average number of requests: The average number of requests in the system can be computed as: Q_avg = sum(Q)

EXAMPLE

 lambda = 3;
 V = [16 7 8];
 S = [0.01 0.02 0.03];
 [U R Q X] = qnos( lambda, S, V );
 R_s = dot(R,V) # System response time
 N = sum(Q) # Average number in system
-| R_s =  1.4062
-| N =  4.2186

5.2.2 Closed Networks

Function File: [U, R, Q, X, G] = qncsmva (N, S, V)
Function File: [U, R, Q, X, G] = qncsmva (N, S, V, m)
Function File: [U, R, Q, X, G] = qncsmva (N, S, V, m, Z)

Analyze closed, single class queueing networks using the exact Mean Value Analysis (MVA) algorithm.

The following queueing disciplines are supported: FCFS, LCFS-PR, PS and IS (Infinite Server). This function supports fixed-rate service centers or multiple server nodes. For general load-dependent service centers, use the function qncsmvald instead.

Additionally, the normalization constant G(n), n=0, …, N is computed; G(n) can be used in conjunction with the BCMP theorem to compute steady-state probabilities.

INPUTS

N

Population size (number of requests in the system, N ≥ 0). If N == 0, this function returns U = R = Q = X = 0

S(k)

mean service time at center k (S(k) ≥ 0).

V(k)

average number of visits to service center k (V(k) ≥ 0).

Z

External delay for customers (Z ≥ 0). Default is 0.

m(k)

number of servers at center k (if m is a scalar, all centers have that number of servers). If m(k) < 1, center k is a delay center (IS); otherwise it is a regular queueing center (FCFS, LCFS-PR or PS) with m(k) servers. Default is m(k) = 1 for all k (each service center has a single server).

OUTPUTS

U(k)

If k is a FCFS, LCFS-PR or PS node (m(k) ≥ 1), then U(k) is the utilization of center k, 0 ≤ U(k) ≤ 1. If k is an IS node (m(k) < 1), then U(k) is the traffic intensity defined as X(k)*S(k). In this case the value of U(k) may be greater than one.

R(k)

center k response time. The Residence Time at center k is R(k) * V(k). The system response time Rsys can be computed either as Rsys = N/Xsys - Z or as Rsys = dot(R,V)

Q(k)

average number of requests at center k. The number of requests in the system can be computed either as sum(Q), or using the formula N-Xsys*Z.

X(k)

center K throughput. The system throughput Xsys can be computed as Xsys = X(1) / V(1)

G(n)

Normalization constants. G(n+1) contains the value of the normalization constant G(n), n=0, …, N as array indexes in Octave start from 1. G(n) can be used in conjunction with the BCMP theorem to compute steady-state probabilities.

NOTES

In presence of load-dependent servers (i.e., if m(k)>1 for some k), the MVA algorithm is known to be numerically unstable. Generally, this issue manifests itself as negative values for the response times or utilizations. This is not a problem of the queueing toolbox, but of the MVA algorithm, and has currently no known solution. This function prints a warning if numerical problems are detected; the warning can be disabled with the command warning("off", "qn:numerical-instability").

REFERENCES

  • M. Reiser and S. S. Lavenberg, Mean-Value Analysis of Closed Multichain Queuing Networks, Journal of the ACM, vol. 27, n. 2, April 1980, pp. 313–322. 10.1145/322186.322195

This implementation is described in R. Jain , The Art of Computer Systems Performance Analysis, Wiley, 1991, p. 577. Multi-server nodes are treated according to G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998, Section 8.2.1, "Single Class Queueing Networks".


See also: qncsmvald,qncscmva.

EXAMPLE

 S = [ 0.125 0.3 0.2 ];
 V = [ 16 10 5 ];
 N = 20;
 m = ones(1,3);
 Z = 4;
 [U R Q X] = qncsmva(N,S,V,m,Z);
 X_s = X(1)/V(1); # System throughput
 R_s = dot(R,V); # System response time
 printf("\t    Util      Qlen     RespT      Tput\n");
 printf("\t--------  --------  --------  --------\n");
 for k=1:length(S)
   printf("Dev%d\t%8.4f  %8.4f  %8.4f  %8.4f\n", k, U(k), Q(k), R(k), X(k) );
 endfor
 printf("\nSystem\t          %8.4f  %8.4f  %8.4f\n\n", N-X_s*Z, R_s, X_s );
Function File: [U, R, Q, X] = qncsmvald (N, S, V)
Function File: [U, R, Q, X] = qncsmvald (N, S, V, Z)

Mean Value Analysis algorithm for closed, single class queueing networks with K service centers and load-dependent service times. This function supports FCFS, LCFS-PR, PS and IS nodes. For networks with only fixed-rate centers and multiple-server nodes, the function qncsmva is more efficient.

INPUTS

N

Population size (number of requests in the system, N ≥ 0). If N == 0, this function returns U = R = Q = X = 0

S(k,n)

mean service time at center k where there are n requests, 1 ≤ n ≤ N. S(k,n) = 1 / \mu_{k}(n), where \mu_{k}(n) is the service rate of center k when there are n requests.

V(k)

average number of visits to service center k (V(k) ≥ 0).

Z

external delay ("think time", Z ≥ 0); default 0.

OUTPUTS

U(k)

utilization of service center k. The utilization is defined as the probability that service center k is not empty, that is, U_k = 1-\pi_k(0) where \pi_k(0) is the steady-state probability that there are 0 jobs at service center k.

R(k)

response time on service center k.

Q(k)

average number of requests in service center k.

X(k)

throughput of service center k.

NOTES

In presence of load-dependent servers, the MVA algorithm is known to be numerically unstable. Generally this problem manifests itself as negative response times or utilization.

REFERENCES

  • M. Reiser and S. S. Lavenberg, Mean-Value Analysis of Closed Multichain Queuing Networks, Journal of the ACM, vol. 27, n. 2, April 1980, pp. 313–322. 10.1145/322186.322195

This implementation is described in G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998, Section 8.2.4.1, “Networks with Load-Dependent Service: Closed Networks”.


See also: qncsmva.

Function File: [U, R, Q, X] = qncscmva (N, S, Sld, V)
Function File: [U, R, Q, X] = qncscmva (N, S, Sld, V, Z)

Conditional MVA (CMVA) algorithm, a numerically stable variant of MVA. This function supports a network of M ≥ 1 service centers and a single delay center. Servers 1, …, (M-1) are load-independent; server M is load-dependent.

INPUTS

N

Number of requests in the system, N ≥ 0. If N == 0, this function returns U = R = Q = X = 0

S(k)

mean service time on server k = 1, …, (M-1) (S(k) > 0). If there are no fixed-rate servers, then S = []

Sld(n)

inverse service rate at server M (the load-dependent server) when there are n requests, n=1, …, N. Sld(n) = 1 / \mu(n).

V(k)

average number of visits to service center k=1, …, M, where V(k) ≥ 0. V(1:M-1) are the visit rates to the fixed rate servers; V(M) is the visit rate to the load dependent server.

Z

External delay for customers (Z ≥ 0). Default is 0.

OUTPUTS

U(k)

center k utilization (k=1, …, M)

R(k)

response time of center k (k=1, …, M). The system response time Rsys can be computed as Rsys = N/Xsys - Z

Q(k)

average number of requests at center k (k=1, …, M).

X(k)

center k throughput (k=1, …, M).

REFERENCES

  • G. Casale. A note on stable flow-equivalent aggregation in closed networks. Queueing Syst. Theory Appl., 60:193–-202, December 2008, 10.1007/s11134-008-9093-6
Function File: [U, R, Q, X] = qncsmvaap (N, S, V)
Function File: [U, R, Q, X] = qncsmvaap (N, S, V, m)
Function File: [U, R, Q, X] = qncsmvaap (N, S, V, m, Z)
Function File: [U, R, Q, X] = qncsmvaap (N, S, V, m, Z, tol)
Function File: [U, R, Q, X] = qncsmvaap (N, S, V, m, Z, tol, iter_max)

Analyze closed, single class queueing networks using the Approximate Mean Value Analysis (MVA) algorithm. This function is based on approximating the number of customers seen at center k when a new request arrives as Q_k(N) \times (N-1)/N. This function only handles single-server and delay centers; if your network contains general load-dependent service centers, use the function qncsmvald instead.

INPUTS

N

Population size (number of requests in the system, N > 0).

S(k)

mean service time on server k (S(k)>0).

V(k)

average number of visits to service center k (V(k) ≥ 0).

m(k)

number of servers at center k (if m is a scalar, all centers have that number of servers). If m(k) < 1, center k is a delay center (IS); if m(k) == 1, center k is a regular queueing center (FCFS, LCFS-PR or PS) with one server (default). This function does not support multiple server nodes (m(k) > 1).

Z

External delay for customers (Z ≥ 0). Default is 0.

tol

Stopping tolerance. The algorithm stops when the maximum relative difference between the new and old value of the queue lengths Q becomes less than the tolerance. Default is 10^{-5}.

iter_max

Maximum number of iterations (iter_max>0. The function aborts if convergenge is not reached within the maximum number of iterations. Default is 100.

OUTPUTS

U(k)

If k is a FCFS, LCFS-PR or PS node (m(k) == 1), then U(k) is the utilization of center k. If k is an IS node (m(k) < 1), then U(k) is the traffic intensity defined as X(k)*S(k).

R(k)

response time at center k. The system response time Rsys can be computed as Rsys = N/Xsys - Z

Q(k)

average number of requests at center k. The number of requests in the system can be computed either as sum(Q), or using the formula N-Xsys*Z.

X(k)

center k throughput. The system throughput Xsys can be computed as Xsys = X(1) / V(1)

REFERENCES

This implementation is based on Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, Quantitative System Performance: Computer System Analysis Using Queueing Network Models, Prentice Hall, 1984. http://www.cs.washington.edu/homes/lazowska/qsp/. In particular, see section 6.4.2.2 ("Approximate Solution Techniques").


See also: qncsmva,qncsmvald.

According to the BCMP theorem, the state probability of a closed single class queueing network with K nodes and N requests can be expressed as:

n = [n1, … nK]; population vector
p = 1/G(N+1) \prod F(k,k);

Here \pi(n_1, …, n_K) is the joint probability of having n_k requests at node k, for all k=1, …, K; we have that \sum_{k=1}^K n_k = N

The convolution algorithms computes the normalization constants {\bf G} = \left[G(0), …, G(N)\right] for single-class, closed networks with N requests. The normalization constants are returned as vector G=[G(1), … G(N+1)] where G(i+1) is the value of G(i) (remember that Octave uses 1-base vectors). The normalization constant can be used to compute all performance measures of interest (utilization, average response time and so on).

queueing implements the convolution algorithm, in the function qncsconv and qncsconvld. The first one supports single-station nodes, multiple-station nodes and IS nodes. The second one supports networks with general load-dependent service centers.

Function File: [U, R, Q, X, G] = qncsconv (N, S, V)
Function File: [U, R, Q, X, G] = qncsconv (N, S, V, m)

Analyze product-form, single class closed networks with K service centers using the convolution algorithm.

Load-independent service centers, multiple servers (M/M/m queues) and IS nodes are supported. For general load-dependent service centers, use qncsconvld instead.

INPUTS

N

Number of requests in the system (N>0).

S(k)

average service time on center k (S(k) ≥ 0).

V(k)

visit count of service center k (V(k) ≥ 0).

m(k)

number of servers at center k. If m(k) < 1, center k is a delay center (IS); if m(k) ≥ 1, center k it is a regular M/M/m queueing center with m(k) identical servers. Default is m(k) = 1 for all k.

OUTPUT

U(k)

center k utilization. For IS nodes, U(k) is the traffic intensity X(k) * S(k).

R(k)

average response time of center k.

Q(k)

average number of customers at center k.

X(k)

throughput of center k.

G(n)

Vector of normalization constants. G(n+1) contains the value of the normalization constant with n requests G(n), n=0, …, N.

NOTE

For a network with K service centers and N requests, this implementation of the convolution algorithm has time and space complexity O(NK).

REFERENCES

  • Jeffrey P. Buzen, Computational Algorithms for Closed Queueing Networks with Exponential Servers, Communications of the ACM, volume 16, number 9, September 1973, pp. 527–531. 10.1145/362342.362345

This implementation is based on G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998, pp. 313–317.


See also: qncsconvld.

EXAMPLE

The normalization constant G can be used to compute the steady-state probabilities for a closed single class product-form Queueing Network with K nodes and N requests. Let n = [n_1, …, n_K] be a valid population vector, \sum_{k=1}^K n_k = N. Then, the steady-state probability p(k) to have n(k) requests at service center k can be computed as:

 n = [1 2 0];
 N = sum(n); # Total population size
 S = [ 1/0.8 1/0.6 1/0.4 ];
 m = [ 2 3 1 ];
 V = [ 1 .667 .2 ];
 [U R Q X G] = qncsconv( N, S, V, m );
 p = [0 0 0]; # initialize p
 # Compute the probability to have n(k) jobs at service center k
 for k=1:3
   p(k) = (V(k)*S(k))^n(k) / G(N+1) * ...
          (G(N-n(k)+1) - V(k)*S(k)*G(N-n(k)) );
   printf("Prob( n(%d) = %d )=%f\n", k, n(k), p(k) );
 endfor
-| Prob( n(1) = 1 ) = 0.17975
-| Prob( n(2) = 2 ) = 0.48404
-| Prob( n(3) = 0 ) = 0.52779

(recall that G(N+1) represents G(N), since in Octave array indices start at one).

Function File: [U, R, Q, X, G] = qncsconvld (N, S, V)

Convolution algorithm for product-form, single-class closed queueing networks with K general load-dependent service centers.

This function computes steady-state performance measures for single-class, closed networks with load-dependent service centers using the convolution algorithm; the normalization constants are also computed. The normalization constants are returned as vector G=[G(1), …, G(N+1)] where G(i+1) is the value of G(i).

INPUTS

N

Number of requests in the system (N>0).

S(k,n)

mean service time at center k where there are n requests, 1 ≤ n ≤ N. S(k,n) = 1 / \mu_{k,n}, where \mu_{k,n} is the service rate of center k when there are n requests.

V(k)

visit count of service center k (V(k) ≥ 0). The length of V is the number of servers K in the network.

OUTPUT

U(k)

center k utilization.

R(k)

average response time at center k.

Q(k)

average number of requests in center k.

X(k)

center k throughput.

G(n)

Normalization constants (vector). G(n+1) corresponds to G(n), as array indexes in Octave start from 1.

REFERENCES

  • Herb Schwetman, Some Computational Aspects of Queueing Network Models, Technical Report CSD-TR-354, Department of Computer Sciences, Purdue University, February 1981 (revised).
  • M. Reiser, H. Kobayashi, On The Convolution Algorithm for Separable Queueing Networks, In Proceedings of the 1976 ACM SIGMETRICS Conference on Computer Performance Modeling Measurement and Evaluation (Cambridge, Massachusetts, United States, March 29–31, 1976). SIGMETRICS ’76. ACM, New York, NY, pp. 109–117. 10.1145/800200.806187

This implementation is based on G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998, pp. 313–317. Function qncsconvld is slightly different from the version described in Bolch et al. because it supports general load-dependent centers (while the version in the book does not). The modification is in the definition of function F() in qncsconvld which has been made similar to function f_i defined in Schwetman, Some Computational Aspects of Queueing Network Models.


See also: qncsconv.

5.2.3 Non Product-Form QNs

Function File: [U, R, Q, X] = qncsmvablo (N, S, M, P )

Approximate MVA algorithm for closed queueing networks with blocking.

INPUTS

N

number of requests in the system. N must be strictly greater than zero, and less than the overall network capacity: 0 < N < sum(M).

S(k)

average service time on server k (S(k) > 0).

M(k)

capacity of center k. The capacity is the maximum number of requests in a service center, including the request in service (M(k) ≥ 1).

P(i,j)

probability that a request which completes service at server i will be transferred to server j.

OUTPUTS

U(k)

center k utilization.

R(k)

average response time of service center k.

Q(k)

average number of requests in service center k (including the request in service).

X(k)

center k throughput.

REFERENCES

  • Ian F. Akyildiz, Mean Value Analysis for Blocking Queueing Networks, IEEE Transactions on Software Engineering, vol. 14, n. 2, april 1988, pp. 418–428. 10.1109/32.4663

See also: qnopen, qnclosed.

Function File: [U, R, Q, X] = qnmarkov (lambda, S, C, P)
Function File: [U, R, Q, X] = qnmarkov (lambda, S, C, P, m)
Function File: [U, R, Q, X] = qnmarkov (N, S, C, P)
Function File: [U, R, Q, X] = qnmarkov (N, S, C, P, m)

Compute utilization, response time, average queue length and throughput for open or closed queueing networks with finite capacity and a single class of requests. Blocking type is Repetitive-Service (RS). This function explicitly generates and solve the underlying Markov chain, and thus might require a large amount of memory.

More specifically, networks which can me analyzed by this function have the following properties:

  • There exists only a single class of customers.
  • The network has K service centers. Center k \in {1, …, K} has m_k > 0 servers, and has a total (finite) capacity of C_k \geq m_k which includes both buffer space and servers. The buffer space at service center k is therefore C_k - m_k.
  • The network can be open, with external arrival rate to center k equal to \lambda_k, or closed with fixed population size N. For closed networks, the population size N must be strictly less than the network capacity: N < \sum_{k=1}^K C_k.
  • Average service times are load-independent.
  • P_{i, j} is the probability that requests completing execution at center i are transferred to center j, i \neq j. For open networks, a request may leave the system from any node i with probability 1-\sum_{j=1}^K P_{i, j}.
  • Blocking type is Repetitive-Service (RS). Service center j is saturated if the number of requests is equal to its capacity C_j. Under the RS blocking discipline, a request completing service at center i which is being transferred to a saturated server j is put back at the end of the queue of i and will receive service again. Center i then processes the next request in queue. External arrivals to a saturated servers are dropped.

INPUTS

lambda(k)
N

If the first argument is a vector lambda, it is considered to be the external arrival rate lambda(k) ≥ 0 to service center k of an open network. If the first argument is a scalar, it is considered as the population size N of a closed network; in this case N must be strictly less than the network capacity: N < sum(C).

S(k)

average service time at service center k

C(k)

capacity of service center k. The capacity includes both the buffer and server space m(k). Thus the buffer space is C(k)-m(k).

P(i,j)

transition probability from service center i to service center j.

m(k)

number of servers at service center k. Note that m(k) ≥ C(k) for each k. If m is omitted, all service centers are assumed to have a single server (m(k) = 1 for all k).

OUTPUTS

U(k)

center k utilization.

R(k)

response time on service center k.

Q(k)

average number of customers in the service center k, including the request in service.

X(k)

throughput of service center k.

NOTES

The space complexity of this implementation is O(\prod_{k=1}^K (C_k + 1)^2). The time complexity is dominated by the time needed to solve a linear system with \prod_{k=1}^K (C_k + 1) unknowns.


5.3 Multiple Class Models

In multiple class queueing models, we assume that there exist C different classes of requests. Each request from class c spends on average time S_{c, k} in service at center k. For open models, we denote with {\bf \lambda} = \lambda_{c, k} the arrival rates, where \lambda_{c, k} is the external arrival rate of class c requests at center k. For closed models, we denote with {\bf N} = \left[N_1, …, N_C\right] the population vector, where N_c is the number of class c requests in the system.

The transition probability matrix for multiple class networks is a C \times K \times C \times K matrix {\bf P} = [P_{r, i, s, j}] where P_{r, i, s, j} is the probability that a class r request which completes service at center i will join server j as a class s request.

Model input and outputs can be adjusted by adding additional indexes for the customer classes.

Model Inputs

lambda_{c, k}

(open networks) External arrival rate of class-c requests to service center k

lambda

(open networks) Overall external arrival rate to the whole system: \lambda = \sum_{c=1}^C \sum_{k=1}^K \lambda_{c, k}

N_c

(closed networks) Number of class c requests in the system.

S_{c, k}

Average service time. S_{c, k} is the average service time on service center k for class c requests.

P_{r, i, s, j}

Routing probability matrix. {\bf P} = [P_{r, i, s, j}] is a C \times K \times C \times K matrix such that P_{r, i, s, j} is the probability that a class r request which completes service at server i will move to server j as a class s request.

V_{c, k}

Mean number of visits of class c requests to center k.

Model Outputs

U_{c, k}

Utilization of service center k by class c requests. The utilization is defined as the fraction of time in which the resource is busy (i.e., the server is processing requests). If center k is a single-server or multiserver node, then 0 ≤ U_{c, k} ≤ 1. If center k is an infinite server node (delay center), then U_{c, k} denotes the traffic intensity and is defined as U_{c, k} = X_{c, k} S_{c, k}; in this case the utilization may be greater than one.

R_{c, k}

Average response time experienced by class c requests on service center k. The average response time is defined as the average time between the arrival of a customer in the queue, and the completion of service.

Q_{c, k}

Average number of class c requests on service center k. This includes both the requests in the queue, and the request being served.

X_{c, k}

Throughput of service center k for class c requests. The throughput is defined as the rate of completion of class c requests.

It is possible to define aggregate performance measures as follows:

U_k

Utilization of service center k: Uk = sum(U,k);

R_c

System response time for class c requests: Rc = sum( V.*R, 1 );

Q_c

Average number of class c requests in the system: Qc = sum( Q, 2 );

X_c

Class c throughput: X(c) = X(c,k) ./ V(c,k); for any k for which V(c,k) != 0

For closed networks, we can define the visit ratios V_{s, j} for class s customers at service center j as follows:

V_sj = sum_r sum_i V_ri P_risj s=1,...,C, j=1,...,K V_s r_s = 1 s=1,...,C

where r_s is the class s reference station. Similarly to single class models, the traffic equation for closed multiclass networks can be solved up to multiplicative constants unless we choose one reference station for each closed class and set its visit ratio to 1.

For open networks the traffic equations are as follows:

V_sj = P_0sj + sum_r sum_i V_ri P_risj s=1,...,C, j=1,...,K

where P_{0, s, j} is the probability that an external arrival goes to service center j as a class-s request. If \lambda_{s, j} is the external arrival rate of class s requests to service center j, and \lambda = \sum_s \sum_j \lambda_{s, j} is the overall external arrival rate, then P_{0, s, j} = \lambda_{s, j} / \lambda.

Function File: [V ch] = qncmvisits (P)
Function File: [V ch] = qncmvisits (P, r)

Compute the average number of visits for the nodes of a closed multiclass network with K service centers and C customer classes.

INPUTS

P(r,i,s,j)

probability that a class r request which completed service at center i is routed to center j as a class s request. Class switching is allowed.

r(c)

index of class c reference station, r(c) \in {1, …, K}, 1 ≤ c ≤ C. The class c visit count to server r(c) (V(c,r(c))) is conventionally set to 1. The reference station serves two purposes: (i) its throughput is assumed to be the system throughput, and (ii) a job returning to the reference station is assumed to have completed one cycle. Default is to consider station 1 as the reference station for all classes.

OUTPUTS

V(c,i)

number of visits of class c requests at center i.

ch(c)

chain number that class c belongs to. Different classes can belong to the same chain. Chains are numbered sequentially starting from 1 (1, 2, …). The total number of chains is max(ch).

Function File: V = qnomvisits (P, lambda)

Compute the visit ratios to the service centers of an open multiclass network with K service centers and C customer classes.

INPUTS

P(r,i,s,j)

probability that a class r request which completed service at center i is routed to center j as a class s request. Class switching is supported.

lambda(r,i)

external arrival rate of class r requests to center i.

OUTPUTS

V(r,i)

visit ratio of class r requests at center i.

5.3.1 Open Networks

Function File: [U, R, Q, X] = qnom (lambda, S, V)
Function File: [U, R, Q, X] = qnom (lambda, S, V, m)
Function File: [U, R, Q, X] = qnom (lambda, S, P)
Function File: [U, R, Q, X] = qnom (lambda, S, P, m)

Exact analysis of open, multiple-class BCMP networks. The network can be made of single-server queueing centers (FCFS, LCFS-PR or PS) or delay centers (IS). This function assumes a network with K service centers and C customer classes.

INPUTS

lambda(c)

If this function is invoked as qnom(lambda, S, V, …), then lambda(c) is the external arrival rate of class c customers (lambda(c) ≥ 0). If this function is invoked as qnom(lambda, S, P, …), then lambda(c,k) is the external arrival rate of class c customers at center k (lambda(c,k) ≥ 0).

S(c,k)

mean service time of class c customers on the service center k (S(c,k)>0). For FCFS nodes, mean service times must be class-independent.

V(c,k)

visit ratio of class c customers to service center k (V(c,k) ≥ 0 ). If you pass this argument, class switching is not allowed

P(r,i,s,j)

probability that a class r job completing service at center i is routed to center j as a class s job. If you pass argument P, class switching is allowed; however, all servers must be fixed-rate or infinite-server nodes (m(k) ≤ 1 for all k).

m(k)

number of servers at center k. If m(k) < 1, enter k is a delay center (IS); otherwise it is a regular queueing center with m(k) servers. Default is m(k) = 1 for all k.

OUTPUTS

U(c,k)

If k is a queueing center, then U(c,k) is the class c utilization of center k. If k is an IS node, then U(c,k) is the class c traffic intensity defined as X(c,k)*S(c,k).

R(c,k)

class c response time at center k. The system response time for class c requests can be computed as dot(R, V, 2).

Q(c,k)

average number of class c requests at center k. The average number of class c requests in the system Qc can be computed as Qc = sum(Q, 2)

X(c,k)

class c throughput at center k.

NOTES

If the function call specifies the visit ratios V, class switching is not allowed. If the function call specifies the routing probability matrix P, then class switching is allowed; however, all nodes are restricted to be fixed rate servers or delay centers: multiple-server and general load-dependent centers are not supported. Note that the meaning of parameter lambda is different from one case to the other (see below).

REFERENCES

  • Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, Quantitative System Performance: Computer System Analysis Using Queueing Network Models, Prentice Hall, 1984. http://www.cs.washington.edu/homes/lazowska/qsp/. In particular, see section 7.4.1 ("Open Model Solution Techniques").

See also: qnopen,qnos,qnomvisits.

5.3.2 Closed Networks

Function File: pop_mix = qncmpopmix (k, N)

Return the set of population mixes for a closed multiclass queueing network with exactly k customers. Specifically, given a closed multiclass QN with C customer classes, where there are N(c) class c requests, c = 1, …, C a k-mix M is a vector of length C with the following properties:

  • 0 ≤ M_c ≤ N(c) for all c = 1, …, C;
  • \sum_{c=1}^C M_c = k

In other words, a k-mix is an allocation of k requests to C classes such that the number of requests assigned to class c does not exceed the maximum value N(c).

pop_mix is a matrix with C columns, such that each row represents a valid mix.

INPUTS

k

Size of the requested mix (scalar, k ≥ 0).

N(c)

number of class c requests (k ≤ sum(N)).

OUTPUTS

pop_mix(i,c)

number of class c requests in the i-th population mix. The number of mixes is rows(pop_mix).

If you are interested in the number of k-mixes only, you can use the funcion qnmvapop.

REFERENCES

  • Herb Schwetman, Implementing the Mean Value Algorithm for the Solution of Queueing Network Models, Technical Report 80-355, Department of Computer Sciences, Purdue University, revised February 15, 1982.

The slightly different problem of enumerating all tuples k_1, …, k_N such that \sum_i k_i = k and k_i ≥ 0, for a given k ≥ 0 has been described in S. Santini, Computing the Indices for a Complex Summation, unpublished report, available at http://arantxa.ii.uam.es/~ssantini/writing/notes/s668_summation.pdf


See also: qncmnpop.

EXAMPLE

Let us consider a multiclass network with C=2 customer classes; the maximum number of class 1 requests is 2, and the maximum number of class 2 requests is 3. How is it possible to allocate 3 requests to the two classes so that the maximum number of requests per class is not exceeded?

 N = [2 3];
 mix = qncmpopmix(3, N)
-| mix = [ [2 1] [1 2] [0 3] ]
Function File: H = qncmnpop (N)

Given a network with C customer classes, this function computes the number of k-mixes H(r,k) that can be constructed by the multiclass MVA algorithm by allocating k customers to the first r classes. See doc-qncmpopmix for the definition of k-mix.

INPUTS

N(c)

number of class-c requests in the system. The total number of requests in the network is sum(N).

OUTPUTS

H(r,k)

is the number of k mixes that can be constructed allocating k customers to the first r classes.

REFERENCES

  • Zahorjan, J. and Wong, E. The solution of separable queueing network models using mean value analysis. SIGMETRICS Perform. Eval. Rev. 10, 3 (Sep. 1981), 80-85. DOI 10.1145/1010629.805477

See also: qncmmva,qncmpopmix.

Function File: [U, R, Q, X] = qncmmva (N, S )
Function File: [U, R, Q, X] = qncmmva (N, S, V)
Function File: [U, R, Q, X] = qncmmva (N, S, V, m)
Function File: [U, R, Q, X] = qncmmva (N, S, V, m, Z)
Function File: [U, R, Q, X] = qncmmva (N, S, P)
Function File: [U, R, Q, X] = qncmmva (N, S, P, r)
Function File: [U, R, Q, X] = qncmmva (N, S, P, r, m)

Compute steady-state performance measures for closed, multiclass queueing networks using the Mean Value Analysys (MVA) algorithm.

Queueing policies at service centers can be any of the following:

FCFS

(First-Come-First-Served) customers are served in order of arrival; multiple servers are allowed. For this kind of queueing discipline, average service times must be class-independent.

PS

(Processor Sharing) customers are served in parallel by a single server, each customer receiving an equal share of the service rate.

LCFS-PR

(Last-Come-First-Served, Preemptive Resume) customers are served in reverse order of arrival by a single server and the last arrival preempts the customer in service who will later resume service at the point of interruption.

IS

(Infinite Server) customers are delayed independently of other customers at the service center (there is effectively an infinite number of servers).

INPUTS

N(c)

number of class c requests; N(c) ≥ 0. If class c has no requests (N(c) == 0), then for all k, this function returns U(c,k) = R(c,k) = Q(c,k) = X(c,k) = 0

S(c,k)

mean service time for class c requests at center k (S(c,k) ≥ 0). If the service time at center k is class-dependent, then center k is assumed to be of type -/G/1–PS (Processor Sharing). If center k is a FCFS node (m(k)>1), then the service times must be class-independent, i.e., all classes must have the same service time.

V(c,k)

average number of visits of class c requests at center k; V(c,k) ≥ 0, default is 1. If you pass this argument, class switching is not allowed

P(r,i,s,j)

probability that a class r request completing service at center i is routed to center j as a class s request; the reference stations for each class are specified with the paramter r. If you pass argument P, class switching is allowed; however, you can not specify any external delay (i.e., Z must be zero) and all servers must be fixed-rate or infinite-server nodes (m(k) ≤ 1 for all k).

r(c)

reference station for class c. If omitted, station 1 is the reference station for all classes. See qncmvisits.

m(k)

If m(k)<1, then center k is assumed to be a delay center (IS node -/G/\infty). If m(k)==1, then service center k is a regular queueing center (M/M/1–FCFS, -/G/1–LCFS-PR or -/G/1–PS). Finally, if m(k)>1, center k is a M/M/m–FCFS center with m(k) identical servers. Default is m(k)=1 for each k.

Z(c)

class c external delay (think time); Z(c) ≥ 0. Default is 0. This parameter can not be used if you pass a routing matrix as the second parameter of qncmmva.

OUTPUTS

U(c,k)

If k is a FCFS, LCFS-PR or PS node (m(k) ≥ 1), then U(c,k) is the class c utilization at center k, 0 ≤ U(c,k) ≤ 1. If k is an IS node, then U(c,k) is the class c traffic intensity at center k, defined as U(c,k) = X(c,k)*S(c,k). In this case the value of U(c,k) may be greater than one.

R(c,k)

class c response time at center k. The class c residence time at center k is R(c,k) * C(c,k). The total class c system response time is dot(R, V, 2).

Q(c,k)

average number of class c requests at center k. The total number of requests at center k is sum(Q(:,k)). The total number of class c requests in the system is sum(Q(c,:)).

X(c,k)

class c throughput at center k. The class c throughput can be computed as X(c,1) / V(c,1).

NOTES

If the function call specifies the visit ratios V, then class switching is not allowed. If the function call specifies the routing probability matrix P, then class switching is allowed; however, in this case all nodes are restricted to be fixed rate servers or delay centers: multiple-server and general load-dependent centers are not supported.

In presence of load-dependent servers (e.g., if m(i)>1 for some i), the MVA algorithm is known to be numerically unstable. Generally this problem shows up as negative values for the computed response times or utilizations. This is not a problem with the queueing package, but with the MVA algorithm; as such, there is no known workaround at the moment (aoart from using a different solution technique, if available). This function prints a warning if it detects numerical problems; you can disable the warning with the command warning("off", "qn:numerical-instability").

Given a network with K service centers, C job classes and population vector {\bf N}=\left[N_1, …, N_C\right], the MVA algorithm requires space O(C \prod_i (N_i + 1)). The time complexity is O(CK\prod_i (N_i + 1)). This implementation is slightly more space-efficient (see details in the code). While the space requirement can be mitigated by using some optimizations, the time complexity can not. If you need to analyze large closed networks you should consider the qncmmvaap function, which implements the approximate MVA algorithm. Note however that qncmmvaap will only provide approximate results.

REFERENCES

  • M. Reiser and S. S. Lavenberg, Mean-Value Analysis of Closed Multichain Queuing Networks, Journal of the ACM, vol. 27, n. 2, April 1980, pp. 313–322. 10.1145/322186.322195

This implementation is based on G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998 and Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, Quantitative System Performance: Computer System Analysis Using Queueing Network Models, Prentice Hall, 1984. http://www.cs.washington.edu/homes/lazowska/qsp/. In particular, see section 7.4.2.1 ("Exact Solution Techniques").


See also: qnclosed, qncmmvaapprox, qncmvisits.

Function File: [U, R, Q, X] = qncmmvabs (N, S, V)
Function File: [U, R, Q, X] = qncmmvabs (N, S, V, m)
Function File: [U, R, Q, X] = qncmmvabs (N, S, V, m, Z)
Function File: [U, R, Q, X] = qncmmvabs (N, S, V, m, Z, tol)
Function File: [U, R, Q, X] = qncmmvabs (N, S, V, m, Z, tol, iter_max)

Approximate Mean Value Analysis (MVA) for closed, multiclass queueing networks with K service centers and C customer classes.

This implementation uses Bard and Schweitzer approximation. It is based on the assumption that the queue length at service center k with population set {\bf N}-{\bf 1}_c is approximated with

Q_k(N-1c) ~ (n-1)/n Q_k(N)

where \bf N is a valid population mix, {\bf N}-{\bf 1}_c is the population mix \bf N with one class c customer removed, and n = \sum_c N_c is the total number of requests.

This implementation works for networks with infinite server (IS) and single-server nodes only.

INPUTS

N(c)

number of class c requests in the system (N(c) ≥ 0).

S(c,k)

mean service time for class c customers at center k (S(c,k) ≥ 0).

V(c,k)

average number of visits of class c requests to center k (V(c,k) ≥ 0).

m(k)

number of servers at center k. If m(k) < 1, then the service center k is assumed to be a delay center (IS). If m(k) == 1, service center k is a regular queueing center (FCFS, LCFS-PR or PS) with a single server node. If omitted, each service center has a single server. Note that multiple server nodes are not supported.

Z(c)

class c external delay (Z ≥ 0). Default is 0.

tol

Stopping tolerance (tol>0). The algorithm stops if the queue length computed on two subsequent iterations are less than tol. Default is 10^{-5}.

iter_max

Maximum number of iterations (iter_max>0. The function aborts if convergenge is not reached within the maximum number of iterations. Default is 100.

OUTPUTS

U(c,k)

If k is a FCFS, LCFS-PR or PS node, then U(c,k) is the utilization of class c requests on service center k. If k is an IS node, then U(c,k) is the class c traffic intensity at device k, defined as U(c,k) = X(c)*S(c,k)

R(c,k)

response time of class c requests at service center k.

Q(c,k)

average number of class c requests at service center k.

X(c,k)

class c throughput at service center k.

REFERENCES

  • Y. Bard, Some Extensions to Multiclass Queueing Network Analysis, proc. 4th Int. Symp. on Modelling and Performance Evaluation of Computer Systems, Feb 1979, pp. 51–62.
  • P. Schweitzer, Approximate Analysis of Multiclass Closed Networks of Queues, Proc. Int. Conf. on Stochastic Control and Optimization, jun 1979, pp. 25–29.

This implementation is based on Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, Quantitative System Performance: Computer System Analysis Using Queueing Network Models, Prentice Hall, 1984. http://www.cs.washington.edu/homes/lazowska/qsp/. In particular, see section 7.4.2.2 ("Approximate Solution Techniques"). This implementation is slightly different from the one described above, as it computes the average response times R instead of the residence times.


See also: qncmmva.

5.3.3 Mixed Networks

Function File: [U, R, Q, X] = qnmix (lambda, N, S, V, m)

Mean Value Analysis for mixed queueing networks. The network consists of K service centers (single-server or delay centers) and C independent customer chains. Both open and closed chains are possible. lambda is the vector of per-chain arrival rates (open classes); N is the vector of populations for closed chains.

Class switching is not allowed. Each customer class must correspond to an independent chain.

If the network is made of open or closed classes only, then this function calls qnom or qncmmva respectively, and prints a warning message.

INPUTS

lambda(c)
N(c)

For each customer chain c:

  • if c is a closed chain, then N(c)>0 is the number of class c requests and lambda(c) must be zero;
  • If c is an open chain, lambda(c)>0 is the arrival rate of class c requests and N(c) must be zero;

In other words, for each class c the following must hold:

(lambda(c)>0 && N(c)==0) || (lambda(c)==0 && N(c)>0)
S(c,k)

mean class c service time at center k, S(c,k) ≥ 0. For FCFS nodes, service times must be class-independent.

V(c,k)

average number of visits of class c customers to center k (V(c,k) ≥ 0).

m(k)

number of servers at center k. Only single-server (m(k)==1) or IS (Infinite Server) nodes (m(k)<1) are supported. If omitted, each center is assumed to be of type M/M/1-FCFS. Queueing discipline for single-server nodes can be FCFS, PS or LCFS-PR.

OUTPUTS

U(c,k)

class c utilization at center k.

R(c,k)

class c response time at center k.

Q(c,k)

average number of class c requests at center k.

X(c,k)

class c throughput at center k.

REFERENCES

  • Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, Quantitative System Performance: Computer System Analysis Using Queueing Network Models, Prentice Hall, 1984. http://www.cs.washington.edu/homes/lazowska/qsp/. In particular, see section 7.4.3 ("Mixed Model Solution Techniques"). Note that in this function we compute the mean response time R instead of the mean residence time as in the reference.
  • Herb Schwetman, Implementing the Mean Value Algorithm for the Solution of Queueing Network Models, Technical Report CSD-TR-355, Department of Computer Sciences, Purdue University, revised Feb 15, 1982.

See also: qncmmva, qncm.


5.4 Generic Algorithms

The queueing package provides a high-level function qnsolve for analyzing QN models. qnsolve takes as input a high-level description of the queueing model, and delegates the actual solution of the model to one of the lower-level function. qnsolve supports single or multiclass models, but at the moment only product-form networks can be analyzed. For non product-form networks See Non Product-Form QNs.

qnsolve accepts two input parameters. The first one is the list of nodes, encoded as an Octave cell array. The second parameter is the vector of visit ratios V, which can be either a vector (for single-class models) or a two-dimensional matrix (for multiple-class models).

Individual nodes in the network are structures build using the qnmknode function.

Function File: Q = qnmknode ("m/m/m-fcfs", S)
Function File: Q = qnmknode ("m/m/m-fcfs", S, m)
Function File: Q = qnmknode ("m/m/1-lcfs-pr", S)
Function File: Q = qnmknode ("-/g/1-ps", S)
Function File: Q = qnmknode ("-/g/1-ps", S, s2)
Function File: Q = qnmknode ("-/g/inf", S)
Function File: Q = qnmknode ("-/g/inf", S, s2)

Creates a node; this function can be used together with qnsolve. It is possible to create either single-class nodes (where there is only one customer class), or multiple-class nodes (where the service time is given per-class). Furthermore, it is possible to specify load-dependent service times. String literals are case-insensitive, so for example "-/g/inf", "-/G/inf" and "-/g/INF" are all equivalent.

INPUTS

S

Mean service time.

  • If S is a scalar, it is assumed to be a load-independent, class-independent service time.
  • If S is a column vector, then S(c) is assumed to the the load-independent service time for class c customers.
  • If S is a row vector, then S(n) is assumed to be the class-independent service time at the node, when there are n requests.
  • Finally, if S is a two-dimensional matrix, then S(c,n) is assumed to be the class c service time when there are n requests at the node.
m

Number of identical servers at the node. Default is m=1.

s2

Squared coefficient of variation for the service time. Default is 1.0.

The returned struct Q should be considered opaque to the client.


See also: qnsolve.

After the network has been defined, it is possible to solve it using qnsolve.

Function File: [U, R, Q, X] = qnsolve ("closed", N, QQ, V)
Function File: [U, R, Q, X] = qnsolve ("closed", N, QQ, V, Z)
Function File: [U, R, Q, X] = qnsolve ("open", lambda, QQ, V)
Function File: [U, R, Q, X] = qnsolve ("mixed", lambda, N, QQ, V)

High-level function for analyzing QN models.

  • For closed networks, the following server types are supported: M/M/m–FCFS, -/G/\infty, -/G/1–LCFS-PR, -/G/1–PS and load-dependent variants.
  • For open networks, the following server types are supported: M/M/m–FCFS, -/G/\infty and -/G/1–PS. General load-dependent nodes are not supported. Multiclass open networks do not support multiple server M/M/m nodes, but only single server M/M/1–FCFS.
  • For mixed networks, the following server types are supported: M/M/1–FCFS, -/G/\infty and -/G/1–PS. General load-dependent nodes are not supported.

INPUTS

N
N(c)

Number of requests in the system for closed networks. For single-class networks, N must be a scalar. For multiclass networks, N(c) is the population size of closed class c.

lambda
lambda(c)

External arrival rate (scalar) for open networks. For single-class networks, lambda must be a scalar. For multiclass networks, lambda(c) is the class c overall arrival rate.

QQ{i}

List of queues in the network. This must be a cell array with N elements, such that QQ{i} is a struct produced by the qnmknode function.

Z

External delay ("think time") for closed networks. Default 0.

OUTPUTS

U(k)

If k is a FCFS node, then U(k) is the utilization of service center k. If k is an IS node, then U(k) is the traffic intensity defined as X(k)*S(k).

R(k)

average response time of service center k.

Q(k)

average number of customers in service center k.

X(k)

throughput of service center k.

Note that for multiclass networks, the computed results are per-class utilization, response time, number of customers and throughput: U(c,k), R(c,k), Q(c,k), X(c,k).

String literals are case-insensitive, so "closed", "Closed" and "CLoSEd" are all equivalent.

EXAMPLE

Let us consider a closed, multiclass network with C=2 classes and K=3 service center. Let the population be M=(2, 1) (class 1 has 2 requests, and class 2 has 1 request). The nodes are as follows:

  • Node 1 is a M/M/1–FCFS node, with load-dependent service times. Service times are class-independent, and are defined by the matrix [0.2 0.1 0.1; 0.2 0.1 0.1]. Thus, S(1,2) = 0.2 means that service time for class 1 customers where there are 2 requests in 0.2. Note that service times are class-independent;
  • Node 2 is a -/G/1–PS node, with service times S_{1, 2} = 0.4 for class 1, and S_{2, 2} = 0.6 for class 2 requests;
  • Node 3 is a -/G/\infty node (delay center), with service times S_{1, 3}=1 and S_{2, 3}=2 for class 1 and 2 respectively.

After defining the per-class visit count V such that V(c,k) is the visit count of class c requests to service center k. We can define and solve the model as follows:



 QQ = { qnmknode( "m/m/m-fcfs", [0.2 0.1 0.1; 0.2 0.1 0.1] ), ...
        qnmknode( "-/g/1-ps", [0.4; 0.6] ), ...
        qnmknode( "-/g/inf", [1; 2] ) };
 V = [ 1 0.6 0.4; ...
       1 0.3 0.7 ];
 N = [ 2 1 ];
 [U R Q X] = qnsolve( "closed", N, QQ, V );
Function File: [U, R, Q, X] = qnclosed (N, S, V, …)

This function computes steady-state performance measures of closed queueing networks using the Mean Value Analysis (MVA) algorithm. The qneneing network is allowed to contain fixed-capacity centers, delay centers or general load-dependent centers. Multiple request classes are supported.

This function dispatches the computation to one of qncsemva, qncsmvald or qncmmva.

  • If N is a scalar, the network is assumed to have a single class of requests; in this case, the exact MVA algorithm is used to analyze the network. If S is a vector, then S(k) is the average service time of center k, and this function calls qncsmva which supports load-independent service centers. If S is a matrix, S(k,i) is the average service time at center k when i=1, …, N jobs are present; in this case, the network is analyzed with the qncmmvald function.
  • If N is a vector, the network is assumed to have multiple classes of requests, and is analyzed using the exact multiclass MVA algorithm as implemented in the qncmmva function.

See also: qncsmva, qncsmvald, qncmmva.

EXAMPLE

 P = [0 0.3 0.7; 1 0 0; 1 0 0]; # Transition probability matrix
 S = [1 0.6 0.2];               # Average service times
 m = ones(size(S));             # All centers are single-server
 Z = 2;                         # External delay
 N = 15;                        # Maximum population to consider
 V = qncsvisits(P);             # Compute number of visits
 X_bsb_lower = X_bsb_upper = X_ab_lower = X_ab_upper = X_mva = zeros(1,N);
 for n=1:N
   [X_bsb_lower(n) X_bsb_upper(n)] = qncsbsb(n, S, V, m, Z);
   [X_ab_lower(n) X_ab_upper(n)] = qncsaba(n, S, V, m, Z);
   [U R Q X] = qnclosed( n, S, V, m, Z );
   X_mva(n) = X(1)/V(1);
 endfor
 close all;
 plot(1:N, X_ab_lower,"g;Asymptotic Bounds;", ...
      1:N, X_bsb_lower,"k;Balanced System Bounds;", ...
      1:N, X_mva,"b;MVA;", "linewidth", 2, ...
      1:N, X_bsb_upper,"k", 1:N, X_ab_upper,"g" );
 axis([1,N,0,1]); legend("location","southeast"); legend("boxoff");
 xlabel("Number of Requests n"); ylabel("System Throughput X(n)");
Function File: [U, R, Q, X] = qnopen (lambda, S, V, …)

Compute utilization, response time, average number of requests in the system, and throughput for open queueing networks. If lambda is a scalar, the network is considered a single-class QN and is solved using qnopensingle. If lambda is a vector, the network is considered as a multiclass QN and solved using qnopenmulti.


See also: qnos, qnom.


5.5 Bounds Analysis

Function File: [Xl, Xu, Rl, Ru] = qnosaba (lambda, D)
Function File: [Xl, Xu, Rl, Ru] = qnosaba (lambda, S, V)
Function File: [Xl, Xu, Rl, Ru] = qnosaba (lambda, S, V, m)

Compute Asymptotic Bounds for open, single-class networks with K service centers.

INPUTS

lambda

Arrival rate of requests (scalar, lambda ≥ 0).

D(k)

service demand at center k. (vector of length K, D(k) ≥ 0).

S(k)

mean service time at center k. (vector of length K, S(k) ≥ 0).

V(k)

mean number of visits to center k. (vector of length K, V(k) ≥ 0).

m(k)

number of servers at center k. This function only supports M/M/1 queues, therefore m must be ones(size(S)).

OUTPUTS

Xl
Xu

Lower and upper bounds on the system throughput. Xl is always set to 0 since there can be no lower bound on the throughput of open networks (scalar).

Rl
Ru

Lower and upper bounds on the system response time. Ru is always set to +inf since there can be no upper bound on the throughput of open networks (scalar).


See also: qnomaba.

Function File: [Xl, Xu, Rl, Ru] = qnomaba (lambda, D)
Function File: [Xl, Xu, Rl, Rl] = qnomaba (lambda, S, V)

Compute Asymptotic Bounds for open, multiclass networks with K service centers and C customer classes.

INPUTS

lambda(c)

class c arrival rate to the system (vector of length C, lambda(c) > 0).

D(c, k)

class c service demand at center k (C \times K matrix, D(c, k) ≥ 0).

S(c, k)

mean service time of class c requests at center k (C \times K matrix, S(c, k) ≥ 0).

V(c, k)

mean number of visits of class c requests at center k (C \times K matrix, V(c, k) ≥ 0).

OUTPUTS

Xl(c)
Xu(c)

lower and upper bounds of class c throughput. Xl(c) is always 0 since there can be no lower bound on the throughput of open networks (vector of length C).

Rl(c)
Ru(c)

lower and upper bounds of class c response time. Ru(c) is always +inf since there can be no upper bound on the response time of open networks (vector of length C).

Function File: [Xl, Xu, Rl, Ru] = qncsaba (N, D)
Function File: [Xl, Xu, Rl, Ru] = qncsaba (N, S, V)
Function File: [Xl, Xu, Rl, Ru] = qncsaba (N, S, V, m)
Function File: [Xl, Xu, Rl, Ru] = qncsaba (N, S, V, m, Z)

Compute Asymptotic Bounds for the system throughput and response time of closed, single-class networks with K service centers.

Single-server and infinite-server nodes are supported. Multiple-server nodes and general load-dependent servers are not supported.

INPUTS

N

number of requests in the system (scalar, N>0).

D(k)

service demand at center k (D(k) ≥ 0).

S(k)

mean service time at center k (S(k) ≥ 0).

V(k)

average number of visits to center k (V(k) ≥ 0).

m(k)

number of servers at center k (if m is a scalar, all centers have that number of servers). If m(k) < 1, center k is a delay center (IS); if m(k) = 1, center k is a M/M/1-FCFS server. This function does not support multiple-server nodes. Default is 1.

Z

External delay (scalar, Z ≥ 0). Default is 0.

OUTPUTS

Xl
Xu

Lower and upper bounds on the system throughput.

Rl
Ru

Lower and upper bounds on the system response time.


See also: qncmaba.

Function File: [Xl, Xu, Rl, Ru] = qncmaba (N, D)
Function File: [Xl, Xu, Rl, Ru] = qncmaba (N, S, V)
Function File: [Xl, Xu, Rl, Ru] = qncmaba (N, S, V, m)
Function File: [Xl, Xu, Rl, Ru] = qncmaba (N, S, V, m, Z)

Compute Asymptotic Bounds for closed, multiclass networks with K service centers and C customer classes. Single-server and infinite-server nodes are supported. Multiple-server nodes and general load-dependent servers are not supported.

INPUTS

N(c)

number of class c requests in the system (vector of length C, N(c) ≥ 0).

D(c, k)

class c service demand at center k (C \times K matrix, D(c,k) ≥ 0).

S(c, k)

mean service time of class c requests at center k (C \times K matrix, S(c,k) ≥ 0).

V(c,k)

average number of visits of class c requests to center k (C \times K matrix, V(c,k) ≥ 0).

m(k)

number of servers at center k (if m is a scalar, all centers have that number of servers). If m(k) < 1, center k is a delay center (IS); if m(k) = 1, center k is a M/M/1-FCFS server. This function does not support multiple-server nodes. Default is 1.

Z(c)

class c external delay (vector of length C, Z(c) ≥ 0). Default is 0.

OUTPUTS

Xl(c)
Xu(c)

Lower and upper bounds for class c throughput.

Rl(c)
Ru(c)

Lower and upper bounds for class c response time.

REFERENCES

  • Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, Quantitative System Performance: Computer System Analysis Using Queueing Network Models, Prentice Hall, 1984. http://www.cs.washington.edu/homes/lazowska/qsp/. In particular, see section 5.2 ("Asymptotic Bounds").

See also: qncsaba.

Function File: [Xl, Xu, Rl, Ru] = qnosbsb (lambda, D)
Function File: [Xl, Xu, Rl, Ru] = qnosbsb (lambda, S, V)

Compute Balanced System Bounds for single-class, open networks with K service centers.

INPUTS

lambda

overall arrival rate to the system (scalar, lambda ≥ 0).

D(k)

service demand at center k (D(k) ≥ 0).

S(k)

service time at center k (S(k) ≥ 0).

V(k)

mean number of visits at center k (V(k) ≥ 0).

m(k)

number of servers at center k. This function only supports M/M/1 queues, therefore m must be ones(size(S)).

OUTPUTS

Xl
Xu

Lower and upper bounds on the system throughput. Xl is always set to 0, since there can be no lower bound on open networks throughput.

Rl
Ru

Lower and upper bounds on the system response time.


See also: qnosaba.

Function File: [Xl, Xu, Rl, Ru] = qncsbsb (N, D)
Function File: [Xl, Xu, Rl, Ru] = qncsbsb (N, S, V)
Function File: [Xl, Xu, Rl, Ru] = qncsbsb (N, S, V, m)
Function File: [Xl, Xu, Rl, Ru] = qncsbsb (N, S, V, m, Z)

Compute Balanced System Bounds on system throughput and response time for closed, single-class networks with K service centers.

INPUTS

N

number of requests in the system (scalar, N ≥ 0).

D(k)

service demand at center k (D(k) ≥ 0).

S(k)

mean service time at center k (S(k) ≥ 0).

V(k)

average number of visits to center k (V(k) ≥ 0). Default is 1.

m(k)

number of servers at center k. This function supports m(k) = 1 only (single-eserver FCFS nodes); this parameter is only for compatibility with qncsaba. Default is 1.

Z

External delay (Z ≥ 0). Default is 0.

OUTPUTS

Xl
Xu

Lower and upper bound on the system throughput.

Rl
Ru

Lower and upper bound on the system response time.

REFERENCES

  • Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. Sevcik, Quantitative System Performance: Computer System Analysis Using Queueing Network Models, Prentice Hall, 1984. http://www.cs.washington.edu/homes/lazowska/qsp/. In particular, see section 5.4 ("Balanced Systems Bounds").

See also: qncmbsb.

Function File: [Xl, Xu, Rl, Ru] = qncmbsb (N, D)
Function File: [Xl, Xu, Rl, Ru] = qncmbsb (N, S, V)

Compute Balanced System Bounds for closed, multiclass networks with K service centers and C customer classes. Only single-server nodes are supported.

INPUTS

N(c)

number of class c requests in the system (vector of length C).

D(c, k)

class c service demand at center k (C \times K matrix, D(c,k) ≥ 0).

S(c, k)

mean service time of class c requests at center k (C \times K matrix, S(c,k) ≥ 0).

V(c,k)

average number of visits of class c requests to center k (C \times K matrix, V(c,k) ≥ 0).

OUTPUTS

Xl(c)
Xu(c)

Lower and upper class c throughput bounds (vector of length C).

Rl(c)
Ru(c)

Lower and upper class c response time bounds (vector of length C).


See also: qncsbsb.

Function File: [Xl, Xu, Rl, Ru] = qncmcb (N, D)
Function File: [Xl, Xu, Rl, Ru] = qncmcb (N, S, V)

Compute Composite Bounds (CB) on system throughput and response time for closed multiclass networks.

INPUTS

N(c)

number of class c requests in the system.

D(c, k)

class c service demand at center k (S(c,k) ≥ 0).

S(c, k)

mean service time of class c requests at center k (S(c,k) ≥ 0).

V(c,k)

average number of visits of class c requests to center k (V(c,k) ≥ 0).

OUTPUTS

Xl(c)
Xu(c)

Lower and upper bounds on class c throughput.

Rl(c)
Ru(c)

Lower and upper bounds on class c response time.

REFERENCES

  • Teemu Kerola, The Composite Bound Method (CBM) for Computing Throughput Bounds in Multiple Class Environments, Performance Evaluation Vol. 6, Issue 1, March 1986, DOI 10.1016/0166-5316(86)90002-7. Also available as Technical Report CSD-TR-475, Department of Computer Sciences, Purdue University, mar 13, 1984 (Revised Aug 27, 1984).
Function File: [Xl, Xu, Rl, Ru] = qncspb (N, D )
Function File: [Xl, Xu, Rl, Ru] = qncspb (N, S, V )
Function File: [Xl, Xu, Rl, Ru] = qncspb (N, S, V, m )
Function File: [Xl, Xu, Rl, Ru] = qncspb (N, S, V, m, Z )

Compute PB Bounds (C. H. Hsieh and S. Lam, 1987) for single-class, closed networks with K service centers.

INPUTS

number of requests in the system (scalar, N > 0).

D(k)

service demand of service center k (D(k) ≥ 0).

S(k)

mean service time at center k (S(k) ≥ 0).

V(k)

visit ratio to center k (V(k) ≥ 0).

m(k)

number of servers at center k. This function only supports M/M/1 queues, therefore m must be ones(size(S)).

Z

external delay (think time, Z ≥ 0). Default 0.

OUTPUTS

Xl
Xu

Lower and upper bounds on the system throughput.

Rl
Ru

Lower and upper bounds on the system response time.

REFERENCES

  • C. H. Hsieh and S. Lam, Two classes of performance bounds for closed queueing networks, Performance Evaluation, Vol. 7 Issue 1, pp. 3–30, February 1987, DOI 10.1016/0166-5316(87)90054-X. Also available as Technical Report TR-85-09, Department of Computer Science, University of Texas at Austin, June 1985

This function implements the non-iterative variant described in G. Casale, R. R. Muntz, G. Serazzi, Geometric Bounds: a Non-Iterative Analysis Technique for Closed Queueing Networks, IEEE Transactions on Computers, 57(6):780-794, June 2008.


See also: qncsaba, qbcsbsb, qncsgb.

Function File: [Xl, Xu, Rl, Ru, Ql, Qu] = qncsgb (N, D)
Function File: [Xl, Xu, Rl, Ru, Ql, Qu] = qncsgb (N, S, V)
Function File: [Xl, Xu, Rl, Ru, Ql, Qu] = qncsgb (N, S, V, m)
Function File: [Xl, Xu, Rl, Ru, Ql, Qu] = qncsgb (N, S, V, m, Z)

Compute Geometric Bounds (GB) on system throughput, system response time and server queue lenghts for closed, single-class networks with K service centers and N requests.

INPUTS

N

number of requests in the system (scalar, N > 0).

D(k)

service demand of service center k (vector of length K, D(k) ≥ 0).

S(k)

mean service time at center k (vector of length K, S(k) ≥ 0).

V(k)

visit ratio to center k (vector of length K, V(k) ≥ 0).

m(k)

number of servers at center k. This function only supports M/M/1 queues, therefore m must be ones(size(S)).

Z

external delay (think time, Z ≥ 0, scalar). Default is 0.

OUTPUTS

Xl
Xu

Lower and upper bound on the system throughput. If Z>0, these bounds are computed using Geometric Square-root Bounds (GSB). If Z==0, these bounds are computed using Geometric Bounds (GB)

Rl
Ru

Lower and upper bound on the system response time. These bounds are derived from Xl and Xu using Little’s Law: Rl = N / Xu - Z, Ru = N / Xl - Z

Ql(k)
Qu(k)

lower and upper bounds of center K queue length.

REFERENCES

  • G. Casale, R. R. Muntz, G. Serazzi, Geometric Bounds: a Non-Iterative Analysis Technique for Closed Queueing Networks, IEEE Transactions on Computers, 57(6):780-794, June 2008. 10.1109/TC.2008.37

In this implementation we set X^+ and X^- as the upper and lower Asymptotic Bounds as computed by the qncsab function, respectively.


5.6 QN Analysis Examples

In this section we illustrate with a few examples how the queueing package can be used to analyze queueing network models. Further examples can be found in the functions demo blocks, and can be inspected with the demo function Octave command.

5.6.1 Closed, Single Class Network

Let us consider again the network shown in Figure 5.1. We denote with S_k the average service time at center k, k=1, 2, 3. Let the service times be S_1 = 1.0, S_2 = 2.0 and S_3 = 0.8. The routing of jobs within the network is described with a routing probability matrix \bf P: a request completing service at center i is enqueued at center j with probability P_{i, j}. We use the following routing matrix:

    / 0  0.3  0.7 \
P = | 1  0    0   |
    \ 1  0    0   /

The network above can be analyzed with the qnclosed function see doc-qnclosed. qnclosed requires the following parameters:

N

Number of requests in the network (since we are considering a closed network, the number of requests is fixed)

S

Array of average service times at the centers: S(k) is the average service time at center k.

V

Array of visit ratios: V(k) is the average number of visits to center k.

We can compute V_k from the routing probability matrix P_{i, j} using the qncsvisits function see doc-qncsvisits. Therefore, we can analyze the network for a given population size N (e.g., N=10) as follows:

N = 10;
S = [1 2 0.8];
P = [0 0.3 0.7; 1 0 0; 1 0 0];
V = qncsvisits(P);
[U R Q X] = qnclosed( N, S, V )
   ⇒ U = 0.99139 0.59483 0.55518
   ⇒ R = 7.4360  4.7531  1.7500
   ⇒ Q = 7.3719  1.4136  1.2144
   ⇒ X = 0.99139 0.29742 0.69397

The output of qnclosed includes the vectors of utilizations U_k at center k, response time R_k, average number of customers Q_k and throughput X_k. In our example, the throughput of center 1 is X_1 = 0.99139, and the average number of requests in center 3 is Q_3 = 1.2144. The utilization of center 1 is U_1 = 0.99139, which is the highest among the service centers. Thus, center 1 is the bottleneck device.

This network can also be analyzed with the qnsolve function see doc-qnsolve. qnsolve can handle open, closed or mixed networks, and allows the network to be described in a very flexible way. First, let Q1, Q2 and Q3 be the variables describing the service centers. Each variable is instantiated with the qnmknode function.

Q1 = qnmknode( "m/m/m-fcfs", 1 );
Q2 = qnmknode( "m/m/m-fcfs", 2 );
Q3 = qnmknode( "m/m/m-fcfs", 0.8 );

The first parameter of qnmknode is a string describing the type of the node; "m/m/m-fcfs" denotes a M/M/m–FCFS center (this parameter is case-insensitive). The second parameter gives the average service time. An optional third parameter can be used to specify the number m of service centers. If omitted, it is assumed m=1 (single-server node).

Now, the network can be analyzed as follows:

N = 10;
V = [1 0.3 0.7];
[U R Q X] = qnsolve( "closed", N, { Q1, Q2, Q3 }, V )
   ⇒ U = 0.99139 0.59483 0.55518
   ⇒ R = 7.4360  4.7531  1.7500
   ⇒ Q = 7.3719  1.4136  1.2144
   ⇒ X = 0.99139 0.29742 0.69397

5.6.2 Open, Single Class Network

Let us consider an open network with K=3 service centers and the following routing probabilities:

    / 0  0.3  0.5 \
P = ! 1  0    0   |
    \ 1  0    0   /

In this network, requests can leave the system from center 1 with probability 1-(0.3+0.5) = 0.2. We suppose that external jobs arrive at center 1 with rate \lambda_1 = 0.15; there are no arrivals at centers 2 and 3.

Similarly to closed networks, we first compute the visit counts V_k to center k, k = 1, 2, 3. We use the qnosvisits function as follows:

P = [0 0.3 0.5; 1 0 0; 1 0 0];
lambda = [0.15 0 0];
V = qnosvisits(P, lambda)
   ⇒ V = 5.00000 1.50000 2.50000

where lambda(k) is the arrival rate at center k, and \bf P is the routing matrix. Assuming the same service times as in the previous example, the network can be analyzed with the qnopen function see doc-qnopen, as follows:

S = [1 2 0.8];
[U R Q X] = qnopen( sum(lambda), S, V )
   ⇒ U = 0.75000 0.45000 0.30000
   ⇒ R = 4.0000  3.6364  1.1429
   ⇒ Q = 3.00000 0.81818 0.42857
   ⇒ X = 0.75000 0.22500 0.37500

The first parameter of the qnopen function is the (scalar) aggregate arrival rate.

Again, it is possible to use the qnsolve high-level function:

Q1 = qnmknode( "m/m/m-fcfs", 1 );
Q2 = qnmknode( "m/m/m-fcfs", 2 );
Q3 = qnmknode( "m/m/m-fcfs", 0.8 );
lambda = [0.15 0 0];
[U R Q X] = qnsolve( "open", sum(lambda), { Q1, Q2, Q3 }, V )
   ⇒ U = 0.75000 0.45000 0.30000
   ⇒ R = 4.0000  3.6364  1.1429
   ⇒ Q = 3.00000 0.81818 0.42857
   ⇒ X = 0.75000 0.22500 0.37500

5.6.3 Closed Multiclass Network/1

The following example is taken from Herb Schwetman, Implementing the Mean Value Algorithm for the Solution of Queueing Network Models, Technical Report CSD-TR-355, Department of Computer Sciences, Purdue University, Feb 15, 1982.

Let us consider the following multiclass QN with three servers and two classes

qn_closed_multi_apl

Figure 5.3

Servers 1 and 2 (labeled APL and IMS, respectively) are infinite server nodes; server 3 (labeled SYS) is Processor Sharing (PS). Mean service times are given in the following table:

APLIMSSYS
Class 11-0.025
Class 2-150.500

There is no class switching. If we assume a population of 15 requests for class 1, and 5 requests for class 2, then the model can be analyzed as follows:

 S = [1 0 .025; 0 15 .5];
 P = zeros(2,3,2,3);
 P(1,1,1,3) = P(1,3,1,1) = 1;
 P(2,2,2,3) = P(2,3,2,2) = 1;
 V = qncmvisits(P,[3 3]); # reference station is station 3
 N = [15 5];
 m = [-1 -1 1];
 [U R Q X] = qncmmva(N,S,V,m)
  ⇒
U =

   14.32312    0.00000    0.35808
    0.00000    4.70699    0.15690

R =

    1.00000    0.00000    0.04726
    0.00000   15.00000    0.93374

Q =

   14.32312    0.00000    0.67688
    0.00000    4.70699    0.29301

X =

   14.32312    0.00000   14.32312
    0.00000    0.31380    0.31380

5.6.4 Closed Multiclass Network/2

The following example is from M. Marzolla, The qnetworks Toolbox: A Software Package for Queueing Networks Analysis, Technical Report UBLCS-2010-04, Department of Computer Science, University of Bologna, Italy, February 2010.

qn_web_model

Figure 5.4: Three-tier enterprise system model

The model shown in Figure 5.4 shows a three-tier enterprise system with K=6 service centers. The first tier contains the Web server (node 1), which is responsible for generating Web pages and transmitting them to clients. The application logic is implemented by nodes 2 and 3, and the storage tier is made of nodes 4–6.The system is subject to two workload classes, both represented as closed populations of N_1 and N_2 requests, respectively. Let D_{c, k} denote the service demand of class c requests at center k. We use the parameter values:

Serv. no.NameClass 1Class 2
1Web Server122
2App. Server 11420
3App. Server 22314
4DB Server 12090
5DB Server 28030
6DB Server 33133

We set the total number of requests to 100, that is N_1 + N_2 = N = 100, and we study how different population mixes (N_1, N_2) affect the system throughput and response time. Let 0 < \beta_1 < 1 denote the fraction of class 1 requests: N_1 = \beta_1 N, N_2 = (1-\beta_1)N. The following Octave code defines the model for \beta_1 = 0.1:

N = 100;     # total population size
beta1 = 0.1; # fraction of class 1 reqs.
S = [12 14 23 20 80 31; ...
      2 20 14 90 30 33 ];
V = ones(size(S));
pop = [fix(beta1*N) N-fix(beta1*N)];
[U R Q X] = qncmmva(pop, S, V);

The qncmmva(pop, S, V) function invocation uses the multiclass MVA algorithm to compute per-class utilizations U_{c, k}, response times R_{c,k}, mean queue lengths Q_{c,k} and throughputs X_{c,k} at each service center k, given a population vector pop, mean service times S and visit ratios V. Since we are given the service demands D_{c, k} = S_{c, k} V_{c,k}, but function qncmmva requires separate service times and visit ratios, we set the service times equal to the demands, and all visit ratios equal to one. Overall class and system throughputs and response times can also be computed:

X1 = X(1,1) / V(1,1)     # class 1 throughput
        ⇒ X1 =  0.0044219
X2 = X(2,1) / V(2,1)     # class 2 throughput
        ⇒ X2 =  0.010128
XX = X1 + X2             # system throughput
        ⇒ XX =  0.014550
R1 = dot(R(1,:), V(1,:)) # class 1 resp. time
        ⇒ R1 =  2261.5
R2 = dot(R(2,:), V(2,:)) # class 2 resp. time
        ⇒ R2 =  8885.9
RR = N / XX              # system resp. time
        ⇒ RR =  6872.7

dot(X,Y) computes the dot product of two vectors. R(1,:) is the first row of matrix R and V(1,:) is the first row of matrix V, so dot(R(1,:), V(1,:)) computes \sum_k R_{1,k} V_{1,k}.

web

Figure 5.5: Throughput and Response Times as a function of the population mix

We can also compute the system power \Phi = X / R, which defines how efficiently resources are being used: high values of \Phi denote the desirable situation of high throughput and low response time. Figure 5.6 shows \Phi as a function of \beta_1. We observe a “plateau” of the global system power, corresponding to values of \beta_1 which approximately lie between 0.3 and 0.7. The per-class power exhibits an interesting (although not completely surprising) pattern, where the class with higher population exhibits worst efficiency as it produces higher contention on the resources.

power

Figure 5.6: System Power as a function of the population mix

5.6.5 Closed Multiclass Network/3

We now consider an example of multiclass network with class switching. The example is taken from Sch82, and is shown in Figure Figure 5.7.

qn_closed_multi_cs

Figure 5.7: Multiclass Model with Class Switching

The system consists of three devices and two job classes. The CPU node is a PS server, while the two nodes labeled I/O are FCFS. Class 1 mean service time at the CPU is 0.01; class 2 mean service time at the CPU is 0.05. The mean service time at node 2 is 0.1, and is class-independent. Similarly, the mean service time at node 3 is 0.07. Jobs in class 1 leave the CPU and join class 2 with probability 0.1; jobs of class 2 leave the CPU and join class 1 with probability 0.2. There are N=3 jobs, which are initially allocated to class 1. However, note that since class switching is allowed, the total number of jobs in each class does not remain constant; however the total number of jobs does.

 C = 2; K = 3;
 S = [.01 .07 .10; ...
      .05 .07 .10 ];
 P = zeros(C,K,C,K);
 P(1,1,1,2) = .7; P(1,1,1,3) = .2; P(1,1,2,1) = .1;
 P(2,1,2,2) = .3; P(2,1,2,3) = .5; P(2,1,1,1) = .2;
 P(1,2,1,1) = P(2,2,2,1) = 1;
 P(1,3,1,1) = P(2,3,2,1) = 1;
 N = [3 0];
 [U R Q X] = qncmmva(N, S, P)
  ⇒
U =

   0.12609   0.61784   0.25218
   0.31522   0.13239   0.31522

R =

   0.014653   0.133148   0.163256
   0.073266   0.133148   0.163256

Q =

   0.18476   1.17519   0.41170
   0.46190   0.25183   0.51462

X =

   12.6089    8.8262    2.5218
    6.3044    1.8913    3.1522

Next: , Previous: , Up: Top   [Contents][Index]

6 References

[Aky88]

Ian F. Akyildiz, Mean Value Analysis for Blocking Queueing Networks, IEEE Transactions on Software Engineering, vol. 14, n. 2, april 1988, pp. 418–428. DOI 10.1109/32.4663

[Bar79]

Y. Bard, Some Extensions to Multiclass Queueing Network Analysis, proc. 4th Int. Symp. on Modelling and Performance Evaluation of Computer Systems, feb. 1979, pp. 51–62.

[BCMP75]

F. Baskett, K. Mani Chandy, R. R. Muntz, and F. G. Palacios. 1975. Open, Closed, and Mixed Networks of Queues with Different Classes of Customers. J. ACM 22, 2 (April 1975), 248—260, DOI 10.1145/321879.321887

[BGMT98]

G. Bolch, S. Greiner, H. de Meer and K. Trivedi, Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications, Wiley, 1998.

[Buz73]

J. P. Buzen, Computational Algorithms for Closed Queueing Networks with Exponential Servers, Communications of the ACM, volume 16, number 9, september 1973, pp. 527–531. DOI 10.1145/362342.362345

[C08]

G. Casale, A note on stable flow-equivalent aggregation in closed networks. Queueing Syst. Theory Appl., 60:193–-202, December 2008, DOI 10.1007/s11134-008-9093-6

[CMS08]

G. Casale, R. R. Muntz, G. Serazzi, Geometric Bounds: a Non-Iterative Analysis Technique for Closed Queueing Networks, IEEE Transactions on Computers, 57(6):780-794, June 2008. DOI 10.1109/TC.2008.37

[GrSn97]

C. M. Grinstead, J. L. Snell, (July 1997). Introduction to Probability. American Mathematical Society. ISBN 978-0821807491; this excellent textbook is available in PDF format and can be used under the terms of the GNU Free Documentation License (FDL)

[Jac04]

J. R. Jackson, Jobshop-Like Queueing Systems, Vol. 50, No. 12, Ten Most Influential Titles of "Management Science’s" First Fifty Years (Dec., 2004), pp. 1796-1802, available online

[Jai91]

R. Jain, The Art of Computer Systems Performance Analysis, Wiley, 1991, p. 577.

[HsLa87]

C. H. Hsieh and S. Lam, Two classes of performance bounds for closed queueing networks, PEVA, vol. 7, n. 1, pp. 3–30, 1987

[Ker84]

T. Kerola, The Composite Bound Method (CBM) for Computing Throughput Bounds in Multiple Class Environments, Performance Evaluation, Vol. 6 Isue 1, March 1986, DOI 10.1016/0166-5316(86)90002-7; also available as Technical Report CSD-TR-475, Department of Computer Sciences, Purdue University, mar 13, 1984 (Revised aug 27, 1984).

[LZGS84]

E. D. Lazowska, J. Zahorjan, G. Scott Graham, and K. C. Sevcik, Quantitative System Performance: Computer System Analysis Using Queueing Network Models, Prentice Hall, 1984. available online.

[ReKo76]

M. Reiser, H. Kobayashi, On The Convolution Algorithm for Separable Queueing Networks, In Proceedings of the 1976 ACM SIGMETRICS Conference on Computer Performance Modeling Measurement and Evaluation (Cambridge, Massachusetts, United States, March 29–31, 1976). SIGMETRICS ’76. ACM, New York, NY, pp. 109–117. DOI 10.1145/800200.806187

[ReLa80]

M. Reiser and S. S. Lavenberg, Mean-Value Analysis of Closed Multichain Queuing Networks, Journal of the ACM, vol. 27, n. 2, April 1980, pp. 313–322. DOI 10.1145/322186.322195

[Sch79]

P. Schweitzer, Approximate Analysis of Multiclass Closed Networks of Queues, Proc. Int. Conf. on Stochastic Control and Optimization, jun 1979, pp. 25—29

[Sch80]

H. D. Schwetman, Testing Network-of-Queues Software, Technical Report CSD-TR 330, Department of computer Sciences, Purdue University, 1980

[Sch81]

H. D. Schwetman, Some Computational Aspects of Queueing Network Models, Technical Report CSD-TR-354, Department of Computer Sciences, Purdue University, feb, 1981 (revised).

[Sch82]

H. D. Schwetman, Implementing the Mean Value Algorithm for the Solution of Queueing Network Models, Technical Report CSD-TR-355, Department of Computer Sciences, Purdue University, feb 15, 1982.

[Sch84]

T. Kerola, H. D. Schwetman, Performance Bounds for Multiclass Models, Technical Report CSD-TR-479, Department of Computer Sciences, Purdue University, 1984.

[Tij03]

H. C. Tijms, A first course in stochastic models, John Wiley and Sons, 2003, ISBN 0471498807, ISBN 9780471498803, DOI 10.1002/047001363X

[ZaWo81]

J. Zahorjan and E. Wong, The solution of separable queueing network models using mean value analysis. SIGMETRICS Perform. Eval. Rev. 10, 3 (Sep. 1981), 80-85. DOI 10.1145/1010629.805477

[Zeng03]

G. Zeng, Two common properties of the erlang-B function, erlang-C function, and Engset blocking function, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296 DOI 10.1016/S0895-7177(03)90040-9


Next: , Previous: , Up: Top   [Contents][Index]

Appendix A GNU GENERAL PUBLIC LICENSE

Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. http://fsf.org/

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.

Preamble

The GNU General Public License is a free, copyleft license for software and other kinds of works.

The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program—to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.

To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it.

For the developers’ and authors’ protection, the GPL clearly explains that there is no warranty for this free software. For both users’ and authors’ sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions.

Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users’ freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users.

Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free.

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS

  1. Definitions.

    “This License” refers to version 3 of the GNU General Public License.

    “Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.

    “The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.

    To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.

    A “covered work” means either the unmodified Program or a work based on the Program.

    To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.

    To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.

    An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.

  2. Source Code.

    The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.

    A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.

    The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.

    The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work’s System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.

    The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.

    The Corresponding Source for a work in source code form is that same work.

  3. Basic Permissions.

    All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.

    You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.

    Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.

  4. Protecting Users’ Legal Rights From Anti-Circumvention Law.

    No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.

    When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work’s users, your or third parties’ legal rights to forbid circumvention of technological measures.

  5. Conveying Verbatim Copies.

    You may convey verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.

    You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.

  6. Conveying Modified Source Versions.

    You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:

    1. The work must carry prominent notices stating that you modified it, and giving a relevant date.
    2. The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
    3. You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
    4. If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.

    A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation’s users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.

  7. Conveying Non-Source Forms.

    You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:

    1. Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
    2. Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
    3. Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
    4. Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
    5. Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.

    A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.

    A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.

    “Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.

    If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).

    The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.

    Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.

  8. Additional Terms.

    “Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.

    When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.

    Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:

    1. Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
    2. Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
    3. Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
    4. Limiting the use for publicity purposes of names of licensors or authors of the material; or
    5. Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
    6. Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.

    All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.

    If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.

    Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.

  9. Termination.

    You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).

    However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.

    Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.

    Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.

  10. Acceptance Not Required for Having Copies.

    You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.

  11. Automatic Licensing of Downstream Recipients.

    Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.

    An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party’s predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.

    You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.

  12. Patents.

    A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor’s “contributor version”.

    A contributor’s “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.

    Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor’s essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.

    In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.

    If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient’s use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.

    If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.

    A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.

    Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.

  13. No Surrender of Others’ Freedom.

    If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.

  14. Use with the GNU Affero General Public License.

    Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.

  15. Revised Versions of this License.

    The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

    Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.

    If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Program.

    Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.

  16. Disclaimer of Warranty.

    THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  17. Limitation of Liability.

    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

  18. Interpretation of Sections 15 and 16.

    If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.

one line to give the program's name and a brief idea of what it does.  
Copyright (C) year name of author

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see http://www.gnu.org/licenses/.

Also add information on how to contact you by electronic and paper mail.

If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:

program Copyright (C) year name of author 
This program comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’.
This is free software, and you are welcome to redistribute it
under certain conditions; type ‘show c’ for details.

The hypothetical commands ‘show w’ and ‘show c’ should show the appropriate parts of the General Public License. Of course, your program’s commands might be different; for a GUI interface, you would use an “about box”.

You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see http://www.gnu.org/licenses/.

The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read http://www.gnu.org/philosophy/why-not-lgpl.html.


Next: , Previous: , Up: Top   [Contents][Index]

Concept Index

Jump to:   A   B   C   D   E   F   G   I   L   M   N   O   P   Q   R   S   T   U   W  
Index Entry  Section

A
absorption probabilities, DTMC: Mean time to absorption (DTMC)
approximate MVA: Single Class Models
asymmetric M/M/m system: The Asymmetric M/M/m System
asymptotic bounds: Bounds Analysis
asymptotic bounds: Bounds Analysis
average number of customers: Single Class Models
average number of customers: Multiple Class Models
average number of visits: Single Class Models
average number of visits: Multiple Class Models

B
balanced system bounds: Bounds Analysis
balanced system bounds: Bounds Analysis
BCMP network: Single Class Models
birth-death process, CTMC: Birth-death process (CTMC)
birth-death process, DTMC: Birth-death process (DTMC)
blocking queueing network: Single Class Models
blocking queueing network: Single Class Models
bounds, asymptotic: Bounds Analysis
bounds, asymptotic: Bounds Analysis
bounds, asymptotic: Bounds Analysis
bounds, asymptotic: Bounds Analysis
bounds, balanced system: Bounds Analysis
bounds, balanced system: Bounds Analysis
bounds, balanced system: Bounds Analysis
bounds, composite: Bounds Analysis
bounds, geometric: Bounds Analysis
bounds, PB: Bounds Analysis

C
closed multiclass network: Bounds Analysis
closed multiclass network: Bounds Analysis
closed multiclass network: Bounds Analysis
closed network: Single Class Models
closed network: Bounds Analysis
closed network: Bounds Analysis
closed network, approximate analysis: Single Class Models
closed network, finite capacity: Single Class Models
closed network, finite capacity: Single Class Models
closed network, multiple classes: Multiple Class Models
closed network, multiple classes: Multiple Class Models
closed network, multiple classes: Multiple Class Models
closed network, multiple classes: Multiple Class Models
closed network, multiple classes: Generic Algorithms
closed network, single class: Single Class Models
closed network, single class: Single Class Models
closed network, single class: Single Class Models
closed network, single class: Single Class Models
closed network, single class: Single Class Models
closed network, single class: Single Class Models
closed network, single class: Generic Algorithms
closed network, single class: Bounds Analysis
closed network, single class: Bounds Analysis
closed network, single class: Bounds Analysis
CMVA: Single Class Models
composite bounds: Bounds Analysis
conditional MVA (CMVA): Single Class Models
continuous time Markov chain: Continuous-Time Markov Chains
continuous time Markov chain: State occupancy probabilities (CTMC)
continuous time Markov chain: Birth-death process (CTMC)
continuous time Markov chain: Expected sojourn times (CTMC)
continuous time Markov chain: Time-averaged expected sojourn times (CTMC)
continuous time Markov chain: Mean time to absorption (CTMC)
continuous time Markov chain: First passage times (CTMC)
convolution algorithm: Single Class Models
convolution algorithm: Single Class Models
copyright: Copying
CTMC: Continuous-Time Markov Chains
CTMC: State occupancy probabilities (CTMC)
CTMC: Birth-death process (CTMC)
CTMC: Expected sojourn times (CTMC)
CTMC: Time-averaged expected sojourn times (CTMC)
CTMC: Mean time to absorption (CTMC)
CTMC: First passage times (CTMC)

D
delay center: Introduction to QNs
deprecated functions: Naming Conventions
discrete time Markov chain: Discrete-Time Markov Chains
discrete time Markov chain: Discrete-Time Markov Chains
discrete time Markov chain: State occupancy probabilities (DTMC)
discrete time Markov chain: Birth-death process (DTMC)
discrete time Markov chain: Expected number of visits (DTMC)
discrete time Markov chain: Time-averaged expected sojourn times (DTMC)
discrete time Markov chain: Mean time to absorption (DTMC)
discrete time Markov chain: First passage times (DTMC)
DTMC: Discrete-Time Markov Chains
DTMC: Discrete-Time Markov Chains
DTMC: State occupancy probabilities (DTMC)
DTMC: Birth-death process (DTMC)
DTMC: Expected number of visits (DTMC)
DTMC: Time-averaged expected sojourn times (DTMC)
DTMC: Mean time to absorption (DTMC)
DTMC: First passage times (DTMC)

E
Engset loss formula: The Engset Formula
Erlang-B formula: The Erlang-B Formula
Erlang-C formula: The Erlang-C Formula
expected sojourn time, CTMC: Expected sojourn times (CTMC)
expected sojourn times, DTMC: Expected number of visits (DTMC)
external arrival rate: Single Class Models
external arrival rate: Multiple Class Models

F
FCFS: Introduction to QNs
first passage times: First passage times (DTMC)
first passage times, CTMC: First passage times (CTMC)
First-Come-First-Served: Introduction to QNs
fundamental matrix: Mean time to absorption (DTMC)

G
geometric bounds: Bounds Analysis

I
infinite server: Introduction to QNs
Infinite Server: Introduction to QNs
irreducible Markov chain: Discrete-Time Markov Chains
irreducible Markov chain: Continuous-Time Markov Chains
IS: Introduction to QNs

L
Last-Come-First-Served Preemptive Resume: Introduction to QNs
LCFS-PR: Introduction to QNs
load-dependent service center: Single Class Models
load-dependent service center: Single Class Models

M
M/G/1 system: The M/G/1 System
M/H_m/1 system: The M/Hm/1 System
M/M/1 system: The M/M/1 System
M/M/1/K system: The M/M/1/K System
M/M/inf system: The M/M/inf System
M/M/m system: The M/M/m System
M/M/m/K system: The M/M/m/K System
Markov chain, continuous time: Continuous-Time Markov Chains
Markov chain, continuous time: Continuous-Time Markov Chains
Markov chain, continuous time: State occupancy probabilities (CTMC)
Markov chain, continuous time: Birth-death process (CTMC)
Markov chain, continuous time: Expected sojourn times (CTMC)
Markov chain, continuous time: Time-averaged expected sojourn times (CTMC)
Markov chain, continuous time: Mean time to absorption (CTMC)
Markov chain, continuous time: First passage times (CTMC)
Markov chain, discrete time: Discrete-Time Markov Chains
Markov chain, discrete time: Discrete-Time Markov Chains
Markov chain, discrete time: State occupancy probabilities (DTMC)
Markov chain, discrete time: Birth-death process (DTMC)
Markov chain, discrete time: Expected number of visits (DTMC)
Markov chain, discrete time: Time-averaged expected sojourn times (DTMC)
Markov chain, discrete time: Mean time to absorption (DTMC)
Markov chain, discrete time: First passage times (DTMC)
Markov chain, state occupancy probabilities: State occupancy probabilities (CTMC)
Markov chain, stationary probabilities: State occupancy probabilities (DTMC)
Markov chain, transient probabilities: State occupancy probabilities (DTMC)
mean recurrence times: First passage times (DTMC)
mean time to absorption, CTMC: Mean time to absorption (CTMC)
mean time to absorption, DTMC: Mean time to absorption (DTMC)
Mean Value Analysis, conditional (CMVA): Single Class Models
Mean Value Analysys (MVA): Single Class Models
Mean Value Analysys (MVA): Single Class Models
Mean Value Analysys (MVA): Multiple Class Models
Mean Value Analysys (MVA): Multiple Class Models
Mean Value Analysys (MVA), approximate: Single Class Models
Mean Value Analysys (MVA), approximate: Multiple Class Models
mixed network: Multiple Class Models
multiclass network, closed: Multiple Class Models
multiclass network, closed: Multiple Class Models
multiclass network, closed: Bounds Analysis
multiclass network, closed: Bounds Analysis
multiclass network, closed: Bounds Analysis
multiclass network, open: Multiple Class Models
multiclass network, open: Bounds Analysis
multiple class queueing network: Introduction to QNs
multiple class queueing network: Multiple Class Models
MVA: Single Class Models
MVA, approximate: Single Class Models
MVA, approximate: Multiple Class Models
MVABLO: Single Class Models

N
normalization constant: Single Class Models
normalization constant: Single Class Models
normalization constant: Single Class Models

O
open network: Generic Algorithms
open network: Bounds Analysis
open network: Bounds Analysis
open network: Bounds Analysis
open network, multiple classes: Multiple Class Models
open network, single class: Single Class Models
open network, single class: Single Class Models

P
PB bounds: Bounds Analysis
population mix: Multiple Class Models
population mix: Multiple Class Models
Processor Sharing: Introduction to QNs
product-form queueing network: Introduction to QNs
PS: Introduction to QNs

Q
queueing network with blocking: Single Class Models
queueing network, multiple class: Introduction to QNs
queueing network, multiple class: Multiple Class Models
queueing network, product-form: Introduction to QNs
queueing network, single class: Introduction to QNs
queueing network, single class: Single Class Models
queueing networks: Queueing Networks

R
response time: Single Class Models
response time: Multiple Class Models
routing probability matrix: Single Class Models
routing probability matrix: Multiple Class Models
RS blocking: Single Class Models

S
service time: Single Class Models
service time: Multiple Class Models
single class queueing network: Introduction to QNs
single class queueing network: Single Class Models
stationary probabilities: State occupancy probabilities (CTMC)
stochastic matrix: Discrete-Time Markov Chains
system response time: Single Class Models
system response time: Multiple Class Models
system throughput: Single Class Models
system throughput: Multiple Class Models

T
throughput: Single Class Models
throughput: Multiple Class Models
time-alveraged sojourn time, CTMC: Time-averaged expected sojourn times (CTMC)
time-alveraged sojourn time, DTMC: Time-averaged expected sojourn times (DTMC)
traffic intensity: The M/M/inf System

U
utilization: Single Class Models
utilization: Multiple Class Models

W
warranty: Copying

Jump to:   A   B   C   D   E   F   G   I   L   M   N   O   P   Q   R   S   T   U   W  

Previous: , Up: Top   [Contents][Index]

Function Index

Jump to:   C   D   E   Q  
Index Entry  Section

C
ctmc: State occupancy probabilities (CTMC)
ctmc: State occupancy probabilities (CTMC)
ctmcbd: Birth-death process (CTMC)
ctmcchkQ: Continuous-Time Markov Chains
ctmcexps: Expected sojourn times (CTMC)
ctmcexps: Expected sojourn times (CTMC)
ctmcfpt: First passage times (CTMC)
ctmcfpt: First passage times (CTMC)
ctmcisir: Continuous-Time Markov Chains
ctmcmtta: Mean time to absorption (CTMC)
ctmctaexps: Time-averaged expected sojourn times (CTMC)
ctmctaexps: Time-averaged expected sojourn times (CTMC)

D
dtmc: State occupancy probabilities (DTMC)
dtmc: State occupancy probabilities (DTMC)
dtmcbd: Birth-death process (DTMC)
dtmcchkP: Discrete-Time Markov Chains
dtmcexps: Expected number of visits (DTMC)
dtmcexps: Expected number of visits (DTMC)
dtmcfpt: First passage times (DTMC)
dtmcisir: Discrete-Time Markov Chains
dtmcmtta: Mean time to absorption (DTMC)
dtmcmtta: Mean time to absorption (DTMC)
dtmctaexps: Time-averaged expected sojourn times (DTMC)
dtmctaexps: Time-averaged expected sojourn times (DTMC)

E
engset: The Engset Formula
erlangb: The Erlang-B Formula
erlangc: The Erlang-C Formula

Q
qnclosed: Generic Algorithms
qncmaba: Bounds Analysis
qncmaba: Bounds Analysis
qncmaba: Bounds Analysis
qncmaba: Bounds Analysis
qncmbsb: Bounds Analysis
qncmbsb: Bounds Analysis
qncmcb: Bounds Analysis
qncmcb: Bounds Analysis
qncmmva: Multiple Class Models
qncmmva: Multiple Class Models
qncmmva: Multiple Class Models
qncmmva: Multiple Class Models
qncmmva: Multiple Class Models
qncmmva: Multiple Class Models
qncmmva: Multiple Class Models
qncmmvabs: Multiple Class Models
qncmmvabs: Multiple Class Models
qncmmvabs: Multiple Class Models
qncmmvabs: Multiple Class Models
qncmmvabs: Multiple Class Models
qncmnpop: Multiple Class Models
qncmpopmix: Multiple Class Models
qncmvisits: Multiple Class Models
qncmvisits: Multiple Class Models
qncsaba: Bounds Analysis
qncsaba: Bounds Analysis
qncsaba: Bounds Analysis
qncsaba: Bounds Analysis
qncsbsb: Bounds Analysis
qncsbsb: Bounds Analysis
qncsbsb: Bounds Analysis
qncsbsb: Bounds Analysis
qncscmva: Single Class Models
qncscmva: Single Class Models
qncsconv: Single Class Models
qncsconv: Single Class Models
qncsconvld: Single Class Models
qncsgb: Bounds Analysis
qncsgb: Bounds Analysis
qncsgb: Bounds Analysis
qncsgb: Bounds Analysis
qncsmva: Single Class Models
qncsmva: Single Class Models
qncsmva: Single Class Models
qncsmvaap: Single Class Models
qncsmvaap: Single Class Models
qncsmvaap: Single Class Models
qncsmvaap: Single Class Models
qncsmvaap: Single Class Models
qncsmvablo: Single Class Models
qncsmvald: Single Class Models
qncsmvald: Single Class Models
qncspb: Bounds Analysis
qncspb: Bounds Analysis
qncspb: Bounds Analysis
qncspb: Bounds Analysis
qncsvisits: Single Class Models
qncsvisits: Single Class Models
qnmarkov: Single Class Models
qnmarkov: Single Class Models
qnmarkov: Single Class Models
qnmarkov: Single Class Models
qnmix: Multiple Class Models
qnmknode: Generic Algorithms
qnmknode: Generic Algorithms
qnmknode: Generic Algorithms
qnmknode: Generic Algorithms
qnmknode: Generic Algorithms
qnmknode: Generic Algorithms
qnmknode: Generic Algorithms
qnom: Multiple Class Models
qnom: Multiple Class Models
qnom: Multiple Class Models
qnom: Multiple Class Models
qnomaba: Bounds Analysis
qnomaba: Bounds Analysis
qnomvisits: Multiple Class Models
qnopen: Generic Algorithms
qnos: Single Class Models
qnos: Single Class Models
qnosaba: Bounds Analysis
qnosaba: Bounds Analysis
qnosaba: Bounds Analysis
qnosbsb: Bounds Analysis
qnosbsb: Bounds Analysis
qnosvisits: Single Class Models
qnsolve: Generic Algorithms
qnsolve: Generic Algorithms
qnsolve: Generic Algorithms
qnsolve: Generic Algorithms
qsammm: The Asymmetric M/M/m System
qsmg1: The M/G/1 System
qsmh1: The M/Hm/1 System
qsmm1: The M/M/1 System
qsmm1: The M/M/1 System
qsmm1k: The M/M/1/K System
qsmm1k: The M/M/1/K System
qsmminf: The M/M/inf System
qsmminf: The M/M/inf System
qsmmm: The M/M/m System
qsmmm: The M/M/m System
qsmmm: The M/M/m System
qsmmmk: The M/M/m/K System
qsmmmk: The M/M/m/K System

Jump to:   C   D   E   Q  

queueing/doc/qn_closed_multi_cs.fig0000664000175000017500000000471514620404470017374 0ustar morenomoreno#FIG 3.2 Produced by xfig version 3.2.5b Landscape Center Metric A4 100.00 Single -2 1200 2 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6570 5580 180 180 6570 5580 6750 5580 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 4770 5130 180 180 4770 5130 4950 5130 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6570 4680 180 180 6570 4680 6750 4680 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 6750 4590 7200 4590 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 6750 5490 7200 5490 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 5 0 0 1.00 60.00 120.00 7200 5490 7200 4140 4230 4140 4230 5040 4590 5040 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 4950 5220 6120 5220 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 3 0 0 1.00 60.00 120.00 6120 5220 6120 4770 6390 4770 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 3 0 0 1.00 60.00 120.00 6120 5220 6120 5670 6390 5670 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 4950 5040 5850 5040 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 3 0 0 1.00 60.00 120.00 5850 5040 5850 4590 6390 4590 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 3 0 0 1.00 60.00 120.00 5850 5040 5850 5490 6390 5490 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 6750 4770 7380 4770 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 6750 5670 7380 5670 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 5 0 0 1.00 60.00 120.00 7380 4770 7380 6120 4230 6120 4230 5220 4590 5220 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 3 0 0 1.00 60.00 120.00 5310 5220 5310 4590 4230 4590 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 3 0 0 1.00 60.00 120.00 5130 5040 5130 5670 4230 5670 4 0 0 50 -1 0 10 0.0000 4 105 75 6525 5625 3\001 4 0 0 50 -1 0 10 0.0000 4 105 75 4725 5175 1\001 4 0 0 50 -1 0 10 0.0000 4 105 75 6525 4725 2\001 4 0 0 50 -1 0 10 0.0000 4 105 120 6165 4950 .3\001 4 0 0 50 -1 0 10 0.0000 4 105 120 5805 4545 .7\001 4 0 0 50 -1 0 10 0.0000 4 105 120 5805 5670 .2\001 4 0 0 50 -1 0 10 0.0000 4 105 120 6075 5850 .5\001 4 0 0 50 -1 0 10 0.0000 4 105 120 5265 4545 .2\001 4 0 0 50 -1 0 10 0.0000 4 105 120 5085 5850 .1\001 4 0 0 50 -1 0 10 0.0000 4 105 450 4230 4095 Class 1\001 4 0 0 50 -1 0 10 0.0000 4 105 450 4230 6300 Class 2\001 4 0 0 50 -1 0 10 0.0000 4 105 315 4590 4905 CPU\001 4 0 0 50 -1 0 10 0.0000 4 105 210 6480 5355 I/O\001 4 0 0 50 -1 0 10 0.0000 4 105 210 6480 4455 I/O\001 4 0 0 50 -1 0 10 0.0000 4 105 165 4680 5490 PS\001 4 0 0 50 -1 0 10 0.0000 4 105 360 6390 4995 FCFS\001 4 0 0 50 -1 0 10 0.0000 4 105 360 6390 5895 FCFS\001 queueing/doc/qn_closed_single.fig0000664000175000017500000000300514620404470017025 0ustar morenomoreno#FIG 3.2 Produced by xfig version 3.2.5b Landscape Center Metric A4 100.00 Single -2 1200 2 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6930 5580 270 270 6930 5580 6930 5310 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6930 4500 270 270 6930 4500 6930 4230 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5317 5043 270 270 5317 5043 5317 4773 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 4 0 0 1.00 60.00 120.00 5580 5040 5850 5040 6030 4500 6300 4500 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3 0 0 1.00 60.00 120.00 5850 5040 6030 5580 6300 5580 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 5 0 0 1.00 60.00 120.00 7470 5580 7470 3960 4770 3960 4770 5040 5040 5040 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 7200 5580 7470 5580 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6300 5310 6660 5310 6660 5850 6300 5850 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6300 4230 6660 4230 6660 4770 6300 4770 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 7200 4500 7470 4500 4 0 0 50 -1 0 12 0.0000 4 135 255 5895 5760 0.7\001 4 0 0 50 -1 0 12 0.0000 4 135 255 5895 4455 0.3\001 4 0 0 50 -1 0 12 0.0000 4 135 210 5175 5490 PS\001 4 0 0 50 -1 0 12 0.0000 4 135 450 6705 4950 FCFS\001 4 0 0 50 -1 0 12 0.0000 4 135 450 6705 6030 FCFS\001 4 0 0 50 -1 0 12 0.0000 4 135 375 5130 4725 CPU\001 4 0 0 50 -1 0 12 0.0000 4 135 480 6705 4185 Disk1\001 4 0 0 50 -1 0 12 0.0000 4 135 480 6705 5265 Disk2\001 4 0 0 50 -1 0 12 0.0000 4 135 105 5265 5085 1\001 4 0 0 50 -1 0 12 0.0000 4 135 105 6885 4545 2\001 4 0 0 50 -1 0 12 0.0000 4 135 105 6885 5625 3\001 queueing/doc/demo_web.m0000664000175000017500000000552714620404470015000 0ustar morenomoreno## Copyright (C) 2012, 2016 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see 1; # not a function file # figure (1, "visible", "off"); # do not show plot window page_screen_output(0); # avoid output pagination N = 100; # total population size beta = linspace(0.1,0.9,18); # population mix for class 1 D = [12 14 23 20 80 31; ... 2 20 14 90 30 33 ]; V = ones(size(D)); X1 = X1 = XX = zeros(size(beta)); R1 = R2 = RR = zeros(size(beta)); for i=1:length(beta) pop = [fix(beta(i)*N) N-fix(beta(i)*N)]; [U R Q X] = qncmmva( pop, D, V ); X1(i) = X(1,1) / V(1,1); X2(i) = X(2,1) / V(2,1); XX(i) = X1(i) + X2(i); R1(i) = dot(R(1,:), V(1,:)); R2(i) = dot(R(2,:), V(2,:)); RR(i) = N / XX(i); endfor ## Plot throughput and response times ## set(gcf,"paperorientation","landscape"); ## papersize=[4 3] * 2; margin=[0 0]; ## set(gcf,"papersize",papersize); ## set(gcf,"paperposition", [margin papersize-margin*2]); subplot(2,1,1); plot(beta, X1, "--;Class 1;", "linewidth", 2, ... beta, X2, ":;Class 2;", "linewidth", 2, ... beta, XX, "-;System;", "linewidth", 2 ); ylabel("Throughput"); legend("location", "south", "orientation", "horizontal"); legend("boxoff"); title("Throughput and response time vs population mix"); subplot(2,1,2); plot(beta, R1, "--;Class 1;", "linewidth", 2, ... beta, R2, ":;Class 2;", "linewidth", 2, ... beta, RR, "-;System;", "linewidth", 2 ); ax = axis(); ax(3) = 0; axis(ax); legend("location", "south", "orientation", "horizontal"); legend("boxoff"); xlabel("Class 1 population mix"); ylabel("Response Time"); print("web.eps", "-deps2", "-mono", "-tight"); clf; ## Plot system power ## set(gcf,"paperorientation","landscape"); ## papersize=[4 2.5] * 1.2; margin=[0 0]; ## set(gcf,"papersize",papersize); ## set(gcf,"paperposition", [margin papersize-margin*2]); plot(beta, X1./R1, "--;Class 1;", "linewidth", 2, ... beta, X2./R2, ":;Class 2;", "linewidth", 2, ... beta, XX./RR, "-;System;", "linewidth", 2); legend("location","south", "orientation", "horizontal"); legend("boxoff"); xlabel("Class 1 population mix"); ylabel("Power"); title("Power as a function of the population mix"); print("power.eps", "-deps2", "-mono", "-tight"); queueing/doc/qn_closed_multi_apl.png0000664000175000017500000000416214620415625017562 0ustar morenomorenoPNG  IHDRPLTEٟ'IDATxn6pzK1b:%vʽ:`譇5RoP Nm`FIEa"Z+vd!B8,l`f:l4hF3ь8#D8o r=+>As>3>`|ŚWm_A5f4OYXâ9GPy~yCi1+s34cV<82F&P6&9M#iT4`MSJt &%c3q0p0Hp#곙Uhje혌>^Y2nL2QԱ ĸ1ĸؾ[Â+LU(2 L0S`L&r sZ@9:hL4˜IN^ ˣxt$^p^jf.nj4d"y}Ј"B xFc\vM>7dѻ5TREt02nsB&qaјn SƴaҰr<<& Q>3`I3I䚌}UMcpm#<=Vȸm㖦}jycՄCmbMɒꚁ}If@$ϻϝ#*gd6j&؀uMFfTu(Œ,s1LqId\ Sq:&i֤>#7̻t5ZA 4\)פaFɺ5Oa6J21>/|asH<>Ly=1b5խِ1zgB垗+ȪK>BY 0 QX݁>!JF5H0:YYp9z+}ި2@7>M b[D^FY~Le6H dzTIl@C #K2շtbr5&`FtyDZU6D15 c$SDU 1eO1& ȨdTT7L!bI32ѴaIp`&'4SZ e4xx-0BOy[`f~u{67G٬v@]==m?>J%Mm&&Q>K~h1%,b:h8f6.M3hxj.;M(mt]7 ŶҖ] uEfi6e4|U=/e3_;7Z;ZijLs \lI_fMvBCS3aT|ξ Q)9 y"v3ܹ8O>#ڶܻq-sU;!}XTlUl sfI)Zcʉoyi5Sf#}$1 <ՌXbtkX3k֍<躞Fr:K7zaLX.ϗ13@ϤȪ1yL6W3H#>l8,w(|iaTs^/bX2[a Xi<%d^3f*ry0>v0"&sZOjE0,Ϣ0jE@ËkNNkHߨo*}1ĸ ĸ1ĔokFjaul1FYSIGv X[5N.Q3= 47M m# ik=zL&]UmS{YRF3 ]l=4>:Ԟi5-X|&}}Z z X7Mڌ;m1w>5o:Ҫ8Nmj}tz{`?42Ƶ=,@s1smhdNHH(ggy#OCfl1u1A~IENDB`queueing/doc/qn_closed_multi_apl.pdf0000664000175000017500000001226214620415627017551 0ustar morenomoreno%PDF-1.5 %쏢 %%Invocation: gs -q -dSAFER -dNOPAUSE -dBATCH -dCompatibilityLevel=1.5 -sDEVICE=pdfwrite -sOutputFile=? -dPDFSETTINGS#/prepress -dMaxSubsetPct=100 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoRotatePages#/None - 5 0 obj <> stream x}Uj1+t:`E֣uL w!8 C~?=&kg1xV%U?['mӶ4IV$ۏYJFH' zH2;S26 ד@u+ZhM+Z ꣭'բhHY8cRj|4d2kI0l2'E¨ں"¨|t hI(Ңlh%C.l]CȚB1̚akBhy0\=p.WP%X/@ҏSX{Zӑ?~ ǬWBF IUBפuB߅ @K(A~ȃFꍁHJ 2d1)mP a).&(g&09w\sC ٪|'(E6\ApEsOB-"bh6gE0Y!UyS 8Oc2,tm r|*ОIYa,GSL73&/Z.ӨgJFpjS%ܲ,^L-cd;ٗ#ɦe˕^%8.#ӳ x<ez؝y^IJulϙpT7/endstream endobj 6 0 obj 736 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 10 0 obj <> endobj 11 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> endobj 12 0 obj <>stream xQkPW%dVcjI#D4ڱbQjEP| bb&PbrYH j%X,m}*R;NwMgXgw=|cJQVe˙PY,AҷH m_\o7v.Qie$-_be:FS$\V~uG(Tfɗr:_+ڥT_ʓc1 5}G5ۈa*,[a"ml6)Ǹ? 'iy*/ OE/+>PUZ3w!{ogK%zK-vsWydW|H p@J5kQ-7z1"YسWVݝ}abV'FVXKmR#ՅːY3tISI;a=tU/ۥ'j]ٔ6t)+[m㸮{Hr<(Dː_8%B4CWH?6VqW WiO$͖@ LMЌn=mcg&*cfagbNlUHACc'9|iἿK~-ah>GO<,4' /26Tp^rf0{TI:%zfK:M+Gc՜k).4*A8,֕Uvy<}Dv؛p^tFgMx^\{6@gjjΠ[ KLgb.rTaA'{h%[/Zl-I -:sы._gwKz A;!dNpGA9Cs&hp9 ix:cKٞ`6;C8^L5Z(6UgsHX+QO??%S-IIΒ* vwރWIQߋ|33Pō tB1,Td Kߪ.9%k1 (2RK{':eCHyI; D~9IlJm>n\y;MLŵ>,Bä֣o}US0X endstream endobj 13 0 obj <>stream 2024-05-13T15:54:31+02:00 2024-05-13T15:54:31+02:00 fig2dev Version 3.2.7a qn_closed_multi_apl.fig endstream endobj 2 0 obj <>endobj xref 0 14 0000000000 65535 f 0000001263 00000 n 0000004677 00000 n 0000001204 00000 n 0000001053 00000 n 0000000228 00000 n 0000001034 00000 n 0000001328 00000 n 0000001429 00000 n 0000001685 00000 n 0000001369 00000 n 0000001399 00000 n 0000001929 00000 n 0000003237 00000 n trailer << /Size 14 /Root 1 0 R /Info 2 0 R /ID [<21BD1FCAF06B3F22872DBF725070C67B><21BD1FCAF06B3F22872DBF725070C67B>] >> startxref 4865 %%EOF queueing/doc/qn_closed_multi_cs.pdf0000664000175000017500000001473714620415630017405 0ustar morenomoreno%PDF-1.5 %쏢 %%Invocation: gs -q -dSAFER -dNOPAUSE -dBATCH -dCompatibilityLevel=1.5 -sDEVICE=pdfwrite -sOutputFile=? -dPDFSETTINGS#/prepress -dMaxSubsetPct=100 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoRotatePages#/None - 5 0 obj <> stream xWK5- :.}%")IvM J#%{kz&=ì&e_=I}|ZN۠]{DžB:[Z'\Q|&*N))iFg79\2UbhsN 6@)Rl!ѽˡa|Zz2ƫHaDV#&*:m~gBFhlb,tU -^ GoC6+ۙ) F{H@ie0U;mX k̽ȽIdP*GPLyZ%;bTGf,I,U͉,ϩ\^n"ؕ1!Q1]i' U͙ҮR}{z} O䡆ТaSjQvc`NE=+jBNP[y OOri6z`_Z *ԃO/wF|ˇ Mqʡɲib_XӛNzpBy[tendstream endobj 6 0 obj 1258 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 10 0 obj <> endobj 11 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> endobj 12 0 obj <>stream xT{PSW$,d`T][-E\+e|R#BC_P B$@ȕ69!% J VGjRweۙs;{vf}1o|RRfߡq:ȇ^)ff"ym "GQ:Ǹ8#wVxw*@.Z:+܌?,Kek3hsC+Kfh>a[rH [1l ǖcX[^cñb:[\D\qƹQbnw+o;>!!bBd ?n83((AZ(hj[jupmwB!$d{9ȭʵP(qwCh ݡKѬo~e@7<΍4͡sQ41BO3f)RSVk : tGblw>1^xj 4)6n贝`eqHXVot [B]A%Z3Ga9,2hj55D&ns|G|=7%f (TiYyWW5BM?TYc ]BOO̰vz3>Ӝ E;j2MZJV}uq |iECe# Eihu:m @G詢 &%pKK!ٔ,VG[l̵\mD$]P"Q0U#9 <[{l @eQWrJuUgΉI fҨ>_}DAf 8&Yq^_P0QZWbAJ6fv s'9on;pr<]BHAօo]\ĐyJ#b >f<Bt+XG"}`1WktSZZmf`*<̖gDWoJ9!;Rj-i氝W_HCb6/[`KE2=|7˓ϙFS*:x`~zGtM>4F\.` ģ漪%i'G22gώ0&;solb&|A2CU~sn>qC=Ё-u26| +v#¿ FK-zjx0iNlՈ8p/JZݡ>g>stream 2024-05-13T15:54:31+02:00 2024-05-13T15:54:31+02:00 fig2dev Version 3.2.7a qn_closed_multi_cs.fig endstream endobj 2 0 obj <>endobj xref 0 14 0000000000 65535 f 0000001786 00000 n 0000006003 00000 n 0000001727 00000 n 0000001576 00000 n 0000000228 00000 n 0000001556 00000 n 0000001851 00000 n 0000001952 00000 n 0000002311 00000 n 0000001892 00000 n 0000001922 00000 n 0000002606 00000 n 0000004564 00000 n trailer << /Size 14 /Root 1 0 R /Info 2 0 R /ID [<43F3140AE5DA825B0C8BFC604DB0B7D8><43F3140AE5DA825B0C8BFC604DB0B7D8>] >> startxref 6190 %%EOF queueing/doc/qn_closed_multi.pdf0000664000175000017500000001350714620415627016720 0ustar morenomoreno%PDF-1.5 %쏢 %%Invocation: gs -q -dSAFER -dNOPAUSE -dBATCH -dCompatibilityLevel=1.5 -sDEVICE=pdfwrite -sOutputFile=? -dPDFSETTINGS#/prepress -dMaxSubsetPct=100 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoRotatePages#/None - 5 0 obj <> stream xUɮS1 +8d @X ]$x ~'N.TJms9qC=|)K 1E?]/9F/e *TB3DDluttk?Ti_E --2 8On@,>eeBv)G@M_ B)6򌒚ðZXAVY!z `Y3_ ~/ 1$!U8*~YQ#6,V#4$@e= ci8UW2TnDf>2#Yf~UP~e {5cJik"T!$u,!HR$&<yԻ5NQC>y%B-~.'!Vل%d^dè^ޯ[j3(B-Sl59gl)P*β/([BrH*-gg˙l̚SX\ւJ QK*k.5T8Hzcr^%= bOmhx,RyodN2FLaU"m.S.WX Wu!=ԅ1Ц.&aUMڄ }d>dkzf@B1N5ޣG}ʁH;:TTD_4M?,ON(iz7ޓw_cv'oN}wvZ(s85 7*Cj*QTtWDq NI'$˨u*P1KX2(a4vǷ|7~s7Ӄ J׍endstream endobj 6 0 obj 796 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 10 0 obj <> endobj 11 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> endobj 12 0 obj <>stream xT{PSW$ljFI$ڝ(Z] Zy(- ! r  'HDBF!`|Ej-UW>ӝie̹eg97;1nxhB)/JV+sTo8,@j>m~b0CHny_FlOo3-9wywT_\JRT&/S䫤d:yD)Wi}2g|mqN0IVH)J+Y')-R8,ۆX ?`82+t\86dc.A3V4磩 yN#̺*c94Aк3Ù %ȣ!l$bqk(xS?/~?#޸4?"/򨻶| hCKՋ_5#>QͤLlH bYgHkѸP2=%s;~RϤ 2 sjqFWOj}F/~OؗWѺ饂3F؀"y5hfX\ӪqjZ X)?^d@yg,ewo.ӈ 6c3o̵/N0ؔh_1=b>T{)y]|޼ b@St[z ~`vWQ{5]~bm:$M.:@7y@&N$JS\[N)`!)>u%8=~E,8phI>0̖B茥TIӒv98^|tU=7g~vd  "7Sm#6uZYx} ǨcQ}J GE\\vRCSf [p[j=z@l3ѩ<鴵7PwUeIkw~DQ|c}^Oz~zifT 1T.2V#˴ 5F}D-Է@p#/Y􅪂LAܤs]խ:X f|0b q)A|;Y$hݩ6~~Sڥ cCWόU:JG>~=/~!DZU{r[fxI-(rL&Q\a@*e/B{ jyl#l6'n*SpQTBx!b/9h!>6y@B53Rx.Cd!lS/ޡ{nZ"խy;k3"@ǟO݁3}=5]'.RnKȯ>stream 2024-05-13T15:54:31+02:00 2024-05-13T15:54:31+02:00 fig2dev Version 3.2.7a qn_closed_multi.fig endstream endobj 2 0 obj <>endobj xref 0 14 0000000000 65535 f 0000001323 00000 n 0000005342 00000 n 0000001264 00000 n 0000001113 00000 n 0000000228 00000 n 0000001094 00000 n 0000001388 00000 n 0000001489 00000 n 0000001840 00000 n 0000001429 00000 n 0000001459 00000 n 0000002110 00000 n 0000003906 00000 n trailer << /Size 14 /Root 1 0 R /Info 2 0 R /ID [<991FEA40167C8E81BEC92A0570DE316B><991FEA40167C8E81BEC92A0570DE316B>] >> startxref 5526 %%EOF queueing/doc/singlestation.texi0000664000175000017500000006200014620415615016607 0ustar morenomoreno@c This file has been automatically generated from singlestation.txi @c by proc.m. Do not edit this file, all changes will be lost @c -*- texinfo -*- @c Copyright (C) 2008, 2009, 2010, 2011, 2012, 2014, 2016, 2018 Moreno Marzolla @c @c This file is part of the queueing package. @c @c The queueing package is free software; you can redistribute it @c and/or modify it under the terms of the GNU General Public License @c as published by the Free Software Foundation; either version 3 of @c the License, or (at your option) any later version. @c @c The queueing package is distributed in the hope that it will be @c useful, but WITHOUT ANY WARRANTY; without even the implied warranty @c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @c GNU General Public License for more details. @c @c You should have received a copy of the GNU General Public License @c along with the queueing package; see the file COPYING. If not, see @c . @node Single Station Queueing Systems @chapter Single Station Queueing Systems Single Station Queueing Systems contain a single station, and can usually be analyzed easily. The @code{queueing} package contains functions for handling the following types of queues: @ifnottex @menu * The M/M/1 System:: Single-server queueing station. * The M/M/m System:: Multiple-server queueing station. * The Erlang-B Formula:: * The Erlang-C Formula:: * The Engset Formula:: * The M/M/inf System:: Infinite-server (delay center) station. * The M/M/1/K System:: Single-server, finite-capacity queueing station. * The M/M/m/K System:: Multiple-server, finite-capacity queueing station. * The Asymmetric M/M/m System:: Asymmetric multiple-server queueing station. * The M/G/1 System:: Single-server with general service time distribution. * The M/Hm/1 System:: Single-server with hyperexponential service time distribution. @end menu @end ifnottex @iftex @itemize @item @math{M/M/1} single-server queueing station; @item @math{M/M/m} multiple-server queueing station; @item Asymmetric @math{M/M/m}; @item @math{M/M/\infty} infinite-server station (delay center); @item @math{M/M/1/K} single-server, finite-capacity queueing station; @item @math{M/M/m/K} multiple-server, finite-capacity queueing station; @item @math{M/G/1} single-server with general service time distribution; @item @math{M/H_m/1} single-server with hyperexponential service time distribution. @end itemize @end iftex @c @c M/M/1 @c @node The M/M/1 System @section The @math{M/M/1} System The @math{M/M/1} system contains a single server connected to an unbounded FCFS queue. Requests arrive according to a Poisson process with rate @math{\lambda}; the service time is exponentially distributed with average service rate @math{\mu}. The system is stable if @math{\lambda < \mu}. @anchor{doc-qsmm1} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qsmm1 (@var{lambda}, @var{mu}) @deftypefnx {Function File} {@var{pk} =} qsmm1 (@var{lambda}, @var{mu}, @var{k}) @cindex @math{M/M/1} system Compute utilization, response time, average number of requests and throughput for a @math{M/M/1} queue. @tex The steady-state probability @math{\pi_k} that there are @math{k} jobs in the system, @math{k \geq 0}, can be computed as: $$ \pi_k = (1-\rho)\rho^k $$ where @math{\rho = \lambda/\mu} is the server utilization. @end tex @strong{INPUTS} @table @code @item @var{lambda} Arrival rate (@code{@var{lambda} @geq{} 0}). @item @var{mu} Service rate (@code{@var{mu} > @var{lambda}}). @item @var{k} Number of requests in the system (@code{@var{k} @geq{} 0}). @end table @strong{OUTPUTS} @table @code @item @var{U} Server utilization @item @var{R} Server response time @item @var{Q} Average number of requests in the system @item @var{X} Server throughput. If the system is ergodic (@code{@var{mu} > @var{lambda}}), we always have @code{@var{X} = @var{lambda}} @item @var{p0} Steady-state probability that there are no requests in the system. @item @var{pk} Steady-state probability that there are @var{k} requests in the system. (including the one being served). @end table If this function is called with less than three input parameters, @var{lambda} and @var{mu} can be vectors of the same size. In this case, the results will be vectors as well. @strong{REFERENCES} @itemize @item G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998, Section 6.3 @end itemize @xseealso{qsmmm, qsmminf, qsmmmk} @end deftypefn @c @c M/M/m @c @node The M/M/m System @section The @math{M/M/m} System The @math{M/M/m} system is similar to the @math{M/M/1} system, except that there are @math{m \geq 1} identical servers connected to a shared FCFS queue. Thus, at most @math{m} requests can be served at the same time. The @math{M/M/m} system can be seen as a single server with load-dependent service rate @math{\mu(n)}, which is a function of the number @math{n} of requests in the system: @iftex @tex $$\mu(n) = \mu \times \min(m,n)$$ @end tex @end iftex @ifnottex @example mu(n) = min(m,n)*mu @end example @end ifnottex @noindent where @math{\mu} is the service rate of each individual server. @anchor{doc-qsmmm} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pm}] =} qsmmm (@var{lambda}, @var{mu}) @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pm}] =} qsmmm (@var{lambda}, @var{mu}, @var{m}) @deftypefnx {Function File} {@var{pk} =} qsmmm (@var{lambda}, @var{mu}, @var{m}, @var{k}) @cindex @math{M/M/m} system Compute utilization, response time, average number of requests in service and throughput for a @math{M/M/m} queue, a queueing system with @math{m} identical servers connected to a single FCFS queue. @tex The steady-state probability @math{\pi_k} that there are @math{k} requests in the system, @math{k \geq 0}, can be computed as: $$ \pi_k = \cases{ \displaystyle{\pi_0 { ( m\rho )^k \over k!}} & $0 \leq k \leq m$;\cr\cr \displaystyle{\pi_0 { \rho^k m^m \over m!}} & $k>m$.\cr } $$ where @math{\rho = \lambda/(m\mu)} is the individual server utilization. The steady-state probability @math{\pi_0} that there are no jobs in the system is: $$ \pi_0 = \left[ \sum_{k=0}^{m-1} { (m\rho)^k \over k! } + { (m\rho)^m \over m!} {1 \over 1-\rho} \right]^{-1} $$ @end tex @strong{INPUTS} @table @code @item @var{lambda} Arrival rate (@code{@var{lambda}>0}). @item @var{mu} Service rate (@code{@var{mu}>@var{lambda}}). @item @var{m} Number of servers (@code{@var{m} @geq{} 1}). Default is @code{@var{m}=1}. @item @var{k} Number of requests in the system (@code{@var{k} @geq{} 0}). @end table @strong{OUTPUTS} @table @code @item @var{U} Service center utilization, @math{U = \lambda / (m \mu)}. @item @var{R} Service center mean response time @item @var{Q} Average number of requests in the system @item @var{X} Service center throughput. If the system is ergodic, we will always have @code{@var{X} = @var{lambda}} @item @var{p0} Steady-state probability that there are 0 requests in the system @item @var{pm} Steady-state probability that an arriving request has to wait in the queue @item @var{pk} Steady-state probability that there are @var{k} requests in the system (including the one being served). @end table If this function is called with less than four parameters, @var{lambda}, @var{mu} and @var{m} can be vectors of the same size. In this case, the results will be vectors as well. @strong{REFERENCES} @itemize @item G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998, Section 6.5 @end itemize @xseealso{erlangc,qsmm1,qsmminf,qsmmmk} @end deftypefn @c @c Erlang-B @c @node The Erlang-B Formula @section The Erlang-B Formula @anchor{doc-erlangb} @deftypefn {Function File} {@var{B} =} erlangb (@var{A}, @var{m}) @cindex Erlang-B formula Compute the steady-state blocking probability in the Erlang loss model. The Erlang-B formula @math{E_B(A, m)} gives the probability that an open system with @math{m} identical servers, arrival rate @math{\lambda}, individual service rate @math{\mu} and offered load @math{A = \lambda / \mu} has all servers busy. This corresponds to the rejection probability of an @math{M/M/m/0} system with @math{m} servers and no queue. @tex @math{E_B(A, m)} is defined as: $$ E_B(A, m) = \displaystyle{{A^m \over m!} \left( \sum_{k=0}^m {A^k \over k!} \right) ^{-1}} $$ @end tex @strong{INPUTS} @table @code @item @var{A} Offered load, defined as @math{A = \lambda / \mu} where @math{\lambda} is the mean arrival rate and @math{\mu} the mean service rate of each individual server (real, @math{A > 0}). @item @var{m} Number of identical servers (integer, @math{m @geq{} 1}). Default @math{m = 1} @end table @strong{OUTPUTS} @table @code @item @var{B} The value @math{E_B(A, m)} @end table @var{A} or @var{m} can be vectors, and in this case, the results will be vectors as well. @strong{REFERENCES} @itemize @item G. Zeng, @cite{Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function}, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296 @end itemize @xseealso{erlangc,engset,qsmmm} @end deftypefn @c @c Erlang-c @c @node The Erlang-C Formula @section The Erlang-C Formula @anchor{doc-erlangc} @deftypefn {Function File} {@var{C} =} erlangc (@var{A}, @var{m}) @cindex Erlang-C formula Compute the steady-state probability of delay in the Erlang delay model. The Erlang-C formula @math{E_C(A, m)} gives the probability that an open queueing system with @math{m} identical servers, infinite wating space, arrival rate @math{\lambda}, individual service rate @math{\mu} and offered load @math{A = \lambda / \mu} has all the servers busy. This is the waiting probability in an @math{M/M/m/\infty} system with @math{m} servers and an infinite queue. @tex @math{E_C(A, m)} is defined as: $$ E_C(A, m) = \displaystyle{ {A^m \over m!} {1 \over 1-\rho} \left( \sum_{k=0}^{m-1} {A^k \over k!} + {A^m \over m!} {1 \over 1 - \rho} \right) ^{-1}} $$ where @math{\rho = A / m = \lambda / (m \mu)}. @end tex @strong{INPUTS} @table @code @item @var{A} Offered load. @math{A = \lambda / \mu} where @math{\lambda} is the mean arrival rate and @math{\mu} the mean service rate of each individual server (real, @math{0 < A < m}). @item @var{m} Number of identical servers (integer, @math{m @geq{} 1}). Default @math{m = 1} @end table @strong{OUTPUTS} @table @code @item @var{B} The value @math{E_C(A, m)} @end table @var{A} or @var{m} can be vectors, and in this case, the results will be vectors as well. @strong{REFERENCES} @itemize @item G. Zeng, @cite{Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function}, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296 @end itemize @xseealso{erlangb,engset,qsmmm} @end deftypefn @c @c Engset @c @node The Engset Formula @section The Engset Formula @anchor{doc-engset} @deftypefn {Function File} {@var{B} =} engset (@var{A}, @var{m}, @var{n}) @cindex Engset loss formula Evaluate the Engset loss formula. The Engset formula computes the blocking probability @math{P_b(A,m,n)} for a system with a finite population of @math{n} users, @math{m} identical servers, no queue, individual service rate @math{\mu}, individual arrival rate @math{\lambda} (i.e., the time until a user tries to request service is exponentially distributed with mean @math{1/\lambda}), and offered load @math{A=\lambda/\mu}. @tex @math{P_b(A, m, n)} is defined for @math{n > m} as: $$ P_b(A, m, n) = {{\displaystyle{A^m {n \choose m}}} \over {\displaystyle{\sum_{k=0}^m A^k {n \choose k}}}} $$ and is 0 if @math{n @leq{} m}. @end tex @strong{INPUTS} @table @code @item @var{A} Offered load, defined as @math{A = \lambda / \mu} where @math{\lambda} is the mean arrival rate and @math{\mu} the mean service rate of each individual server (real, @math{A > 0}). @item @var{m} Number of identical servers (integer, @math{m @geq{} 1}). Default @math{m = 1} @item @var{n} Number of requests (integer, @math{n @geq{} 1}). Default @math{n = 1} @end table @strong{OUTPUTS} @table @code @item @var{B} The value @math{P_b(A, m, n)} @end table @var{A}, @var{m} or @math{n} can be vectors, and in this case, the results will be vectors as well. @strong{REFERENCES} @itemize @item G. Zeng, @cite{Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function}, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296 @end itemize @xseealso{erlangb, erlangc} @end deftypefn @c @c M/M/inf @c @node The M/M/inf System @section The @math{M/M/}inf System The @math{M/M/\infty} system is a special case of @math{M/M/m} system with infinitely many identical servers (i.e., @math{m = \infty}). Each new request is always assigned to a new server, so that queueing never occurs. The @math{M/M/\infty} system is always stable. @anchor{doc-qsmminf} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qsmminf (@var{lambda}, @var{mu}) @deftypefnx {Function File} {@var{pk} =} qsmminf (@var{lambda}, @var{mu}, @var{k}) Compute utilization, response time, average number of requests and throughput for an infinite-server queue. The @math{M/M/\infty} system has an infinite number of identical servers. Such a system is always stable (i.e., the mean queue length is always finite) for any arrival and service rates. @cindex @math{M/M/}inf system @tex The steady-state probability @math{\pi_k} that there are @math{k} requests in the system, @math{k @geq{} 0}, can be computed as: $$ \pi_k = {1 \over k!} \left( \lambda \over \mu \right)^k e^{-\lambda / \mu} $$ @end tex @strong{INPUTS} @table @code @item @var{lambda} Arrival rate (@code{@var{lambda}>0}). @item @var{mu} Service rate (@code{@var{mu}>0}). @item @var{k} Number of requests in the system (@code{@var{k} @geq{} 0}). @end table @strong{OUTPUTS} @table @code @item @var{U} Traffic intensity (defined as @math{\lambda/\mu}). Note that this is different from the utilization, which in the case of @math{M/M/\infty} centers is always zero. @cindex traffic intensity @item @var{R} Service center response time. @item @var{Q} Average number of requests in the system (which is equal to the traffic intensity @math{\lambda/\mu}). @item @var{X} Throughput (which is always equal to @code{@var{X} = @var{lambda}}). @item @var{p0} Steady-state probability that there are no requests in the system @item @var{pk} Steady-state probability that there are @var{k} requests in the system (including the one being served). @end table If this function is called with less than three arguments, @var{lambda} and @var{mu} can be vectors of the same size. In this case, the results will be vectors as well. @strong{REFERENCES} @itemize @item G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998, Section 6.4 @end itemize @xseealso{qsmm1,qsmmm,qsmmmk} @end deftypefn @c @c M/M/1/k @c @node The M/M/1/K System @section The @math{M/M/1/K} System In a @math{M/M/1/K} finite capacity system there is a single server, and there can be at most @math{K} jobs at any time (including the job currently in service), @math{K > 1}. If a new request tries to join the system when there are already @math{K} other requests, the request is lost. The queue has @math{K-1} slots. The @math{M/M/1/K} system is always stable, regardless of the arrival and service rates. @anchor{doc-qsmm1k} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pK}] =} qsmm1k (@var{lambda}, @var{mu}, @var{K}) @deftypefnx {Function File} {@var{pn} =} qsmm1k (@var{lambda}, @var{mu}, @var{K}, @var{n}) @cindex @math{M/M/1/K} system Compute utilization, response time, average number of requests and throughput for a @math{M/M/1/K} finite capacity system. In a @math{M/M/1/K} queue there is a single server and a queue with finite capacity: the maximum number of requests in the system (including the request being served) is @math{K}, and the maximum queue length is therefore @math{K-1}. @tex The steady-state probability @math{\pi_n} that there are @math{n} jobs in the system, @math{0 @leq{} n @leq{} K}, is: $$ \pi_n = {(1-a)a^n \over 1-a^{K+1}} $$ where @math{a = \lambda/\mu}. @end tex @strong{INPUTS} @table @code @item @var{lambda} Arrival rate (@code{@var{lambda}>0}). @item @var{mu} Service rate (@code{@var{mu}>0}). @item @var{K} Maximum number of requests allowed in the system (@code{@var{K} @geq{} 1}). @item @var{n} Number of requests in the (@code{0 @leq{} @var{n} @leq{} K}). @end table @strong{OUTPUTS} @table @code @item @var{U} Service center utilization, which is defined as @code{@var{U} = 1-@var{p0}} @item @var{R} Service center response time @item @var{Q} Average number of requests in the system @item @var{X} Service center throughput @item @var{p0} Steady-state probability that there are no requests in the system @item @var{pK} Steady-state probability that there are @math{K} requests in the system (i.e., that the system is full) @item @var{pn} Steady-state probability that there are @math{n} requests in the system (including the one being served). @end table If this function is called with less than four arguments, @var{lambda}, @var{mu} and @var{K} can be vectors of the same size. In this case, the results will be vectors as well. @xseealso{qsmm1,qsmminf,qsmmm} @end deftypefn @c @c M/M/m/k @c @node The M/M/m/K System @section The @math{M/M/m/K} System The @math{M/M/m/K} finite capacity system is similar to the @math{M/M/1/k} system except that the number of servers is @math{m}, where @math{1 \leq m \leq K}. The queue has @math{K-m} slots. The @math{M/M/m/K} system is always stable. @anchor{doc-qsmmmk} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pK}] =} qsmmmk (@var{lambda}, @var{mu}, @var{m}, @var{K}) @deftypefnx {Function File} {@var{pn} =} qsmmmk (@var{lambda}, @var{mu}, @var{m}, @var{K}, @var{n}) @cindex @math{M/M/m/K} system Compute utilization, response time, average number of requests and throughput for a @math{M/M/m/K} finite capacity system. In a @math{M/M/m/K} system there are @math{m \geq 1} identical service centers sharing a fixed-capacity queue. At any time, at most @math{K @geq{} m} requests can be in the system, including those being served. The maximum queue length is @math{K-m}. This function generates and solves the underlying CTMC. @tex The steady-state probability @math{\pi_n} that there are @math{n} jobs in the system, @math{0 @leq{} n @leq{} K}, is: $$ \pi_n = \cases{ \displaystyle{{\rho^n \over n!} \pi_0} & if $0 \leq n \leq m$;\cr\cr \displaystyle{{\rho^m \over m!} \left( \rho \over m \right)^{n-m} \pi_0} & if $m < n \leq K$\cr} $$ where @math{\rho = \lambda/\mu} is the offered load. The probability @math{\pi_0} that the system is empty can be computed by considering that all probabilities must sum to one: @math{\sum_{k=0}^K \pi_k = 1}, that gives: $$ \pi_0 = \left[ \sum_{k=0}^m {\rho^k \over k!} + {\rho^m \over m!} \sum_{k=m+1}^K \left( {\rho \over m}\right)^{k-m} \right]^{-1} $$ @end tex @strong{INPUTS} @table @code @item @var{lambda} Arrival rate (@code{@var{lambda}>0}) @item @var{mu} Service rate (@code{@var{mu}>0}) @item @var{m} Number of servers (@code{@var{m} @geq{} 1}) @item @var{K} Maximum number of requests allowed in the system, including those being served (@code{@var{K} @geq{} @var{m}}) @item @var{n} Number of requests in the (@code{0 @leq{} @var{n} @leq{} K}). @end table @strong{OUTPUTS} @table @code @item @var{U} Service center utilization @item @var{R} Service center response time @item @var{Q} Average number of requests in the system @item @var{X} Service center throughput @item @var{p0} Steady-state probability that there are no requests in the system. @item @var{pK} Steady-state probability that there are @var{K} requests in the system (i.e., probability that the system is full). @item @var{pn} Steady-state probability that there are @var{n} requests in the system (including those being served). @end table If this function is called with less than five arguments, @var{lambda}, @var{mu}, @var{m} and @var{K} can be either scalars, or vectors of the same size. In this case, the results will be vectors as well. @strong{REFERENCES} @itemize @item G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998, Section 6.6 @end itemize @xseealso{qsmm1,qsmminf,qsmmm} @end deftypefn @c @c Asymmetric M/M/m @c @node The Asymmetric M/M/m System @section The Asymmetric @math{M/M/m} System The Asymmetric @math{M/M/m} system contains @math{m} servers connected to a single queue. Differently from the @math{M/M/m} system, in the asymmetric @math{M/M/m} each server may have a different service time. @anchor{doc-qsammm} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qsammm (@var{lambda}, @var{mu}) @cindex asymmetric @math{M/M/m} system Compute @emph{approximate} utilization, response time, average number of requests in service and throughput for an asymmetric @math{M/M/m} queue. In this type of system there are @math{m} different servers connected to a single queue. Each server has its own (possibly different) service rate. If there is more than one server available, requests are routed to a randomly-chosen one. @strong{INPUTS} @table @code @item @var{lambda} Arrival rate (@code{@var{lambda}>0}) @item @var{mu} @code{@var{mu}(i)} is the service rate of server @math{i}, @math{1 @leq{} i @leq{} m}. The system must be ergodic (@code{@var{lambda} < sum(@var{mu})}). @end table @strong{OUTPUTS} @table @code @item @var{U} Approximate service center utilization, @math{U = \lambda / ( \sum_{i=1}^m \mu_i )}. @item @var{R} Approximate service center response time @item @var{Q} Approximate number of requests in the system @item @var{X} Approximate system throughput. If the system is ergodic, @code{@var{X} = @var{lambda}} @end table @strong{REFERENCES} @itemize @item G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998 @end itemize @xseealso{qsmmm} @end deftypefn @c @c @c @node The M/G/1 System @section The @math{M/G/1} System @anchor{doc-qsmg1} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qsmg1 (@var{lambda}, @var{xavg}, @var{x2nd}) @cindex @math{M/G/1} system Compute utilization, response time, average number of requests and throughput for a @math{M/G/1} system. The service time distribution is described by its mean @var{xavg}, and by its second moment @var{x2nd}. The computations are based on results from L. Kleinrock, @cite{Queuing Systems}, Wiley, Vol 2, and Pollaczek-Khinchine formula. @strong{INPUTS} @table @code @item @var{lambda} Arrival rate @item @var{xavg} Average service time @item @var{x2nd} Second moment of service time distribution @end table @strong{OUTPUTS} @table @code @item @var{U} Service center utilization @item @var{R} Service center response time @item @var{Q} Average number of requests in the system @item @var{X} Service center throughput @item @var{p0} Probability that there is not any request at system @end table @var{lambda}, @var{xavg}, @var{t2nd} can be vectors of the same size. In this case, the results will be vectors as well. @xseealso{qsmh1} @end deftypefn @c @c @c @node The M/Hm/1 System @section The @math{M/H_m/1} System @anchor{doc-qsmh1} @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qsmh1 (@var{lambda}, @var{mu}, @var{alpha}) @cindex @math{M/H_m/1} system Compute utilization, response time, average number of requests and throughput for a @math{M/H_m/1} system. In this system, the customer service times have hyper-exponential distribution: @tex $$ B(x) = \sum_{j=1}^m \alpha_j(1-e^{-\mu_j x}),\quad x>0 $$ @end tex @ifnottex @example @group ___ m \ B(x) = > alpha(j) * (1-exp(-mu(j)*x)) x>0 /__ j=1 @end group @end example @end ifnottex where @math{\alpha_j} is the probability that the request is served at phase @math{j}, in which case the average service rate is @math{\mu_j}. After completing service at phase @math{j}, for some @math{j}, the request exits the system. @strong{INPUTS} @table @code @item @var{lambda} Arrival rate @item @var{mu} @code{@var{mu}(j)} is the phase @math{j} service rate. The total number of phases @math{m} is @code{length(@var{mu})}. @item @var{alpha} @code{@var{alpha}(j)} is the probability that a request is served at phase @math{j}. @var{alpha} must have the same size as @var{mu}. @end table @strong{OUTPUTS} @table @code @item @var{U} Service center utilization @item @var{R} Service center response time @item @var{Q} Average number of requests in the system @item @var{X} Service center throughput @end table @end deftypefn queueing/doc/conf.texi0000664000175000017500000000005714620415614014654 0ustar morenomoreno@set VERSION 1.2.8 @set VERSIONDATE 2024-05-13 queueing/doc/qn_open_single.png0000664000175000017500000000743514620415615016552 0ustar morenomorenoPNG  IHDR4yPLTEٟIDATxMoH`7AhgāAW;WA)opjs#WHqDq8JŅ]*\ kOQM>]`i v'y6g|61Lif+ڔdݮ̫vt c24?.`^-`V &)30 9* !Gi{ٴO#fA~ɯSG0"LnoӚ{R֛?$ΗȻf'yG6oˤ yhB] $CvUyȚ̮|^d&2=7knE jXޕ* lC5r:KknnIM YURsT#9pl7|sB.* ;y,")MNf**U_YxS5\%3k9/M:h󣜗{6KfSә&4J[k1/0MvmR,cYsbyz}_^Wly`~guuȯ9>C}MRcwr_sL{E\ K_Y&̆y&]1DŽf^~w0gf ,Ib V]BwPa$07&`9cZ0f:4a&K??q!&dwnq039?/I2Į^Gv(9&\1-opSpsVW4eKfm3˛sC6˛s?1OczǨ9~Dac0EF͑fW[X WMkz!6?H#9ei~Ro̱5=;iLSobf@Mk.͑6ktq3l0tZfP{]'ph&rday~ZfP;ms1ړy< h4b3}O:T c}5 ;_f9SMuҋNIOV׮IF 7<.zkf|zy}T_YP*Q胪֧&53RxMڦȤY"ϭyCdkvcO7)DftA/kj'I&nN3:]zdo9Y5ȼI}`Ű4V̇|N" Aj! 5֊N!S|Ljf?uɐ(ԇo׸t.fWT#R5"$旚柝п9Wlza~fC:t[N4K}roj/vsW37G<,ޤ7kn+6Xi;MʬU*fsSGM{]Ll1a#z;{Mv;۔k!nSƞ9V6{ g_9%)bOvnj~}&=U#0P-jY41bf&QǞ3sa:E'_C)*i{L{ tᢦ>ߛx)cO崞b`|;F>c~ N{J=ǞR}pMGLgScٿ3yOc˼7y[C_3yKCfa6Qub&ZpS٘ip"9$PJr2q̜ۧ/׳ʱ$ILگVXҘlD9w,hT{SȬ8+f\9p[}X N$#rbIh0{onBLdcK:s8?I![O΄Hٛ÷nM^xƔM>̺ǾLܫ\oaX,.\7ѱxcOÖC.)rYM5&_LըDe!)ݦ:]qqg9Y -Gwj|E3eg[%3sa38$ʻfnjرӜL0+\6v9+5<n.Nq!yM5~fMɞj5~XmFL2ic58jfB換Ѵfo=\z!}gd }6LE0oӚrf1[$Ԩyz҉Ğ6SQd4cOOʌV1jT/DbO-gZ"mS L+Tӊ=oڱM$T:ČLK#TcD> stream xWˎ7 WXE/q g{!!olӁ $R7Iiz׳aȪYo\b>=-ɖwץdOhsfU$o]1%)௳ё[y\P!_ &P* A&hXHhpTq^>/KhZ4kʂ\/5S:`eS-CKx^|a[ϿGα '%e ܁ aȻJpBV+EnI ZP jHɫA5B*@a 1y R$]]*AǵKNwd$-+:mIW}5Dt෎MdB(dh|^B,+H6EZ;rwY Rm)9ԧHsU']Ab1|sg !IWppqd >Iç 4(L$-"uhUPc|KBkc| 2d FBvSli-X B5;_:7gYP ˇ?KHlN5N22CucEϐ)_NLywcv"EOp̘PB~fځg)ء_<>IFe齃mvs9 zAz)>-{2hў叧'3K " nky?<9UqniKWendstream endobj 6 0 obj 1255 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 10 0 obj <> endobj 11 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> endobj 12 0 obj <>stream xUkTS>!䜣ԒFфֶj-+T[Ղ@! BxE ! ĶZUlZ޵u]]w͟3{of`.p DEi+W)/ޅHR0a \WzB3Pse0v5M6 J 3^;XX= "a~qX(]RޑLI^Zð{ i¨|Mo {{{6bQX4bA^;a`{`k1Oy,aQXvuŒdN&Ne  ĿI| MKGK휏Lꆬƕв**KJ`b;$kk26 &*⣛ ̇ 啱G`徴 Q6Zŷ ~ԺɹkTppD=qه8 #}M7$Iw9\@|t0u*H@LTZ8 儱8n䲟@Zu`W|&IǨ9 Cf.aTJXR\+-S@P ~p+@.$J<&Ao^◶^(G@WIqfZzhȵ'ݩHEj~{PnE"ԵFUa>$٩O=p#\WRS mu4HWFXufu`9p-ɞQ睓7Fx<_u"CZ8C.=νw1h Qg ~GS_WU #YNCe٧1Z/ `l[kƊ.k_$p}[gѩVE]ޓR[vX UGI2Q4nKY}VZNSwlN+' K n`JQ-uuymq}qm wEE9O\<^J8~ob1 ތjI߹Bxk)@جUzx=3'r|:tZ6jAb9HGjPzu-ږ-mAiE bXoVOZkҘ*1骫j&P!|D WD^]WRasJNbM˸`Zק8SeObhqn1PdcLO~ ?@[J+R2CS.ڧ/ͱmQ`oMh]ʥBeAY⁏50\5oZO]e\e?0ᖥ9teAE^~%3@= G,icD޽o!wݏ^Jc]O}V@I!qu篰p; dP'iwj~}3 /}C{Hɥ`O"vHEִ*v:vd+!f ;Os zrӴUFhK)th YZq턾;YV|ZvȄO7Z>k ݡ27 #*,.?uq-1`^ ;@h8MRh,%qenQ }\۰Cpɀn͈($x`Gnyoo~!:Nr0ȕuܑ_7y|]nݱMZG|s'pΓ}nw9AjpKG,3wef9+Jiǒ=-dLM%M$t]]R乙|XQ(Z9 SC2Y"^џlYmN̿snT,l"Rpr+msGf9HC k5sLV`2p+ YVxH#RNN9[tpϐ9AߠU)20T7>INq?DKPػo<[{mVXe]B6Zw6ݩq{d endstream endobj 13 0 obj <>stream 2024-05-13T15:54:31+02:00 2024-05-13T15:54:31+02:00 fig2dev Version 3.2.7a qn_web_model.fig endstream endobj 2 0 obj <>endobj xref 0 14 0000000000 65535 f 0000001783 00000 n 0000006609 00000 n 0000001724 00000 n 0000001573 00000 n 0000000228 00000 n 0000001553 00000 n 0000001848 00000 n 0000001949 00000 n 0000002322 00000 n 0000001889 00000 n 0000001919 00000 n 0000002619 00000 n 0000005176 00000 n trailer << /Size 14 /Root 1 0 R /Info 2 0 R /ID [<7BCA98CB27FE1C75BC6707DB35E02C2A><7BCA98CB27FE1C75BC6707DB35E02C2A>] >> startxref 6790 %%EOF queueing/doc/power.png0000664000175000017500000003364414620415625014710 0ustar morenomorenoPNG  IHDRF?bKGD̿ pHYsddtIME 6P 6IDATxqLYg5%fqlj&ܹXQpKҍ4+i c@2[Ᏼ/h+&Y: #O$`iԸAO mE$11=QLbˮST:U;s~s; &&=+`R22р]BriY^[w.$ͯr;Yro-U-a/]0"EQ8)G"(L䁢̔x:(XS iba3@I"on!!@q(١@Xç>Nal15d$0; 0d 9 ,c@?ͅAI`a:RvBrd~uyvC\Y͋ 6 oJQ&7ٜ e QlYkN/MrB=(\1$bhQ/zBmFE +AQllLo v[Dff`FQ@Q"lcEy(0<E-oVm(3{(3i%WF!lwBvq D&L`:U F1G?V pfXD\o$:+eFjdY؀o_!IboNN$I('pȤJh,0Y 0edL422SF&`DLh)# 0edL422SF&`#;wr?mmWvg>3hh~d6;@ә3u.z΋LMN)d2tߜ)$R?2^]9xi8ſ9pAovO?;Uɼݦ3Mz Q/2~t4qz.I|ʬozݩwh/d\8uΈ-ǩs*Bû*ՃVp59Y: h:sT2Z} p母+"i=* կ>[9sigO۰VԴv;gאzw~,fZf԰rSՐTΟq8H5+YmMːVe7|Ndq~wB쭴6-֍T2ʼa8Ho4xk]E"hO hk:0~rv~Z~I:SkRbiAUk u ՔV/w]>jWYu Ք5jnjyWhH= ՔjfjݕxwjKF j)[5 7䓧y;puҜZw /Gy2z w4BA]2C~lߏ}V)Q-ȷwДg~P jƹY]Fk+2.sIkx\*jFӏkVGFс6-Gd_uӬհj@FyHǝFY]\Fڴo^f&omQ~}=ɨΚ5f23F; u֬q&uTFo\G Vok_F [V::ZFa[:p7 OtUz#εi;_Lc^W5E<}LKNIp?8d/z+zssC& u#]MMa;è[w7$k`# UPE{%N}(ĄorW=VpʒS@_Eveaa2...șb0-$'tkzB؆:6:%^\}QEP ?|n/0WT_Gret 8e ɞALZ`$P[~v.vTFn]D ꢚA5Íbǡp\is9l6heF_]n m޵8d0UF8$p5N;c֌&#  جņri' `,/ۈ2*#v28ժ.n(#svQy^)̀22gM)vD9;hN]W>Ɠn ]ΝӬOFv8>#"@OFV JF}%:|^9.ɼ?9$ޞ21)dD{$ApBrela pIp\BR F1rSRQ1zC&&̍=qD,]RsUyCd?moAqoD &% /q?:mʩ뫋ͩ_i0bFK.)RU֠$-4T䇠6iN;9ut\XF]VNQǫc-hzWʤ7:O<HeRV? 7jpݖH NX;qqllK8WzWX,dK;Ammi29_^g]KٴU8sTc)erJˮ}zh{ޫz dWsluΖ\Z޾ h1zCG dGaKXmV{c ,jF?\KZYF͝-PyI([NՍ܁5f^ݼcqԛ\~LD_FGqVY"_CA%: Uuju*ߟ؋ &JQ7SF/2շFmS|7Ǻb~i7F:bn&4 icll=pNtXH70 E5ZsEcghcaGvrpVwUFK] 3p>u|>8@X)KNY\QXO۴8 2󕓑TN>*"Izz h$Ȩ7ɉ8p^8v6ͷrTn;* ]}=xS'޽.gOWkX~4m11RY,{R]zVLJ·\=޻;J]$>}nEO]<l4;?jͲzꪏJoQY#8;k#5^69R_OK#[OOEV4^#ŲƎL0\gWx*&)RɬmJV>٢#uUi*PJ&orFFώL`EEA}^KALNmXu*>Ot%~B/ Эjvg co[-CU;[%1]#!0X|TL26=dd|">R"ZiCB"ˠ8FoJƴFGp讴,?uJZ֨$ғ?9'mSFUz#l9e)g61RHģ;2eT4[q6n 61uP1eT,[mHk4V7m=/D6KT:|1et Vv3JaM䮙2*;%|7aC"{?:Vb~|}wl< )#Mav4B k&M*OCGMS3y hWm,e71eT,Y&vW%+T4k_FoT,nڡX*Y5QQp6kX|qI٦a"È"ڌi6jŐ2PX`YVʹFGR`5clp[3QdIɜuӎLAv$8M-=zCg>X܇dqfͧwfZH(8;yV>ݻEQ1U~Kzᣧӄ8ڬ+^/^(<= ޸]oI-/Fxyi0 ˻$B===WM= t2]>@.F[s?mOtQ+v}.gc!uH~q*tK_I*h=bӇq.wWqqF} @8}CAXZ:/6Jkɕ;❷F\J(;h-uޮ` X{Sh|6+ɕ5i'o_*2q}pO:;])޶/ϗWd(pų Q˗'Wֶ*&Yl|N7-Oϖ/4SIHU6YԢ]'(Ͳv\Law/voXf<31'ӧS>7Ǣ4"'(lulTaZ-˸HeScwiҎ6fLkUcԙ>4`'Fױh9}׺LmD#Xuސθ,/fom>N{cf`0N4ip/vFf푊R5 2 |ؚ=MڝRd4);iKeOc7}pZVHn>ܠ,Z8 )qWO_5 dSn) G*MB.Lcql<[%mxLzjE-Qds+SFuU{GQayXDoǤH7_5cM= t2]|3&c:[ra.v&&rHT>護 h1VR5z\I8}CA<"bbwcg @X)Kҕ+Mŋ/ U~S&o'Y /^X}7 h$4 9]sT;˫ 9P$-4T䇠 PN2r:${B Ȣs$#IeZyb"r:< [zG&GbQpH($ܰN5ǧo`:+ L qE ^$Nkh#˜ah@_5SF&`DLh)# 0edL422SF&`DLh)# 0edL422SF&`DLh)# 0edL]1 74tճQ+U+MXԲ$$xfffh=ƫ􂴤net/vBq^?C޻{7 @39sG.$!.GVMF[y%4?>n"ƣ n),RYRSw#~:ȡA>?u#46xmuf| rmzzٿ98 ?`3+CM(G? &B4i nZ nKRQa& ?{M#lC tI%mot d?OF/lϢC`5LoNBp 0 ?:mf7GDlwYn%qwg#InmFl;(鄤xe7^Ct.lwO`X裨*t1KԇF?\e7&Ixs(`,nˁoIW2.,:m.`shh&st3?Bp .F:?z\R+ylKMʨ<\o{^o8|k(0a֖1Y;\"w@;_sG=ngdw(H$0LF8rPZ&a7x,x;TL8$?Ey!rvg3~ ?8so>N d~7;K<v\аr feWQ 6QEQ3, K3)SQ"EQ\rf晢(Jī(ʳE٘y(33zRzF'.J`uQlA.KEQJSD+`yN63\^+ʳr,#cצ"}$.WC`. rl.`>x7fy5 }5Ffhڏ&:bDLh)# 0edL422SF&`DLh@iklK,K{v7JU<*9FJ*Tr-#594 0ZŊBX+WrFXѥR>$BNIB  {~9ZF21)dD{$Ap)Dg0ѝe`ԙ=ƄorW=Vpʒw Aj)zU*BT?2.>ZFF`Zb! 2MHN{g xDʳ_?xq25("I@0  gW߄^-S&9A=!dу=( Ȉ1?;N!OO`bNduw*;XbL+ Hz4"'hv%: ZN029Y 0edL4hLt krktZUE<:y/B'K+Y=w4FB'$jTgxZ( ]<c{eu9E]vu/?f*o%|5ネ^P2?p=KV.(opO3㷥 E@+$'hѮ9E mI+0RƗodfhDLh)# 0edL4&h"E\95IM5{l{Ӏ +ѷo$SlȉkM9&9HFs_:hIQDwg&ŜSkxa s9;]ވ;T9t[S#N<`wIlX]B애/ΐt[E G7 3 =}t{P[Mwt YP~+>J7BuѨuFĮ?oz+}DAsfE?-J= ']v!2ДͫismJD9 R+O=q/tщFΑ^ AkZh xByO/XO9 sB!<QGjOީ"蛺Wg $Zٚ]#fZ$[u=!b ;=(Ysc{E N:P0-8I9QI_6ffffL4μSV^%tEXtdate:create2024-05-13T15:54:29+02:00EӁ%tEXtdate:modify2024-05-13T15:54:29+02:004k=tEXtps:HiResBoundingBox419x314+0+0mztEXtps:LevelAdobe-3.0 /hIENDB`queueing/doc/qn_open_single.fig0000664000175000017500000000341414620404470016521 0ustar morenomoreno#FIG 3.2 Produced by xfig version 3.2.5b Landscape Center Metric A4 100.00 Single -2 1200 2 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6930 5580 270 270 6930 5580 6930 5310 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6930 4500 270 270 6930 4500 6930 4230 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5299 5029 270 270 5299 5029 5299 4759 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 4 0 0 1.00 60.00 120.00 5580 5040 5850 5040 6030 4500 6300 4500 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3 0 0 1.00 60.00 120.00 5850 5040 6030 5580 6300 5580 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 7200 5580 7470 5580 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6300 5310 6660 5310 6660 5850 6300 5850 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 6300 4230 6660 4230 6660 4770 6300 4770 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 7200 4500 7470 4500 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 4500 5040 5040 5040 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 4 0 0 1.00 60.00 120.00 7470 5580 7470 3960 4860 3960 4860 5040 2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 5760 5040 5760 6210 4 0 0 50 -1 0 12 0.0000 4 135 255 5445 5940 0.2\001 4 0 0 50 -1 0 12 0.0000 4 135 255 5940 5760 0.5\001 4 0 0 50 -1 0 12 0.0000 4 135 255 5940 4455 0.3\001 4 0 0 50 -1 32 12 0.0000 4 150 105 4365 5130 l\001 4 0 0 50 -1 0 12 0.0000 4 135 375 5130 4725 CPU\001 4 0 0 50 -1 0 12 0.0000 4 135 480 6705 4185 Disk1\001 4 0 0 50 -1 0 12 0.0000 4 135 480 6705 5265 Disk2\001 4 0 0 50 -1 0 12 0.0000 4 135 105 5265 5085 1\001 4 0 0 50 -1 0 12 0.0000 4 135 105 6885 4545 2\001 4 0 0 50 -1 0 12 0.0000 4 135 105 6885 5625 3\001 4 0 0 50 -1 0 12 0.0000 4 135 450 6705 6030 FCFS\001 4 0 0 50 -1 0 12 0.0000 4 135 450 6705 4950 FCFS\001 4 0 0 50 -1 0 12 0.0000 4 135 210 5220 5490 PS\001 queueing/doc/qn_closed_multi_apl.fig0000664000175000017500000000233014620404470017532 0ustar morenomoreno#FIG 3.2 Produced by xfig version 3.2.5b Landscape Center Metric A4 100.00 Single -2 1200 2 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 6570 4590 180 180 6570 4590 6750 4590 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5670 5220 180 180 5670 5220 5850 5220 1 3 0 1 0 7 50 -1 -1 0.000 1 0.0000 5680 4053 180 180 5680 4053 5860 4053 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 4 0 0 1.00 60.00 120.00 5850 4050 6120 4050 6120 4500 6390 4500 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 4 0 0 1.00 60.00 120.00 5850 5220 6120 5220 6120 4680 6390 4680 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 6 0 0 1.00 60.00 120.00 6750 4500 7020 4500 7020 3510 5130 3510 5130 4050 5490 4050 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 6 0 0 1.00 60.00 120.00 6750 4680 7020 4680 7020 5760 5130 5760 5130 5220 5490 5220 4 0 0 50 -1 -1 10 0.0000 4 105 300 5535 3825 APL\001 4 0 0 50 -1 -1 10 0.0000 4 105 285 5535 4995 IMS\001 4 0 0 50 -1 -1 10 0.0000 4 105 270 6390 4365 SYS\001 4 0 0 50 -1 0 10 0.0000 4 105 75 5625 4095 1\001 4 0 0 50 -1 0 10 0.0000 4 105 75 5625 5265 2\001 4 0 0 50 -1 0 10 0.0000 4 105 75 6525 4635 3\001 4 0 0 50 -1 0 10 0.0000 4 105 165 6480 4950 PS\001 4 0 0 50 -1 0 10 0.0000 4 105 135 5625 4410 IS\001 4 0 0 50 -1 0 10 0.0000 4 105 135 5625 5580 IS\001 queueing/doc/power.pdf0000664000175000017500000005505514620415627014677 0ustar morenomoreno%PDF-1.5 %쏢 %%Invocation: gs -q -dSAFER -dNOPAUSE -dBATCH -dCompatibilityLevel=1.5 -sDEVICE=pdfwrite -sOutputFile=? -dPDFSETTINGS#/prepress -dMaxSubsetPct=100 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoRotatePages#/None - 5 0 obj <> stream xXI5&4}_ !hU9"!'q)!AQ&҄*vg& I*"'1B;j3pPN9?x~3џdJxA:=^v7O{?wII內oylux. ]q ^E`R,6= `6iz<[,x4%|6iz<[4<vgmóix6iD;Txh[2/z<[4<6DklCS40k9.`fYٿ!0T/抒ƗzEZ NZ&ꎾTKmSΗj6|:9}AN(ṸӇY{04CNnpgxsF߃2 re8_Tq<~$ 4N4pi|CZъ ڨF4$wH'>]{DCUrhC)D!g3dCy?WW*է3Z*6O\?v w"}v뗲ʸ]8{+^!waEն<eu߱$q,k^ͯ`ZtWW --=-a=%rnUvYl>XnX(GP}-RugvZLtTZ@ܧ`CvS﹑W.c=N#w*E_ ] z$<(%17}M3;g7|*XS'ʪJs.cUCA֏h +\$$;Pc6 `&41ļ)r}i +$&i~!`1'H\q )Ӛ&?@eɺ"(@"]c0nQsE;껐% gSMw0{Ǟz#]T'M֤X=LPXq 1=ה3 &V+Qq#c5$~=9=kK \ʍ'=s_lHÀܰJCj6Ŗ,֥#, 4nMKS3E$lK;Vyɪ}jD_B){^x;^> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <>endobj 69 0 obj <> endobj 70 0 obj <> endobj 33 0 obj <>stream x3V0P0Q5T1S , 1s - Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAmq3,m-RM$yRٷo(\SlbbP`rT ?Z endstream endobj 28 0 obj <>stream x33W0P0T5T05U0VH1230 !U`jbT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-,$uC[ u0_0RK_c_Vwm7L;;lNصki.xĠNs endstream endobj 23 0 obj <>stream x323U0P0Uе0P042S , 1s  @)Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAm|B = endstream endobj 18 0 obj <>stream x353V0P0T55Q05T0RH1230 !U`j`T052 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-\ !~RI/hro2}]?O"\zݥ]w+:w2lHV.WO@.cI endstream endobj 13 0 obj <>stream x353S0P0T57T052S , 1s L @Y@I'O.}O_T.pJ.}2.}g  45KM V8qy(-&,Ͽ3!b~~L \ \eS endstream endobj 64 0 obj <>stream x33P0P0V53W05W0RH1230T ɹ\ &`A3K  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1P X< Y9_Q?pýٗ#VG3E-M 3&3)2g]48o.'R_oߥ>\ͽPiG׶nms8թW endstream endobj 59 0 obj <>stream x33V0P0Q53S01S , 1s , b ff@ Y@9'O.}O_T.pK.}*.}gC.}h\nn@n.P9?47XΎEAm B .8m endstream endobj 54 0 obj <>stream x33V0P0U53T03Q02VH1230!U`jiT02L,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(\!]~W|/?SC_]=fޥ_7U:Ї6q1(0qz*r[[` endstream endobj 49 0 obj <>stream x333Q0P0U53T03P5TH1230!U`jj*2@.'BIQi*~8P%PS!K4X.}7}gg7 7Fhs~Nin^1Pq߿\Q=>ʾ[V]oS8dH endstream endobj 44 0 obj <>stream x313T0P0S53T01R5TH123!U`lfT`,ɥPRTʥTɥT`ȥ 45KM ƥSW bg颠s 'f?|cP`rTB@ endstream endobj 39 0 obj <>stream x3P0P53T56U )\z@a 1s ̌ F`M ,ɥPRTʥT˥Tȥ`ȥ 47KM V8qy(';"Cl V_1(0qz*roE, endstream endobj 34 0 obj <>stream x353V0P5T5P05S @, 1s L  = :yr{*rr{q;8+rDwwvvrllfp;qy(tH˽z]o~ݶ;6wݭmӾztoҍ[U}*uϯf__e{վ[7R~/`aprT)Q@ endstream endobj 29 0 obj <>stream x3T0P0Q5P05R0VH1230 !U`baT032L,ɥPRTʥTɥTƥ\r;;66 @ܼb;;.O$8*'sl_~ L\ \JZ endstream endobj 24 0 obj <>stream x33W0P0T5T05W0VH1230 !U`jfT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-'z`CskZ:Hh"/Kw7&inzy9 19oogzc0ݴcffVF.WO@.kS endstream endobj 19 0 obj <>stream x5LP յp&K{ a"Ƙ`M4|4j(z=I"hrkt+3Td֊HlF=u'./J\quΔ~ͫDS,qZ.D " endstream endobj 14 0 obj <>stream x353S0P0V57T05R0RH1230 !U`biT072@,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(- { ˗/_ Ppo{}_U];ևKo}Hhp}bDxdŘHxDX\=Z< endstream endobj 65 0 obj <>stream x31V0B]sc#C.=C(U7 *@<=}JJSÁ= ]fr;;66 @ܼb;;.OEl3?~{pG_~˽u{e߽wovS! HQ\ endstream endobj 60 0 obj <>stream x3гP0B] s#C.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O-[؄[5G ̱e[]_ Mة<5mOLOi'zw=Io݈fbP`rTH endstream endobj 55 0 obj <>stream x33W0P0Uе0T02V5TH1230!U`haT@=@ etU()*M*w pV0w˥{mw)+jtQPxĠ>2 endstream endobj 50 0 obj <>stream x333V0P0R53T0P0TH1230 !U`jfT032@,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-sC@F< UCK{%KqMoׯwض=ӎo;:";;1Mm#B nL! endstream endobj 45 0 obj <>stream x333R0P0V53T03P0RH1230 !U`jnT032@,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-\'5OCY:Zef?kF=MM?o?C >stream x373Q0P0Wе0T07T5TH1230!U`fbT02́,ɥPRTʥTɥTƥ`ȥ 45KM ƥSW bg颠qhd)'G?KCׯ,=z= \ \8fN endstream endobj 35 0 obj <>stream x3P0Pе0R53W0TеTH1230 !U`alT00kf`i'O.}O_T.pZ.}B.}gC.}h\nn@n.P9?47ΎEAm5Ȑϭz2Ƿg1ݰmáM'R\=I endstream endobj 30 0 obj <>stream x36гP0B]sc#K#C.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O=ٯ?/zn,^.WO@.nEQ endstream endobj 25 0 obj <>stream x353R0P0T5T05P0VH1230 !U`biT032@X,ɥPRTʥTɥTƥ\r;;66 @ܼb;;.O }\*M-r͇j_"濗jk-:ӖUPG⠎† L9$_td^OS3vg̹]vk \ \CMB endstream endobj 20 0 obj <>stream x353S0P0V57T052S , 1s L @1Y@I'O.}O_T.pJ.}2.}g  45KM V8qy(->stream x353S0P0R57T052R @c$r*̍ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j qz0?E}WV}ۥEnHeo"בde/_r?Pis'H1p.WO@.Z endstream endobj 9 0 obj <>stream x353S0P0R57T052R @c$r*X̍ 570K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j 8s(|g ?_??|w?m0}6-_wun٥7u^l&ƣ;[~ endstream endobj 66 0 obj <>stream x323R0P0T53P02Q0RH1230 !U`dlT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-u_O"!, \ \=>@X endstream endobj 61 0 obj <>stream x313V0P0T5P01T0RH1230 !U`b`T01 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-xbPa^. ̗5_~k)'(9J&!p,3ޖ]mms&mmbP`rTDX endstream endobj 56 0 obj <>stream x3V0P0S53T4R5TH1230!U`afT`,ɥPRTʥTɥT`ȥ 45KM ƥSW bg颠s)[e} )%;@(M0F6 .WO@.9V endstream endobj 51 0 obj <>stream x363R0B]sSc#C.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O ;p\>stream x333T0P0R53T02R @@c$r*̌ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j .3 I~-{˗/l'P\uѵ "y xi2e]S'@ϡq;bL}nƭiCB L endstream endobj 41 0 obj <>stream x333U0P0V53T03Q0RH1230 !U`fhT032@X,tU()*M*w pVr\r;;66 @ܼb;;.Oyn>jHQENv]_8}_K}߭nozm۲G֭];t07&֯  \ \ΡQ endstream endobj 36 0 obj <>stream x3P0P53T55S0Q5QH1230 !U`fjT052kf`i'O.}O_T.pZ.}B.}gC.}h\nn@n.P9?47ΎEAmcL[/Ta~5 &T7Kݿ;Vm=bn]vk̜\=>stream x323Q0P0Uе0P042S , 1s  @)Y@I'O.}O_T.pJ.}2.}g %hj,`cﭠ q)+jtQP8@VCB F= endstream endobj 26 0 obj <>stream x333T0P04P5P0S @@c$r*YA C.'BIQi*~8P)PS!K4X.}7}gg7 7F[A(㜟SW bg颠?0e{:AS! _> endstream endobj 21 0 obj <>stream x353S0P0R57T052R @c$r*̍ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j H4 T_"/_a↢ck>Iz"uz#nvv6nk3 \ \kU endstream endobj 16 0 obj <>stream x353S0PP57T062S , 1s  @Y@I'O.}O_T.pJ.}2.}g  45KM V8qy(-pέbDŽ_߿.WO@.i?| endstream endobj 11 0 obj <>stream x32U0P0W54P02S , 1s  @9Y@I'O.}O_T.pJ.}2.}gC.}h\. 1!B #F endstream endobj 67 0 obj <>stream x31׳T0P0T5P01S0RH1230 !U`bjT@-@ dtU()*M*w pV0w˥{+esJsZ<]Y`"7Of/µKmLmv@z6onnbk3+#B 1oEB endstream endobj 62 0 obj <>stream x35P0P0W53Q062S @, 1s L f 9Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAmh9&B 9b endstream endobj 57 0 obj <>stream x333Q0B]3SK]CC.=C(U7 @=`)'O.}O_T.p4t pV0w˥{w)+*tQP'evڭۣחۦ{ݜ׮ͭU`t/&׿4jWtCB qNX endstream endobj 52 0 obj <>stream x36гP0P0Uе0T02V5TH1230!U`haT@=@ etU()*M*w pV0w˥{mw)+jtQP[/l`hrT{= endstream endobj 47 0 obj <>stream x363W0B] CcS]CC.=C(U7 *X@<=}JJSÁ= ]fr;;66@sJsZ<]-9 ->|AS! \J' endstream endobj 42 0 obj <>stream x0ճT0B]3 S]CC.=C(U7 *Z@<=}JJSÁ= ]fr;;66@sJsZ<]ι"Xo_v_+_o_no_߯WQ׵VzǠ4Vb endstream endobj 37 0 obj <>stream x3P0P5T5T0T5RH1230 !U`f`T077k (ɥPRTʥT˥Tȥ`ȥ 47KM V8qy(,8!܄Rv yxDm uH 2I<1m<$*R缝EH9,㞳4Bv*fx$sb=9`Ϧ.WO@.+i endstream endobj 32 0 obj <>stream x3T0P0Q5T052S , 1s L, @ Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAm^wг̥o$ۻ0@&.WO@.I\I{ endstream endobj 27 0 obj <>stream x333U0P0Q5T0P02QH1230!U`jbT02@.'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠qAnDm@_ct?~we_U+¿ȥwMϾc0=Mַq>\oHXĠja endstream endobj 22 0 obj <>stream x37׳T0P0Vе0T072R @c$r*,L c j2K:yr{*rUr{q;8+9.@Sc݀}o]s~Nin^1P5l+y.d4h>akK^W &ׂ/MY'G]?k.dۡhMѢ[nmp07NSCB _H endstream endobj 17 0 obj <>stream x353S0P0R57T052R @c$r*̍ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j H4 T{½&U/w_e-ۻFT4{b>  )\=]K endstream endobj 12 0 obj <>stream x353S0P0R57T052S , 1s L @Y@I'O.}O_T.pJ.}2.}g  45KM V8qy(fk}{oߨO|ؾ<6>ܓ}??v%>stream x37V0P0U5P02S , 1s L &@)Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAmy^{?/.-<7]vlɡ# \ \O endstream endobj 63 0 obj <>stream x35P0P0T53Q012S @pFr.WXP0b]0 (ɥPRTʥTɥTƥ`ȥ 45KM V8qy(_T|}&wFu5?m{a|އ{̷oow˾֯տK.&van1, \ \ rI endstream endobj 58 0 obj <>stream x33ֳP0P0R53W01R @c$r*Z, # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j ڤT5>stream x333Q0P0Uе0T0T5TH1230!U`jbT02L,ɥPRTʥTɥTƥ`ȥ 45KM ƥSW bg颠sY yTslW񃡁S! Z$S endstream endobj 48 0 obj <>stream x333Q0P0S5 F )\z@A 1s LM fF@5%<=}JJSÁ*=ʸ ]r;;66 @ܼb;;.Owx$.sE]~WU_~_;Ǡ H$ endstream endobj 43 0 obj <>stream x333T0P0V53T"#C.= ɹ\ `A3c  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1PY<'y>h|"| 8eRr&>{{l"^kLnp0b.WO@.ARz endstream endobj 38 0 obj <>stream x3P0P53T55S0Q5QH1230 !U`fjT052kf`i'O.}O_T.pZ.}B.}gC.}h\nn@n.P9?47ΎEAm'" _w’sY*nk}YW޲/s|a#tu}սkltllt"BB ͧVP endstream endobj 71 0 obj <>stream x]1N@E{7HfL iBCBm9PP^fs|z|ky]0N/ךr}ʟT5{56KwΛwҥvgx{;7Nm-Vtb x﷙ O}(ZOlCj!@[PjDLU&bsPl \Mƃ &_WH}+V|opj@+&_@2@\ 9|5 WI|M:]l*_gNW:t66U&u6tIM:]뜂ӵ̗Spr NW6U toC_|:] P@ }Q@r(( ( ( (=]8^IU׺?]p^q˼~R endstream endobj 10 0 obj <>/FontMatrix[1 0 0 1 0 0]/FontBBox[0 0 86 81]/FirstChar 0/LastChar 58/Widths[ 55.6 25 55.6 55.6 55.6 55.6 55.6 55.6 53.3 33.3 55.6 55.6 77.9 23.5 59.7 54.2 61.1 61.5 58.7 59 30.8 24.4 59 89.3 52.3 0 0 0 0 0 74.4 67.5 85.9 64.1 43.1 62.2 61.1 37.7 67.4 67.4 61.3 37.2 30.8 66.4 68.3 29.7 98.3 60.4 63.8 19.3 48.8 44.3 50 50 60 43 25.2 47.9 73] /Subtype/Type3>> endobj 72 0 obj <> endobj 73 0 obj <>stream 2024-05-13T15:54:31+02:00 2024-05-13T15:54:31+02:00 GPL Ghostscript 950 (ps2write) Untitled endstream endobj 2 0 obj <>endobj xref 0 74 0000000000 65535 f 0000002023 00000 n 0000021285 00000 n 0000001964 00000 n 0000001813 00000 n 0000000228 00000 n 0000001793 00000 n 0000002088 00000 n 0000002129 00000 n 0000009361 00000 n 0000018439 00000 n 0000012495 00000 n 0000015706 00000 n 0000003280 00000 n 0000006101 00000 n 0000009052 00000 n 0000012270 00000 n 0000015423 00000 n 0000002997 00000 n 0000005896 00000 n 0000008800 00000 n 0000011964 00000 n 0000015105 00000 n 0000002788 00000 n 0000005584 00000 n 0000008497 00000 n 0000011738 00000 n 0000014810 00000 n 0000002499 00000 n 0000005341 00000 n 0000008274 00000 n 0000011521 00000 n 0000014571 00000 n 0000002243 00000 n 0000005054 00000 n 0000008024 00000 n 0000011228 00000 n 0000014169 00000 n 0000017588 00000 n 0000004825 00000 n 0000007760 00000 n 0000010938 00000 n 0000013872 00000 n 0000017301 00000 n 0000004593 00000 n 0000007456 00000 n 0000010634 00000 n 0000013643 00000 n 0000017059 00000 n 0000004355 00000 n 0000007171 00000 n 0000010404 00000 n 0000013423 00000 n 0000016815 00000 n 0000004065 00000 n 0000006960 00000 n 0000010153 00000 n 0000013161 00000 n 0000016518 00000 n 0000003858 00000 n 0000006678 00000 n 0000009868 00000 n 0000012941 00000 n 0000016240 00000 n 0000003536 00000 n 0000006408 00000 n 0000009642 00000 n 0000012668 00000 n 0000015992 00000 n 0000002172 00000 n 0000002211 00000 n 0000017892 00000 n 0000019572 00000 n 0000019852 00000 n trailer << /Size 74 /Root 1 0 R /Info 2 0 R /ID [<862515688AAC43C97985EF8810CF1AA3><862515688AAC43C97985EF8810CF1AA3>] >> startxref 21451 %%EOF queueing/doc/summary.texi0000664000175000017500000001454514620415615015434 0ustar morenomoreno@c This file has been automatically generated from summary.txi @c by proc.m. Do not edit this file, all changes will be lost @c -*- texinfo -*- @c Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2020 Moreno Marzolla @c @c This file is part of the queueing package. @c @c The queueing package is free software; you can redistribute it @c and/or modify it under the terms of the GNU General Public License @c as published by the Free Software Foundation; either version 3 of @c the License, or (at your option) any later version. @c @c The queueing package is distributed in the hope that it will be @c useful, but WITHOUT ANY WARRANTY; without even the implied warranty @c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @c GNU General Public License for more details. @c @c You should have received a copy of the GNU General Public License @c along with the queueing package; see the file COPYING. If not, see @c . @node Summary @chapter Summary @menu * About the Queueing Package:: What is the Queueing package. * Contributing Guidelines:: How to contribute. * Acknowledgments:: @end menu @node About the Queueing Package @section About the Queueing Package This document describes the @code{queueing} package for GNU Octave (@code{queueing} in short). The @code{queueing} package, previously known as @code{qnetworks} toolbox, is a collection of functions for analyzing queueing networks and Markov chains written for GNU Octave. Specifically, @code{queueing} contains functions for analyzing Jackson networks, open, closed or mixed product-form BCMP networks, and computing performance bounds. The following algorithms are available @itemize @item Convolution for closed, single-class product-form networks with load-dependent service centers; @item Exact and approximate Mean Value Analysis (MVA) for single and multiple class product-form closed networks; @item MVA for mixed, multiple class product-form networks with load-independent service centers; @item Approximate MVA for closed, single-class networks with blocking (MVABLO algorithm by F. Akyildiz); @item Asymptotic Bounds, Balanced System Bounds and Geometric Bounds; @end itemize @noindent @code{queueing} provides functions for analyzing the following types of single-station queueing systems: @itemize @item @math{M/M/1} @item @math{M/M/m} @item @math{M/M/\infty} @item @math{M/M/1/k} single-server, finite capacity system @item @math{M/M/m/k} multiple-server, finite capacity system @item Asymmetric @math{M/M/m} @item @math{M/G/1} (general service time distribution) @item @math{M/H_m/1} (Hyperexponential service time distribution) @end itemize Functions for Markov chain analysis are also provided (discrete- and continuous-time chains are supported): @itemize @item Birth-death processes; @item Transient and stationary state occupancy probabilities; @item Mean time to absorption; @item Expected sojourn times and time-averaged sojourn times; @item Mean first passage times; @end itemize The @code{queueing} package is distributed under the terms of the GNU General Public License (GPL), version 3 or later (@pxref{Copying}). You are encouraged to share this software with others, and improve this package by contributing additional functions and reporting bugs. @xref{Contributing Guidelines}. If you use the @code{queueing} package in a technical paper, please cite it as: @quotation Moreno Marzolla, @emph{The qnetworks Toolbox: A Software Package for Queueing Networks Analysis}. Khalid Al-Begain, Dieter Fiems and William J. Knottenbelt, Editors, Proceedings 17th International Conference on Analytical and Stochastic Modeling Techniques and Applications (ASMTA 2010) Cardiff, UK, June 14--16, 2010, volume 6148 of Lecture Notes in Computer Science, Springer, pp. 102--116, ISBN 978-3-642-13567-5 @end quotation If you use BibTeX, this is the citation block: @verbatim @inproceedings{queueing, author = {Moreno Marzolla}, title = {The qnetworks Toolbox: A Software Package for Queueing Networks Analysis}, booktitle = {Analytical and Stochastic Modeling Techniques and Applications, 17th International Conference, ASMTA 2010, Cardiff, UK, June 14-16, 2010. Proceedings}, editor = {Khalid Al-Begain and Dieter Fiems and William J. Knottenbelt}, year = {2010}, publisher = {Springer}, series = {Lecture Notes in Computer Science}, volume = {6148}, pages = {102--116}, ee = {http://dx.doi.org/10.1007/978-3-642-13568-2_8}, isbn = {978-3-642-13567-5} } @end verbatim An early draft of the paper above is available as Technical Report @uref{https://www.moreno.marzolla.name/publications/papers/UBLCS-2010-04.pdf, UBLCS-2010-04}, February 2010, Department of Computer Science, University of Bologna, Italy. @node Contributing Guidelines @section Contributing Guidelines Contributions and bug reports are @emph{always} welcome. If you want to contribute to the @code{queueing} package, here are some guidelines: @itemize @item If you are contributing a new function, please embed proper documentation within the function itself. The documentation must be in @code{texinfo} format, so that it can be extracted and included into the printable manual. See the existing functions for the documentation style. @item Make sure that each new function validates its input parameters. For example, a function accepting vectors should check whether the dimensions match. @item Provide bibliographic references for each new algorithm you contribute. Document any significant difference from the reference. Update the @file{doc/references.txi} file if appropriate. @item Include test and demo blocks. Test blocks are particularly important, since most algorithms are tricky to implement correctly. If appropriate, test blocks should also verify that the function fails on incorrect inputs. @end itemize Send your contribution to Moreno Marzolla (@email{moreno.marzolla@@unibo.it}). If you are a user of this package and find it useful, let me know by dropping me a line. Thanks. @node Acknowledgments @section Acknowledgments The following people (listed alphabetically) contributed to the @code{queueing} package, either by providing feedback, reporting bugs or contributing code: Philip Carinhas, Phil Colbourn, Diego Didona, Yves Durand, Marco Guazzone, Dmitry Kolesnikov, Michele Mazzucco, Marco Paolieri. queueing/doc/references.texi0000664000175000017500000001541414620415615016054 0ustar morenomoreno@c This file has been automatically generated from references.txi @c by proc.m. Do not edit this file, all changes will be lost @c -*- texinfo -*- @c Copyright (C) 2012, 2016 Moreno Marzolla @c @c This file is part of the queueing package. @c @c The queueing package is free software; you can redistribute it @c and/or modify it under the terms of the GNU General Public License @c as published by the Free Software Foundation; either version 3 of @c the License, or (at your option) any later version. @c @c The queueing package is distributed in the hope that it will be @c useful, but WITHOUT ANY WARRANTY; without even the implied warranty @c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @c GNU General Public License for more details. @c @c You should have received a copy of the GNU General Public License @c along with the queueing package; see the file COPYING. If not, see @c . @node References @chapter References @table @asis @item [Aky88] Ian F. Akyildiz, @cite{Mean Value Analysis for Blocking Queueing Networks}, IEEE Transactions on Software Engineering, vol. 14, n. 2, april 1988, pp. 418--428. DOI @uref{http://dx.doi.org/10.1109/32.4663, 10.1109/32.4663} @item [Bar79] Y. Bard, @cite{Some Extensions to Multiclass Queueing Network Analysis}, proc. 4th Int. Symp. on Modelling and Performance Evaluation of Computer Systems, feb. 1979, pp. 51--62. @item [BCMP75] F. Baskett, K. Mani Chandy, R. R. Muntz, and F. G. Palacios. 1975. @cite{Open, Closed, and Mixed Networks of Queues with Different Classes of Customers}. J. ACM 22, 2 (April 1975), 248—260, DOI @uref{http://doi.acm.org/10.1145/321879.321887, 10.1145/321879.321887} @item [BGMT98] G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and Performance Evaluation with Computer Science Applications}, Wiley, 1998. @item [Buz73] J. P. Buzen, @cite{Computational Algorithms for Closed Queueing Networks with Exponential Servers}, Communications of the ACM, volume 16, number 9, september 1973, pp. 527--531. DOI @uref{http://doi.acm.org/10.1145/362342.362345, 10.1145/362342.362345} @item [C08] G. Casale, @cite{A note on stable flow-equivalent aggregation in closed networks}. Queueing Syst. Theory Appl., 60:193–-202, December 2008, DOI @uref{http://dx.doi.org/10.1007/s11134-008-9093-6, 10.1007/s11134-008-9093-6} @item [CMS08] G. Casale, R. R. Muntz, G. Serazzi, @cite{Geometric Bounds: a Non-Iterative Analysis Technique for Closed Queueing Networks}, IEEE Transactions on Computers, 57(6):780-794, June 2008. DOI @uref{http://doi.ieeecomputersociety.org/10.1109/TC.2008.37, 10.1109/TC.2008.37} @item @anchor{GrSn97}[GrSn97] C. M. Grinstead, J. L. Snell, (July 1997). @cite{Introduction to Probability}. American Mathematical Society. ISBN 978-0821807491; this excellent textbook is @uref{http://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/amsbook.mac.pdf, available in PDF format} and can be used under the terms of the @uref{http://www.gnu.org/copyleft/fdl.html, GNU Free Documentation License (FDL)} @item [Jac04] J. R. Jackson, @cite{Jobshop-Like Queueing Systems}, Vol. 50, No. 12, Ten Most Influential Titles of "Management Science's" First Fifty Years (Dec., 2004), pp. 1796-1802, @uref{http://www.jstor.org/stable/30046149, available online} @item [Jai91] R. Jain, @cite{The Art of Computer Systems Performance Analysis}, Wiley, 1991, p. 577. @item [HsLa87] C. H. Hsieh and S. Lam, @cite{Two classes of performance bounds for closed queueing networks}, PEVA, vol. 7, n. 1, pp. 3--30, 1987 @item [Ker84] T. Kerola, @cite{The Composite Bound Method (CBM) for Computing Throughput Bounds in Multiple Class Environments}, Performance Evaluation, Vol. 6 Isue 1, March 1986, DOI @uref{http://dx.doi.org/10.1016/0166-5316(86)90002-7, 10.1016/0166-5316(86)90002-7}; also available as @uref{http://docs.lib.purdue.edu/cstech/395/, Technical Report CSD-TR-475}, Department of Computer Sciences, Purdue University, mar 13, 1984 (Revised aug 27, 1984). @item [LZGS84] E. D. Lazowska, J. Zahorjan, G. Scott Graham, and K. C. Sevcik, @cite{Quantitative System Performance: Computer System Analysis Using Queueing Network Models}, Prentice Hall, 1984. @uref{http://www.cs.washington.edu/homes/lazowska/qsp/, available online}. @item [ReKo76] M. Reiser, H. Kobayashi, @cite{On The Convolution Algorithm for Separable Queueing Networks}, In Proceedings of the 1976 ACM SIGMETRICS Conference on Computer Performance Modeling Measurement and Evaluation (Cambridge, Massachusetts, United States, March 29--31, 1976). SIGMETRICS '76. ACM, New York, NY, pp. 109--117. DOI @uref{http://doi.acm.org/10.1145/800200.806187, 10.1145/800200.806187} @item [ReLa80] M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, April 1980, pp. 313--322. DOI @uref{http://doi.acm.org/10.1145/322186.322195, 10.1145/322186.322195} @item [Sch79] P. Schweitzer, @cite{Approximate Analysis of Multiclass Closed Networks of Queues}, Proc. Int. Conf. on Stochastic Control and Optimization, jun 1979, pp. 25—29 @item [Sch80] H. D. Schwetman, @cite{Testing Network-of-Queues Software}, @uref{http://docs.lib.purdue.edu/cstech/259/, Technical Report CSD-TR 330}, Department of computer Sciences, Purdue University, 1980 @item [Sch81] H. D. Schwetman, @cite{Some Computational Aspects of Queueing Network Models}, @uref{http://docs.lib.purdue.edu/cstech/285/, Technical Report CSD-TR-354}, Department of Computer Sciences, Purdue University, feb, 1981 (revised). @item @anchor{Sch82}[Sch82] H. D. Schwetman, @cite{Implementing the Mean Value Algorithm for the Solution of Queueing Network Models}, @uref{http://docs.lib.purdue.edu/cstech/286/, Technical Report CSD-TR-355}, Department of Computer Sciences, Purdue University, feb 15, 1982. @item [Sch84] T. Kerola, H. D. Schwetman, @cite{Performance Bounds for Multiclass Models}, @uref{http://docs.lib.purdue.edu/cstech/399/, Technical Report CSD-TR-479}, Department of Computer Sciences, Purdue University, 1984. @item [Tij03] H. C. Tijms, @cite{A first course in stochastic models}, John Wiley and Sons, 2003, ISBN 0471498807, ISBN 9780471498803, DOI @uref{http://dx.doi.org/10.1002/047001363X, 10.1002/047001363X} @item [ZaWo81] J. Zahorjan and E. Wong, @cite{The solution of separable queueing network models using mean value analysis}. SIGMETRICS Perform. Eval. Rev. 10, 3 (Sep. 1981), 80-85. DOI @uref{http://doi.acm.org/10.1145/1010629.805477, 10.1145/1010629.805477} @item [Zeng03] G. Zeng, @cite{Two common properties of the erlang-B function, erlang-C function, and Engset blocking function}, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296 DOI @uref{http://dx.doi.org/10.1016/S0895-7177(03)90040-9, 10.1016/S0895-7177(03)90040-9} @end table queueing/doc/gpl.texi0000664000175000017500000010452214620415615014514 0ustar morenomoreno@c This file has been automatically generated from gpl.txi @c by proc.m. Do not edit this file, all changes will be lost @node Copying @appendix GNU GENERAL PUBLIC LICENSE @cindex warranty @cindex copyright @center Version 3, 29 June 2007 @display Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @heading Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program---to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. @heading TERMS AND CONDITIONS @enumerate 0 @item Definitions. ``This License'' refers to version 3 of the GNU General Public License. ``Copyright'' also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. ``The Program'' refers to any copyrightable work licensed under this License. Each licensee is addressed as ``you''. ``Licensees'' and ``recipients'' may be individuals or organizations. To ``modify'' a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a ``modified version'' of the earlier work or a work ``based on'' the earlier work. A ``covered work'' means either the unmodified Program or a work based on the Program. To ``propagate'' a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To ``convey'' a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays ``Appropriate Legal Notices'' to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. @item Source Code. The ``source code'' for a work means the preferred form of the work for making modifications to it. ``Object code'' means any non-source form of a work. A ``Standard Interface'' means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The ``System Libraries'' of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A ``Major Component'', in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The ``Corresponding Source'' for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. @item Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. @item Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. @item Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. @item Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: @enumerate a @item The work must carry prominent notices stating that you modified it, and giving a relevant date. @item The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to ``keep intact all notices''. @item You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. @item If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. @end enumerate A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. @item Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: @enumerate a @item Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. @item Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. @item Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. @item Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. @item Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. @end enumerate A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A ``User Product'' is either (1) a ``consumer product'', which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, ``normally used'' refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. ``Installation Information'' for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. @item Additional Terms. ``Additional permissions'' are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: @enumerate a @item Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or @item Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or @item Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or @item Limiting the use for publicity purposes of names of licensors or authors of the material; or @item Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or @item Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. @end enumerate All other non-permissive additional terms are considered ``further restrictions'' within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. @item Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. @item Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. @item Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An ``entity transaction'' is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. @item Patents. A ``contributor'' is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's ``contributor version''. A contributor's ``essential patent claims'' are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, ``control'' includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a ``patent license'' is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To ``grant'' such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. ``Knowingly relying'' means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is ``discriminatory'' if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. @item No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. @item Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. @item Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. @item Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. @item Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. @item Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. @end enumerate @heading END OF TERMS AND CONDITIONS @heading How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found. @smallexample @var{one line to give the program's name and a brief idea of what it does.} Copyright (C) @var{year} @var{name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see @url{http://www.gnu.org/licenses/}. @end smallexample Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: @smallexample @var{program} Copyright (C) @var{year} @var{name of author} This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. This is free software, and you are welcome to redistribute it under certain conditions; type @samp{show c} for details. @end smallexample The hypothetical commands @samp{show w} and @samp{show c} should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an ``about box''. You should also get your employer (if you work as a programmer) or school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see @url{http://www.gnu.org/licenses/}. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. queueing/doc/installation.texi0000664000175000017500000004402414620415615016433 0ustar morenomoreno@c This file has been automatically generated from installation.txi @c by proc.m. Do not edit this file, all changes will be lost @c -*- texinfo -*- @c Copyright (C) 2008, 2009, 2010, 2011, 2012, 2014, 2016, 2018, 2024 Moreno Marzolla @c @c This file is part of the queueing package. @c @c The queueing package is free software; you can redistribute it @c and/or modify it under the terms of the GNU General Public License @c as published by the Free Software Foundation; either version 3 of @c the License, or (at your option) any later version. @c @c The queueing package is distributed in the hope that it will be @c useful, but WITHOUT ANY WARRANTY; without even the implied warranty @c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @c GNU General Public License for more details. @c @c You should have received a copy of the GNU General Public License @c along with the queueing package; see the file COPYING. If not, see @c . @ifset INSTALLONLY @include conf.texi This file documents the installation procedure of the Octave @code{queueing} package. @code{queueing} is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 3 or later, as published by the Free Software Foundation. @quotation Note This file (@file{INSTALL}) is automatically generated from @file{doc/installation.txi} in the @code{queueing} source tree. Do not modify this document directly, as changes will be lost. Modify @file{doc/installation.txi} instead. @end quotation @end ifset @node Installation and Getting Started @chapter Installation and Getting Started @menu * Installation through Octave package management system:: * Manual installation:: * Development sources:: * Testing and Demos:: * Naming Conventions:: * Quick start Guide:: @end menu @c @c @c @node Installation through Octave package management system @section Installation through Octave package management system The most recent version of @code{queueing} is @value{VERSION} and can be downloaded from @url{https://gnu-octave.github.io/packages/queueing/} Additional information can be found at @url{https://www.moreno.marzolla.name/software/queueing/} To install @code{queueing}, follow these steps: @enumerate @item If you have a recent version of GNU Octave and a network connection, you can install @code{queueing} from Octave command prompt using this command: @example octave:1> @kbd{pkg install pkg install "https://github.com/mmarzolla/queueing/releases/download/@value{VERSION}/queueing-@value{VERSION}.tar.gz"} @end example The command above will download and install the latest version of the @code{queueing} package from the source repository, and install it on your machine. If you do not have root access, you can perform a local install with: @example octave:1> @kbd{pkg install -local "https://github.com/mmarzolla/queueing/releases/download/@value{VERSION}/queueing-@value{VERSION}.tar.gz"} @end example This will install @code{queueing} in your home directory, and the package will be available to the current user only. @item Alternatively, you can first download the @code{queueing} tarball; to install the package in the system-wide location issue this command at the Octave prompt: @example octave:1> @kbd{pkg install @emph{queueing-@value{VERSION}.tar.gz}} @end example @noindent (you may need to start Octave as root in order to allow the installation to copy the files to the target locations). After this, all functions will be available each time Octave starts, without the need to tweak the search path. If you do not have root access, you can do a local install using: @example octave:1> @kbd{pkg install -local queueing-@value{VERSION}.tar.gz} @end example @item Use the @kbd{pkg list} command at the Octave prompt to check that the @code{queueing} package has been succesfully installed; you should see something like: @example octave:1>@kbd{pkg list queueing} Package Name | Version | Installation directory --------------+---------+----------------------- queueing | @value{VERSION} | /home/moreno/octave/queueing-@value{VERSION} @end example @item Starting from version 1.1.1, @code{queueing} is no longer automatically loaded on Octave start. To make the functions available for use, you need to issue the command @example octave:1>@kbd{pkg load queueing} @end example @noindent at the Octave prompt. To automatically load @code{queueing} each time Octave starts, you can add the command above to the startup script (usually, @file{~/.octaverc} on Unix systems). @item To completely remove @code{queueing} from your system, use the @kbd{pkg uninstall} command: @example octave:1> @kbd{pkg uninstall queueing} @end example @end enumerate @c @c @c @node Manual installation @section Manual installation If you want to manually install @code{queueing} in a custom location, you can download the tarball and unpack it somewhere: @example @kbd{tar xvfz queueing-@value{VERSION}.tar.gz} @kbd{cd queueing-@value{VERSION}/} @end example Copy all @code{.m} files from the @file{inst/} directory to some target location. Then, start Octave with the @option{-p} option to add the target location to the search path, so that Octave will find all @code{queueing} functions automatically: @example @kbd{octave -p @emph{/path/to/queueing}} @end example For example, if all @code{queueing} m-files are in @file{/usr/local/queueing}, you can start Octave as follows: @example @kbd{octave -p @emph{/usr/local/queueing}} @end example If you want, you can add the following line to @file{~/.octaverc}: @example @kbd{addpath("@emph{/path/to/queueing}");} @end example @noindent so that the path @file{/path/to/queueing} is automatically added to the search path each time Octave is started, and you no longer need to specify the @option{-p} option on the command line. @c @c The following will not appear in the INSTALL text file @c @ifclear INSTALLONLY @node Development sources @section Development sources The source code of the @code{queueing} package can be found in the Git repository at the URL: @url{https://github.com/mmarzolla/queueing} The source distribution contains additional development files that are not present in the installation tarball. This section briefly describes the content of the source tree. This is only relevant for developers who want to modify the code or the documentation. The source distribution contains the following directories: @table @file @item doc/ Documentation sources. Most of the documentation is extracted from the comment blocks of function files from the @file{inst/} directory. @item inst/ This directory contains the @verb{|m|}-files which implement the various algorithms provided by @code{queueing}. As a notational convention, the names of functions for Queueing Networks begin with the @samp{qn} prefix; the name of functions for Continuous-Time Markov Chains (CTMCs) begin with the @samp{ctmc} prefix, and the names of functions for Discrete-Time Markov Chains (DTMCs) begin with the @samp{dtmc} prefix. @item test/ This directory contains the scripts used to run all function tests. @item devel/ This directory contains functions that are either not working properly, or need additional testing before they are moved to the @file{inst/} directory. @end table The @code{queueing} package ships with a Makefile which can be used to produce the documentation (in PDF and HTML format), and automatically execute all tests. The following targets are defined: @table @code @item all Running @samp{make} (or @samp{make all}) on the top-level directory builds the programs used to extract the documentation from the comments embedded in the m-files, and then produce the documentation in PDF and HTML format (@file{doc/queueing.pdf} and @file{doc/queueing.html}, respectively). @item check Running @samp{make check} will execute all tests contained in the m-files. If you modify the code of any function in the @file{inst/} directory, you should run the tests to ensure that no errors have been introduced. You are also encouraged to contribute new tests, especially for functions that are not adequately validated. @item clean @itemx distclean @itemx dist The @samp{make clean}, @samp{make distclean} and @samp{make dist} commands are used to clean up the source directory and prepare the distribution archive in compressed tar format. @end table @node Testing and Demos @section Testing and Demos The @code{queueing} package makes extensive use of test and demo blocks. These are GNU Octave features that allow tests and demos to be embedded within the source code of m-files. Multiple test blocks can be defined using the @samp{%!test} directive: @example @group %!test %! # test code %! %!test %! # another test code @end group @end example Test blocks rely on the @command{assert} built-in function to check che correctness of computation, e.g., by comparing the results with known ``good'' values or by cross-checking with other functions. The tests for a given function can be manually executed with the @command{test} command: for example, @code{test("qsmm1")} executes all tests in the script file @file{qsmm1.m} and prints a diagnostic message: @example @kbd{test("qsmm1");} @print{} PASSES 3 out of 3 tests @end example A quick way to run all tests for all functions in the @code{queueing} package is using the @command{runtests} built-in command at the GNU Octave prompt, passing as parameter the full path where the @code{.m} files are stored: @example @kbd{runtests("/path/to/queueing/inst");} @print{} Processing files in /path/to/queueing/inst: @print{} @print{} ctmc.m .............................................. PASS 9/9 @print{} ctmcbd.m ............................................ PASS 1/1 @dots{} @end example A better way for Unix users is to use the @file{Makefile} provided in the top-level directory of the development sources. As described in @ref{Development sources}, the @file{Makefile} defines a target @samp{check} that runs all tests over all functions in the @file{inst/} directory. Simply run the @example @kbd{make check} @end example @noindent command from the Unix shell to run all tests. The source files include small demos that show how the function defined there can be used. Similarly to test blocks, demos are embedded in the source files using the @samp{%!demo} directive. Demos can be displayed and run using the @command{demo} built-in command at the GNU Octave prompt: @example @kbd{demo("qsmm1");} @verbatim ## Given a M/M/1 queue, compute the steady-state probability pk ## of having k requests in the systen. lambda = 0.2; mu = 0.25; k = 0:10; pk = qsmm1(lambda, mu, k); plot(k, pk, "-o", "linewidth", 2); xlabel("N. of requests (k)"); ylabel("p_k"); title(sprintf("M/M/1 system, \\lambda = %g, \\mu = %g", lambda, mu)); @end verbatim @end example @node Naming Conventions @section Naming Conventions Most of the functions in the @code{queueing} package obey a common naming convention. Function names are made of several parts; the first part is a prefix which indicates the class of problems the function addresses: @table @asis @item @strong{ctmc-} Functions for continuous-time Markov chains @item @strong{dtmc-} Functions for discrete-time Markov chains @item @strong{qs-} Functions for analyzing single-station queueing systems (individual service centers) @item @strong{qn-} Functions for analyzing queueing networks @end table Functions dealing with Markov chains start with either the @code{ctmc} or @code{dtmc} prefix; the prefix is optionally followed by an additional string which hints at what the function does: @table @asis @item @strong{-bd} Birth-Death process @item @strong{-mtta} Mean Time to Absorption @item @strong{-fpt} First Passage Times @item @strong{-exps} Expected Sojourn Times @item @strong{-taexps} Time-Averaged Expected Sojourn Times @end table For example, function @code{ctmcbd} returns the infinitesimal generator matrix for a continuous birth-death process, while @code{dtmcbd} returns the transition probability matrix for a discrete birth-death process. Note that there exist functions @code{ctmc} and @code{dtmc} (without any suffix) that compute steady-state and transient state occupancy probabilities for CTMCs and DTMCs, respectively. @xref{Markov Chains}. Functions whose name starts with @code{qs-} deal with single station queueing systems. The suffix describes the type of system, e.g., @code{qsmm1} for @math{M/M/1}, @code{qnmmm} for @math{M/M/m} and so on. @xref{Single Station Queueing Systems}. Finally, functions whose name starts with @code{qn-} deal with queueing networks. The character that follows indicates whether the function handles open (@code{'o'}) or closed (@code{'c'}) networks, and whether there is a single customer class (@code{'s'}) or multiple classes (@code{'m'}). The string @code{mix} indicates that the function supports mixed networks with both open and closed customer classes. @table @asis @item @strong{-os-} Open, single-class network: open network with a single class of customers @item @strong{-om-} Open, multiclass network: open network with multiple job classes @item @strong{-cs-} Closed, single-class network @item @strong{-cm-} Closed, multiclass network @item @strong{-mix-} Mixed network with open and closed classes of customers @end table The last part of the function name indicates the algorithm implemented by the function. @xref{Queueing Networks}. @table @asis @item @strong{-aba} Asymptotic Bounds Analysis @item @strong{-bsb} Balanced System Bounds @item @strong{-gb} Geometric Bounds @item @strong{-pb} PB Bounds @item @strong{-cb} Composite Bounds (CB) @item @strong{-mva} Mean Value Analysis (MVA) algorithm @item @strong{-cmva} Conditional MVA @item @strong{-mvald} MVA with general load-dependent servers @item @strong{-mvaap} Approximate MVA @item @strong{-mvablo} MVABLO approximation for blocking queueing networks @item @strong{-conv} Convolution algorithm @item @strong{-convld} Convolution algorithm with general load-dependent servers @end table @cindex deprecated functions Some deprecated functions may be present in the @code{queueing} package; generally, these are functions that have been renamed, and the old name is kept for a while for backward compatibility. Deprecated functions are not documented and will be removed in future releases. Calling a deprecated functions displays a warning message that appears only once per session. The warning message can be turned off with the command: @example @group octave:1> @kbd{warning ("off", "qn:deprecated-function");} @end group @end example However, you are strongly recommended to update your code to the new API. To help catching usages of deprecated functions, you can transform warnings into errors so that your application stops immediately: @example @group octave:1> @kbd{warning ("error", "qn:deprecated-function");} @end group @end example @node Quick start Guide @section Quick start Guide You can use all functions by simply invoking their name with the appropriate parameters; an error is shown in case of missing/wrong parameters. Extensive documentation is provided for each function, and can be displayed with the @command{help} command. For example: @example octave:2> @kbd{help qncsmvablo} @end example @noindent shows the documentation for the @command{qncsmvablo} function. Additional information can be found in the @code{queueing} manual, that is available in PDF format in @file{doc/queueing.pdf} and in HTML format in @file{doc/queueing.html}. Ad sicussed above, many functions have demo blocks showing usage examples. To execute the demos for the @command{qnclosed} function, use the @command{demo} command: @example octave:4> @kbd{demo qnclosed} @end example We now illustrate a few examples of how the @code{queueing} package can be used. More examples are provided in the manual. @noindent @strong{Example 1} Compute the stationary state occupancy probabilities of a continuous-time Markov chain with infinitesimal generator matrix @iftex @tex $$ {\bf Q} = \pmatrix{ -0.8 & 0.6 & 9,2 \cr 0.3 & -0.7 & 0.4 \cr 0.2 & 0.2 & -0.4 } $$ @end tex @end iftex @ifnottex @example @group / -0.8 0.6 0.2 \ Q = | 0.3 -0.7 0.4 | \ 0.2 0.2 -0.4 / @end group @end example @end ifnottex @example @group Q = [ -0.8 0.6 0.2; ... 0.3 -0.7 0.4; ... 0.2 0.2 -0.4 ]; q = ctmc(Q) @result{} q = 0.23256 0.32558 0.44186 @end group @end example @noindent @strong{Example 2} Compute the transient state occupancy probability after @math{n=3} transitions of a three state discrete-time birth-death process, with birth probabilities @math{\lambda_{01} = 0.3} and @math{\lambda_{12} = 0.5} and death probabilities @math{\mu_{10} = 0.5} and @math{\mu_{21} = 0.7}, assuming that the system is initially in state zero (i.e., the initial state occupancy probabilities are @math{[1, 0, 0]}). @example @group n = 3; p0 = [1 0 0]; P = dtmcbd( [0.3 0.5], [0.5 0.7] ); p = dtmc(P,n,p0) @result{} p = 0.55300 0.29700 0.15000 @end group @end example @noindent @strong{Example 3} Compute server utilization, response time, mean number of requests and throughput of a closed queueing network with @math{N=4} requests and three @math{M/M/1}--FCFS queues with mean service times @math{S = [1.0, 0.8, 1.4]} and average number of visits @math{V = [1.0, 0.8, 0.8]} @example @group S = [1.0 0.8 1.4]; V = [1.0 0.8 0.8]; N = 4; [U R Q X] = qncsmva(N, S, V) @result{} U = 0.70064 0.44841 0.78471 R = 2.1030 1.2642 3.2433 Q = 1.47346 0.70862 1.81792 X = 0.70064 0.56051 0.56051 @end group @end example @noindent @strong{Example 4} Compute server utilization, response time, mean number of requests and throughput of an open queueing network with three @math{M/M/1}--FCFS queues with mean service times @math{S = [1.0, 0.8, 1.4]} and average number of visits @math{V = [1.0, 0.8, 0.8]}. The overall arrival rate is @math{\lambda = 0.8} requests/second. @example @group S = [1.0 0.8 1.4]; V = [1.0 0.8 0.8]; lambda = 0.8; [U R Q X] = qnos(lambda, S, V) @result{} U = 0.80000 0.51200 0.89600 R = 5.0000 1.6393 13.4615 Q = 4.0000 1.0492 8.6154 X = 0.80000 0.64000 0.64000 @end group @end example @c @c @c @end ifclear queueing/doc/web.pdf0000664000175000017500000006107614620415627014320 0ustar morenomoreno%PDF-1.5 %쏢 %%Invocation: gs -q -dSAFER -dNOPAUSE -dBATCH -dCompatibilityLevel=1.5 -sDEVICE=pdfwrite -sOutputFile=? -dPDFSETTINGS#/prepress -dMaxSubsetPct=100 -dSubsetFonts=true -dEmbedAllFonts=true -dAutoRotatePages#/None - 5 0 obj <> stream xYie7 !K`wݬR$%Zʇ|ʪ4>뭻 ~z>T'?bYB)ϬַׇĔs'KH%Wr-綳'Eg-H):|c`~x~ř1+E,]]^]Grxl9=+𦝗>IL(iճ)v*);Hf CsFhN#H 4zB;4Gif\uTB;tx.F;,su +-dɢB(q,Svs)xD2VAt/%G7;fܓ2ZߙgW\xu.-je,NV>Y燗Һ9|{;j8Ms]4ӯO.#1dkWr^%S ë{䳢KLi_ esw69UD^ و_K6-&~ĖЦr1e,NLίP]XO`d-{B{_I/ԐeFi[BɩuX .mo-.~I_Th~G~D|x<Ph!W0xrHvpbqJ[3UW)yo2X "d=Z6^6p2MCb߈mT vD|\^BSUrb(ϩQ}ch7a0DZI1j &VF4èh M1*jcԠ FEl*2çNC&Tղi VB4hv 2ŧwlnY~ .E@hM٩G9@SJhN%P9h~"TBSvZ斨eh.ciu\vhPv&UQƮEc|^bݨ>aTrv|Ґc)^<ߴyEV^32g"g f&pe9 IUҺ2.׊&ɋ-Ǿu|Gڴ ܟl%">|,^MҪ=ˊ{h]>WQɰˏ ݑ?zdMǪ:Βj%nvk{Fh{a)^ip 48"~F9h~޲8<( ѭ BC[V@IP/4:Y"~B)VnB/4Tv;TR&}(XWE]MH,"cblR!d:ls6Q0ل}48${g#bmb,UoxH>,Ug{bPV/YJ:N38#4[99ahpvΉ=6z\4DbwNF_Ӡ iPqN1lz&pNx"/1M=sՇ"?Y"}Fŝi^4TC86J~NK~'۳RE!M?/3&pendstream endobj 6 0 obj 2206 endobj 4 0 obj <> /Contents 5 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R ] /Count 1 >> endobj 1 0 obj <> endobj 7 0 obj <>endobj 8 0 obj <>endobj 74 0 obj <> endobj 75 0 obj <> endobj 73 0 obj <>stream x353Q0P5T5P05S @, 1s L  = :yr{*rr{q;8+rDwwvvrllfp;qy(tH˽z]o۝YV|ti_o]lw[G|}}//2˽j_{ D2.WO@.P endstream endobj 68 0 obj <>stream x33T0P0Q5P05R0VH123 !U`baT032L,ɥPRTʥTɥTƥ\r;;66 @ܼb;;.O$8*'sl_~ L\ \)J endstream endobj 63 0 obj <>stream x3ԳP0P0R5T"cC.=C ɹ\ `A3#  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1P }RE'Z$"H]_~Qb΂O kY^;2}c%z'ɳH:!>!Sr•[vM~;::"1`A.WO@.+U endstream endobj 58 0 obj <>stream x3P0P53R55R  1s ̌ &`M D<=}JJSÁj=  ]r;;66 @ܼb;;.Od Z ׉{[?| k''t7} endstream endobj 53 0 obj <>stream x3P0B]KSCC.=C U6 *i'BIQi*~8PPS!K4X.}7}gg7 7F[A(㜟SW bg颠pC~yUU5/8ekگ/Զ?ooo D7i&620rz*rD endstream endobj 48 0 obj <>stream x353T0PP53U06R5TH123!U`dbT01,,ɥPRTʥTɥTƥ`ȥ 45KM ƥSW bg颠`4?~E{AS! 9 endstream endobj 43 0 obj <>stream x3P0P57S5T0 )\z@a 1s - F`M $vU()*M*w pV0w˥{+esJsZ<]8ΐkbp4Y endstream endobj 38 0 obj <>stream x3P0P53R56,R  1s ̌ F`M ,ɥPRTʥT˥Tȥ`ȥ 47KM V8qy(';"Cl V1(0qz*rn, endstream endobj 33 0 obj <>stream x33S0P5T5T0S , 1s L- !3N\ %E\@\`)YK%hl,`c 4K9?47ΎEAm+R_࿽~^_ۯ/_~~˯US! 2HO endstream endobj 28 0 obj <>stream x33V0P0Vе0P032R @c$r*Z, j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j Jd>EfO(kh47Kڗ_J߿qyĎWߔz8`AL0+Q endstream endobj 23 0 obj <>stream x333Q0P0V53P03T02QH1230!U`jaT02,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-XBZ#EN/S..g簛W]-?%=M~֯]m]nf[)e;yy02pz*r[Y[_ endstream endobj 18 0 obj <>stream x37гT0P0Rе0P02S , 1s  @Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAm,Vz{G endstream endobj 13 0 obj <>stream x353S0B]s#S#]CC.=C(U7 *@<=}JJSÁ=K4X.}7}gg7 7Fhs~Nin^1Pڂk!_\Poz0H>"z _AS! 1=R endstream endobj 69 0 obj <>stream x36гP0B]sc#K#C.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O=ٯ?/zn,^.WO@.nEQ endstream endobj 64 0 obj <>stream x353V0P0T5T05P0VH1230 !U`biT032@X,ɥPRTʥTɥTƥ\r;;66 @ܼb;;.O }\*M-r͇j_"濗jk-:ӖUPG⠎† L9$_td^OS_ߊ>̙s%Nv $\=8M endstream endobj 59 0 obj <>stream x3P0Pе0V54R  1s , `= ,ɥPRTʥTʥ`ɥ`ȥ 45KM w)+갳tQP~04ppz*rg% endstream endobj 54 0 obj <>stream x373T0P0Q5T0P5TH123!U`fbT02@.'BIQi*~8P%PS!K4X.}7}gg7 7Fhs~Nin^1Pڊ3&q{?/.-<7]۷"#AS! IN endstream endobj 49 0 obj <>stream x353T0P0T53U01S5TH123!U`bjT032 ,ɥPRTʥTɥTƥ`ȥ 45KM ƥSW bg颠iR>stream x33ֳP0P0V5P03T0TH1230 !U`jaT02,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-HhR1?"|JU /2s29\?ʲ6={{t 8s~sHDl S endstream endobj 39 0 obj <>stream x3P0P53R55S0V5QH1230 !U`fjT052kf`i'O.}O_T.pZ.}B.}gC.}h\nn@n.P9?47ΎEAmcL[/Ta~5 &T7_ݿ;VÜ9{$T7(Xv $" "901(pz*rGL endstream endobj 34 0 obj <>stream x33W0P0Sе0P022S , 1s  - @u,'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠?>AS! > endstream endobj 29 0 obj <>stream x333R0P0R53P"cC.=C ɹ\ `A3c  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1PY<'y>h|"| 8eRr&yo{^w=o7KO]NLlmst +KQ endstream endobj 24 0 obj <>stream x33V0P0S5 F& )\z@Q 1s L- &@u%<=}JJSÁ*=ʸ ]r;;66 @ܼb;;.O+OJǾ~qHf7~{{[=8_v_}x<" ,\ \[! endstream endobj 19 0 obj <>stream x333U0P0Sе@f! g$r*, @ @ N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1Pfq߿\-[o:ַqp \ \O endstream endobj 14 0 obj <>stream x353S0P0R57R05T0TH1230 !U`biT072,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(- !~Ǘ/_h|G/_Uo[.!Q/:eq<Y[o;cz#Qfap`rTZ endstream endobj 70 0 obj <>stream x323Q0P0Uе0P042S , 1s  @)Y@I'O.}O_T.pJ.}2.}g %hj,`cﭠ q)+jtQP8@VCB F= endstream endobj 65 0 obj <>stream x333R0P04P5P0S , 1s , XXɓKW4K?KK)YK%hl,`cﭠ q)+jtQP[ 2=F_ >! endstream endobj 60 0 obj <>stream x3P0P53Rе0,R  1s ̌ f`M ,ɥPRTʥT˥Tȥ`ȥ 47KM V8qy('r9Ħ5:o3{Id_ȽYe=P~.02pz*rI endstream endobj 55 0 obj <>stream x3P0Pе0V57,R  1s , f&`M D<=}JJSÁj=  ]r;;66 @ܼb;;.O8-C?oֶ! WAٷ۽wˇ9$\L/q4m?bAS! 1AS endstream endobj 50 0 obj <>stream x333T0P0R5P05S0TH123 !U`jbT02,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-@EN /8k} ok vE09|B#|¹d1(3ܲjv,6'Vۜ95nNM8t .WO@.Yz endstream endobj 45 0 obj <>stream x33V0P0U53W04Q5TH1230!U`iS032L,ɥPRTʥ`ɥTť`ȥ 43KM ťSW`ig颠?pS! Q8 endstream endobj 40 0 obj <>stream x3P0P5bScc] C.=C0ɹ\ f`AS&6'BIQi*~8P-P!S!K4X.}7}gg7 7F[A(㜟SW bg颠30bo~WTT7g´Rg`rT9W endstream endobj 35 0 obj <>stream x333Q0B]SK 2PH1230 ɹ\@i RN\ %E\@i.}0`ȥ 43KM V8qy(m2^+~`z۴/s7߱[n~0]7wUگ/߾~կp03M endstream endobj 30 0 obj <>stream x333R0P0T53P05W0VH1230 !U`jfT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-,$yAƇ[|}^&uuC 1B's&."$a'=Ƕ\{a~&mm Ov endstream endobj 25 0 obj <>stream x363R0P0T57Q06U0VH1230 !U`lbT072 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-H:k9eC\=^BI% endstream endobj 20 0 obj <>stream x313T0P0S53P012S @@c$r*4i2K:yr{*rUr{Up;8+rDMwwvvrllt29y@-vv\. j;Wp~?Y_ƹS! B8 endstream endobj 15 0 obj <>stream x353S0P0R57R05R0TH1230 !U`j`T072,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-QCI(_pܫ͏_?\[[on8ͣ1:"17G\G-ۗ˾~@qջز#Q?;;G`ásX\=ÃZ endstream endobj 9 0 obj <>stream x353S0P0V57R05R0TH1230 !U`biT072@,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-a/8pܫ6fڭp;{c_o&زMۆCnDlHK\[ endstream endobj 71 0 obj <>stream x33T0P0Q5T052S @@c$r*XL-  N\ %E\@\@e\N \.@Sc݀}o]s~Nin^1Pw}TH'w=o5anL \ \uH endstream endobj 66 0 obj <>stream x333U0P0Q5T0P02QH1230!U`jbT02@.'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠qAnDm@_ct?~we_UW~{Ww[]߲#Q/oٷm}GL B ` endstream endobj 61 0 obj <>stream x3P0P0Vе0T072R @c$r*,L c j2K:yr{*rUr{q;8+9.@Sc݀}o]s~Nin^1P5l+y.d4h>akK9~;M_ݛY'G]?k.dۡ76Enݺmá<:N \ \_ endstream endobj 56 0 obj <>stream x3P0P53R55U0V5VH1230 !U`fjT052k A'BIQi*~8P-P!S!K4X.}7}gg7 7F[A(㜟SW bg颠Ṙ[s>stream x31V0P5T5P01R0TH1230 !U`blT037i&`Y'O.}O_T.pR.}:.}gC.}h\nn@n7 .}ܼb;;.OEl3?~{pG_~˽u{e߽wotR) endstream endobj 46 0 obj <>stream x3гT0P0T5T02R @c$r*L C j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j Z6 ;kc~ΛlSy*j8H}9!NzMm9:ͬ \ \YH= endstream endobj 41 0 obj <>stream x3P0P53R55U02Q5QH1230!U`afT054`i'O.}O_T.pZ.}B.}g  47KM V8qy(-T#"|YqM>dD]߂}i}񫷯ߗ]GE<)ڪCt]׉s;гAS! DWD endstream endobj 36 0 obj <>stream x3P0Pе0V53LR  1s , f . fvU()*M*w pV0w˥{+esJsZ<]6.[pH=k@ep`rTaB endstream endobj 31 0 obj <>stream x36гP0P0Uе0P022S , 1s  - @u,'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠?6𓉷_n=|?=n endstream endobj 26 0 obj <>stream x333V0P0V53P01R @c$r*̌ j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j IMkVι=tٞzZ7߿QCxS?9|„D&>stream x333S0P0V53P032R @c$r*̌ j2K:yr{*rUr{q;8+9.@Sc݀}o]s~Nin^1PڂK<7YEt5$q(|"'|X;/uU_w_={ϭջ>Qmn֭m8tG6AS! N endstream endobj 16 0 obj <>stream x353S0PT57R06S5TH1230!U`dnT072,,ɥPRTʥTɥTƥ\r;;66@۸sJsZ<]?c¯Ç~CB (?? endstream endobj 11 0 obj <>stream x32U0P0W54T0R )\z@Q 1s  @9u%<=}JJSÁ*=ʸ ]ry(DŽ\ \#v endstream endobj 72 0 obj <>stream x3Q0P0Q5T02S , 1s - Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAmqz3Le8r}[opGǙCBS! DC\ endstream endobj 67 0 obj <>stream x3гP0P0T5T05U0VH1230 !U`jbT032 ,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-,$uC[ u0_0RK_~Aoc_Vwm7L;;lNصki.xĠNf endstream endobj 62 0 obj <>stream x323S0P0Uе0P042S , 1s  @)Y@I'O.}O_T.pJ.}2.}gC.}h\nn@n.P9?47ΎEAm|B = endstream endobj 57 0 obj <>stream x3P0P53R55P0V5QH1230 !U`fjT013k@1'BIQi*~8P-P!S!K4X.}7}gg7 7F[A(㜟SW bg颠`UcAهU_޿7%/eu__vݥv[o'{vs1(0qz*rR& endstream endobj 52 0 obj <>stream x323R0B]3C#cCC.=C U6 *@<=}JJSÁ= ]fr;;66 @ܼb;;.O3_+I$}S! C? endstream endobj 47 0 obj <>stream x313Q0P0R5T01R0TH1230 !U`b`T01,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-xbࡤЖ}NF|_嶮:a^堎1]Aƞ+/ڀFgs?mw߮[Gs08pz*rh@ endstream endobj 42 0 obj <>stream x3P0P53R5T02QеPH1230!U`afT054`i'O.}O_T.pZ.}B.}g  47KM V8qy('W xn8bWK{/W_Vޥ.`absV_;MGGB-l#B IL endstream endobj 37 0 obj <>stream x3P0Pе0V55R  1s , &`M D<=}JJSÁj=  ]r;;66 @ܼb;;.Os\t!*ˮ뿮ߌ}EE#B Rm8 endstream endobj 32 0 obj <>stream x3Q0P0U53P42S @, 1s , @u,'BIQi*~8P%PS!K4X.}7}gg7 7F[A(㜟SW bg颠s)[e} )%;[&}`#&.WO@.wV endstream endobj 27 0 obj <>stream x333U0P0S5@f!0Fr.WXPL4%<=}JJSÁ*=* ]r;;66 @ܼb;;.O+-Σzo砸[V]oS8H endstream endobj 22 0 obj <>stream x333U0P0S5T03T0VH1230 !U`jjT032̀,ɥPRTʥTɥTƥ`ȥ 45KM V8qy(-$q(/jekX_ت_~8.WO@.\H endstream endobj 17 0 obj <>stream x353S0P0R57T052R @c$r*̍ # j2K:yr{*rUr{q;8+rDMwwvvrllt29y@-vv\. j H4 T{½&U/w˾[w8h6p6z۸Ox=?, \ \zL endstream endobj 12 0 obj <>stream x353S0P0R57R0R )\z@Q 1s L @u%<=}JJSÁ*=ʸK4X.}7}gg7 7Fhs~Nin^1Po6v߷߻wjć>Qcc=۷_m >uanM\ \ \Q endstream endobj 76 0 obj <>stream x]1n@E{7f`l4.I.@KC)>)Ryޛ6f.VnXK}.fu|ֆ uZ?οx:uzx<>/FontMatrix[1 0 0 1 0 0]/FontBBox[0 0 86 84]/FirstChar 0/LastChar 63/Widths[ 55.6 25 55.6 55.6 55.6 55.6 55.6 55.6 70.9 66.5 43.1 67.6 67.5 67.4 68.3 37.2 62.3 67.5 68.3 64.2 61.2 30.8 98.4 59.6 29.7 60.4 0 0 0 0 0 0 0 0 63.8 19.3 48.9 44.4 50.1 50.1 60.1 43 25.2 48 73.1 0 0 0 0 0 0 78 23.6 59.8 54.3 61.2 61.5 58.8 59.1 30.8 24.4 59.1 89.4 52.4] /Subtype/Type3>> endobj 77 0 obj <> endobj 78 0 obj <>stream 2024-05-13T15:54:31+02:00 2024-05-13T15:54:31+02:00 GPL Ghostscript 950 (ps2write) Untitled endstream endobj 2 0 obj <>endobj xref 0 79 0000000000 65535 f 0000002734 00000 n 0000023250 00000 n 0000002675 00000 n 0000002524 00000 n 0000000228 00000 n 0000002504 00000 n 0000002799 00000 n 0000002840 00000 n 0000012628 00000 n 0000020318 00000 n 0000016199 00000 n 0000019457 00000 n 0000006080 00000 n 0000009214 00000 n 0000012318 00000 n 0000015971 00000 n 0000019175 00000 n 0000005862 00000 n 0000008977 00000 n 0000012088 00000 n 0000015680 00000 n 0000018933 00000 n 0000005541 00000 n 0000008689 00000 n 0000011851 00000 n 0000015379 00000 n 0000018700 00000 n 0000005255 00000 n 0000008400 00000 n 0000011544 00000 n 0000015162 00000 n 0000018449 00000 n 0000004991 00000 n 0000008192 00000 n 0000011287 00000 n 0000014942 00000 n 0000018209 00000 n 0000004763 00000 n 0000007898 00000 n 0000011041 00000 n 0000014626 00000 n 0000017923 00000 n 0000004528 00000 n 0000007600 00000 n 0000010830 00000 n 0000014339 00000 n 0000017639 00000 n 0000004303 00000 n 0000007317 00000 n 0000010507 00000 n 0000014060 00000 n 0000017420 00000 n 0000004039 00000 n 0000007066 00000 n 0000010242 00000 n 0000013757 00000 n 0000017128 00000 n 0000003794 00000 n 0000006857 00000 n 0000009967 00000 n 0000013441 00000 n 0000016919 00000 n 0000003483 00000 n 0000006554 00000 n 0000009740 00000 n 0000013145 00000 n 0000016630 00000 n 0000003239 00000 n 0000006331 00000 n 0000009523 00000 n 0000012907 00000 n 0000016373 00000 n 0000002954 00000 n 0000002883 00000 n 0000002922 00000 n 0000019745 00000 n 0000021517 00000 n 0000021817 00000 n trailer << /Size 79 /Root 1 0 R /Info 2 0 R /ID [<0FFB7FFB700F8FD461F532CD2E5012DB><0FFB7FFB700F8FD461F532CD2E5012DB>] >> startxref 23416 %%EOF queueing/inst/0000775000175000017500000000000014620417652013246 5ustar morenomorenoqueueing/inst/qncsaba.m0000664000175000017500000001101114620404470015020 0ustar morenomoreno## Copyright (C) 2012, 2016, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsaba (@var{N}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsaba (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsaba (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsaba (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## ## @cindex bounds, asymptotic ## @cindex asymptotic bounds ## @cindex closed network, single class ## ## Compute Asymptotic Bounds for the system throughput and response ## time of closed, single-class networks with @math{K} service ## centers. ## ## Single-server and infinite-server nodes are supported. ## Multiple-server nodes and general load-dependent servers are not ## supported. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## number of requests in the system (scalar, @code{@var{N}>0}). ## ## @item @var{D}(k) ## service demand at center @math{k} ## (@code{@var{D}(k) @geq{} 0}). ## ## @item @var{S}(k) ## mean service time at center @math{k} ## (@code{@var{S}(k) @geq{} 0}). ## ## @item @var{V}(k) ## average number of visits to center ## @math{k} (@code{@var{V}(k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k} ## (if @var{m} is a scalar, all centers have that number of servers). If ## @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); ## if @code{@var{m}(k) = 1}, center @math{k} is a M/M/1-FCFS server. ## This function does not support multiple-server nodes. Default ## is 1. ## ## @item @var{Z} ## External delay (scalar, @code{@var{Z} @geq{} 0}). Default is 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl} ## @itemx @var{Xu} ## Lower and upper bounds on the system throughput. ## ## @item @var{Rl} ## @itemx @var{Ru} ## Lower and upper bounds on the system response time. ## ## @end table ## ## @seealso{qncmaba} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [Xl Xu Rl Ru] = qncsaba( varargin ) #N, S, V, m, Z ) if (nargin<2 || nargin>5) print_usage(); endif [err N S V m Z] = qncschkparam( varargin{:} ); isempty(err) || error(err); all(m<=1) || ... error( "multiple server nodes are not supported" ); D = S.*V; Dtot_single = sum(D(m==1)); # total demand at single-server nodes Dtot_delay = sum(D(m<1)); # total demand at IS nodes Dtot = sum(D); # total demand Dmax = max(D); # max demand Xl = N/(N*Dtot_single + Dtot_delay + Z); Xu = min( N/(Dtot+Z), 1/Dmax ); Rl = max( Dtot, N*Dmax - Z ); Ru = N*Dtot_single + Dtot_delay; endfunction %!test %! fail("qncsaba(-1,0)", "N must be"); %! fail("qncsaba(1,[])", "nonempty"); %! fail("qncsaba(1,[-1 2])", "nonnegative"); %! fail("qncsaba(1,[1 2],[1 2 3])", "incompatible size"); %! fail("qncsaba(1,[1 2 3],[1 2 -1])", "nonnegative"); %! fail("qncsaba(1,[1 2 3],[1 2 3],[1 2])", "incompatible size"); %! fail("qncsaba(1,[1 2 3],[1 2 3],[1 2 1])", "not supported"); %! fail("qncsaba(1,[1 2 3],[1 2 3],[1 1 1],-1)", "nonnegative"); %! fail("qncsaba(1,[1 2 3],[1 2 3],1,[0 0])", "scalar"); ## Example 9.6 p. 913 Bolch et al. %!test %! N = 20; %! S = [ 4.6*2 8 ]; %! Z = 120; %! [X_l X_u R_l R_u] = qncsaba(N, S, ones(size(S)), ones(size(S)), Z); %! assert( [X_u R_l], [0.109 64], 1e-3 ); %!test %! S = [1 0.8 1.2 0.5]; %! V = [1 2 2 1]; %! D = S .* V; %! N = 50; %! tol = 1e-7; # compensate for numerical inaccuracies %! for n=1:N %! [U R Q X] = qncsmva(n, S, V); %! Xs = X(1)/V(1); %! Rs = dot(R,V); %! [Xl Xu Rl Ru] = qncsaba( n, D ); %! assert( Xl <= Xs+tol ); %! assert( Xu >= Xs-tol ); %! assert( Rl <= Rs+tol ); %! assert( Ru >= Rs-tol ); %! endfor queueing/inst/erlangc.m0000664000175000017500000000634214620404470015036 0ustar morenomoreno## Copyright (C) 2014, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{C} =} erlangc (@var{A}, @var{m}) ## ## @cindex Erlang-C formula ## ## Compute the steady-state probability of delay in the Erlang delay model. ## ## The Erlang-C formula @math{E_C(A, m)} gives the probability that an ## open queueing system with @math{m} identical servers, infinite ## wating space, arrival rate @math{\lambda}, individual service rate ## @math{\mu} and offered load @math{A = \lambda / \mu} has all the ## servers busy. This is the waiting probability in an ## @math{M/M/m/\infty} system with @math{m} servers and an infinite ## queue. ## ## @tex ## @math{E_C(A, m)} is defined as: ## ## $$ ## E_C(A, m) = \displaystyle{ {A^m \over m!} {1 \over 1-\rho} \left( \sum_{k=0}^{m-1} {A^k \over k!} + {A^m \over m!} {1 \over 1 - \rho} \right) ^{-1}} ## $$ ## ## where @math{\rho = A / m = \lambda / (m \mu)}. ## @end tex ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{A} ## Offered load. @math{A = \lambda / \mu} where ## @math{\lambda} is the mean arrival rate and @math{\mu} the mean ## service rate of each individual server (real, @math{0 < A < m}). ## ## @item @var{m} ## Number of identical servers (integer, @math{m @geq{} 1}). ## Default @math{m = 1} ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{B} ## The value @math{E_C(A, m)} ## ## @end table ## ## @var{A} or @var{m} can be vectors, and in this case, the results will ## be vectors as well. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Zeng, @cite{Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function}, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296 ## @end itemize ## ## @seealso{erlangb,engset,qsmmm} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function C = erlangc(A, m) if ( nargin < 1 || nargin > 2 ) print_usage(); endif ( isnumeric(A) && all(A(:) > 0) ) || error("A must be positive"); if ( nargin == 1 ) m = 1; else ( isnumeric(m) && all( fix(m(:)) == m(:)) && all( m(:) > 0 ) ) || error("m must be a positive integer"); endif [err A, m] = common_size(A, m); if ( err ) error("parameters are not of common size"); endif all( A(:) < m(:) ) || error("A must be < m"); rho = A ./ m; B = erlangb(A, m); C = B ./ (1 - rho .* (1 - B)); endfunction %!test %! fail("erlangc('foo',1)", "positive"); %! fail("erlangc(1,'bar')", "positive"); queueing/inst/qnopen.m0000664000175000017500000000427114620404470014722 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopen (@var{lambda}, @var{S}, @var{V}, @dots{}) ## ## @cindex open network ## ## Compute utilization, response time, average number of requests in the ## system, and throughput for open queueing networks. If @var{lambda} is ## a scalar, the network is considered a single-class QN and is solved ## using @code{qnopensingle}. If @var{lambda} is a vector, the network ## is considered as a multiclass QN and solved using @code{qnopenmulti}. ## ## @seealso{qnos, qnom} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qnopen( lambda, S, V, varargin ) if ( nargin < 3 ) print_usage(); endif if ( isscalar(lambda) ) [U R Q X] = qnos(lambda, S, V, varargin{:}); else [U R Q X] = qnom(lambda, S, V, varargin{:}); endif endfunction %!test %! # Example 34.1 p. 572 %! lambda = 3; %! V = [16 7 8]; %! S = [0.01 0.02 0.03]; %! [U R Q X] = qnopen( lambda, S, V ); %! assert( R, [0.0192 0.0345 0.107], 1e-2 ); %! assert( U, [0.48 0.42 0.72], 1e-2 ); %!test %! V = [1 1; 1 1]; %! S = [1 3; 2 4]; %! lambda = [3/19 2/19]; %! [U R Q] = qnopen(lambda, S, diag( lambda / sum(lambda) ) * V); %! assert( U(1,1), 3/19, 1e-6 ); %! assert( U(2,1), 4/19, 1e-6 ); %! assert( R(1,1), 19/12, 1e-6 ); %! assert( R(1,2), 57/2, 1e-6 ); %! assert( Q(1,1), .25, 1e-6 ); queueing/inst/dtmc.m0000664000175000017500000001242714620404470014353 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{p} =} dtmc (@var{P}) ## @deftypefnx {Function File} {@var{p} =} dtmc (@var{P}, @var{n}, @var{p0}) ## ## @cindex Markov chain, discrete time ## @cindex discrete time Markov chain ## @cindex DTMC ## @cindex Markov chain, stationary probabilities ## @cindex Markov chain, transient probabilities ## ## Compute stationary or transient state occupancy probabilities for a discrete-time Markov chain. ## ## With a single argument, compute the stationary state occupancy ## probabilities @code{@var{p}(1), @dots{}, @var{p}(N)} for a ## discrete-time Markov chain with finite state space @math{@{1, @dots{}, ## N@}} and with @math{N \times N} transition matrix ## @var{P}. With three arguments, compute the transient state occupancy ## probabilities @code{@var{p}(1), @dots{}, @var{p}(N)} that the system is in ## state @math{i} after @var{n} steps, given initial occupancy ## probabilities @var{p0}(1), @dots{}, @var{p0}(N). ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(i,j) ## transition probabilities from state @math{i} to state @math{j}. ## @var{P} must be an @math{N \times N} irreducible stochastic matrix, ## meaning that the sum of each row must be 1 (@math{\sum_{j=1}^N ## P_{i, j} = 1}), and the rank of @var{P} must be @math{N}. ## ## @item @var{n} ## Number of transitions after which state occupancy probabilities are computed ## (scalar, @math{n @geq{} 0}) ## ## @item @var{p0}(i) ## probability that at step 0 the system is in state @math{i} (vector ## of length @math{N}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{p}(i) ## If this function is called with a single argument, @code{@var{p}(i)} ## is the steady-state probability that the system is in state @math{i}. ## If this function is called with three arguments, @code{@var{p}(i)} ## is the probability that the system is in state @math{i} ## after @var{n} transitions, given the probabilities ## @code{@var{p0}(i)} that the initial state is @math{i}. ## ## @end table ## ## @seealso{ctmc} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function p = dtmc( P, n, p0 ) if ( nargin != 1 && nargin != 3 ) print_usage(); endif [N err] = dtmcchkP(P); ( N>0 ) || ... error( err ); if ( nargin == 1 ) # steady-state analysis A = P-eye(N); A(:,N) = 1; # add normalization condition rank( A ) == N || ... warning( "dtmc(): P is reducible" ); b = [ zeros(1,N-1) 1 ]; p = b/A; else # transient analysis ( isscalar(n) && n>=0 ) || ... error( "n must be >=0" ); ( isvector(p0) && length(p0) == N && all(p0>=0) && abs(sum(p0)-1.0). ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{V} =} qnosvisits (@var{P}, @var{lambda}) ## ## Compute the average number of visits to the service centers of a single ## class open Queueing Network with @math{K} service centers. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(i,j) ## is the probability that a request which completed service at center ## @math{i} is routed to center @math{j} (@math{K \times K} matrix). ## ## @item @var{lambda}(k) ## external arrival rate to center @math{k}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{V}(k) ## average number of visits to server @math{k}. ## ## @end table ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function V = qnosvisits( P, lambda ) if ( nargin != 2 ) print_usage(); endif issquare(P) || ... error("P must be a square matrix"); K = rows(P); all(P(:)>=0) && all( sum(P,2)<=1+1e-5 ) || ... error( "invalid transition probability matrix P" ); ( isvector(lambda) && length(lambda) == K ) || ... error( "lambda must be a vector with %d elements", K ); all( lambda>= 0 ) || ... error( "lambda contains negative values" ); lambda = lambda(:)'; V = zeros(size(P)); A = eye(K)-P; b = lambda / sum(lambda); V = b/A; ## Make sure that no negative values appear (sometimes, numerical ## errors produce tiny negative values instead of zeros) V = max(0,V); endfunction %!test %! fail( "qnosvisits([0 .5; .5 0],[0 -1])", "contains negative" ); %! fail( "qnosvisits([1 1 1; 1 1 1], [1 1])", "square" ); %!test %! %! ## Open, single class network %! %! P = [0 0.2 0.5; 1 0 0; 1 0 0]; %! lambda = [ 0.1 0.3 0.2 ]; %! V = qnosvisits(P,lambda); %! assert( V*P+lambda/sum(lambda),V,1e-5 ); %!demo %! p = 0.3; %! lambda = 1.2 %! P = [0 0.3 0.5; 1 0 0; 1 0 0]; %! V = qnosvisits(P,[1.2 0 0]) %!demo %! P = [ 0 0.4 0.6 0; ... %! 0.2 0 0.2 0.6; ... %! 0 0 0 1; ... %! 0 0 0 0 ]; %! lambda = [0.1 0 0 0.3]; %! V = qnosvisits(P,lambda); %! S = [2 1 2 1.8]; %! m = [3 1 1 2]; %! [U R Q X] = qnos( sum(lambda), S, V, m ) queueing/inst/qsmh1.m0000664000175000017500000000607314620404470014455 0ustar morenomoreno## Copyright (C) 2009 Dmitry Kolesnikov ## Copyright (C) 2012, 2016 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qsmh1 (@var{lambda}, @var{mu}, @var{alpha}) ## ## @cindex @math{M/H_m/1} system ## ## Compute utilization, response time, average number of requests and ## throughput for a @math{M/H_m/1} system. In this system, the customer ## service times have hyper-exponential distribution: ## ## @tex ## $$ B(x) = \sum_{j=1}^m \alpha_j(1-e^{-\mu_j x}),\quad x>0 $$ ## @end tex ## ## @ifnottex ## @example ## @group ## ___ m ## \ ## B(x) = > alpha(j) * (1-exp(-mu(j)*x)) x>0 ## /__ ## j=1 ## @end group ## @end example ## @end ifnottex ## ## where @math{\alpha_j} is the probability that the request is served ## at phase @math{j}, in which case the average service rate is ## @math{\mu_j}. After completing service at phase @math{j}, for ## some @math{j}, the request exits the system. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate ## ## @item @var{mu} ## @code{@var{mu}(j)} is the phase @math{j} service rate. The total ## number of phases @math{m} is @code{length(@var{mu})}. ## ## @item @var{alpha} ## @code{@var{alpha}(j)} is the probability that a request ## is served at phase @math{j}. @var{alpha} must have the same size ## as @var{mu}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U} ## Service center utilization ## ## @item @var{R} ## Service center response time ## ## @item @var{Q} ## Average number of requests in the system ## ## @item @var{X} ## Service center throughput ## ## @end table ## ## @end deftypefn ## Author: Dmitry Kolesnikov function [U R Q X p0] = qsmh1(lambda, mu, alpha) if ( nargin != 3 ) print_usage(); endif if ( size(mu) != size(alpha) ) error( "parameters are of incompatible size" ); endif [n c] = size(mu); if (!is_scalar(lambda) && (n != length(lambda)) ) error( "parameters are of incompatible size" ); endif for i=1:n avg = sum( alpha(i,:) .* (1 ./ mu(i,:)) ); m2nd = sum( alpha(i,:) .* (1 ./ (mu(i,:) .* mu(i,:))) ); if (is_scalar(lambda)) xavg = avg; x2nd = m2nd; else xavg(i) = avg; x2nd(i) = m2nd; endif endfor [U R Q X p0] = qsmg1(lambda, xavg, x2nd); endfunction queueing/inst/qncmaba.m0000664000175000017500000001512614620404470015025 0ustar morenomoreno## Copyright (C) 2012, 2016, 2018, 2020, 2022 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmaba (@var{N}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmaba (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmaba (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmaba (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## ## @cindex bounds, asymptotic ## @cindex asymptotic bounds ## @cindex closed network ## @cindex multiclass network, closed ## @cindex closed multiclass network ## ## Compute Asymptotic Bounds for closed, multiclass networks ## with @math{K} service centers and @math{C} customer classes. ## Single-server and infinite-server nodes are supported. ## Multiple-server nodes and general load-dependent servers are not ## supported. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N}(c) ## number of class @math{c} requests in the system ## (vector of length @math{C}, @code{@var{N}(c) @geq{} 0}). ## ## @item @var{D}(c, k) ## class @math{c} service demand ## at center @math{k} (@math{C \times K} matrix, @code{@var{D}(c,k) @geq{} 0}). ## ## @item @var{S}(c, k) ## mean service time of class @math{c} ## requests at center @math{k} (@math{C \times K} matrix, @code{@var{S}(c,k) @geq{} 0}). ## ## @item @var{V}(c,k) ## average number of visits of class @math{c} ## requests to center @math{k} (@math{C \times K} matrix, @code{@var{V}(c,k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k} ## (if @var{m} is a scalar, all centers have that number of servers). If ## @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); ## if @code{@var{m}(k) = 1}, center @math{k} is a M/M/1-FCFS server. ## This function does not support multiple-server nodes. Default ## is 1. ## ## @item @var{Z}(c) ## class @math{c} external delay ## (vector of length @math{C}, @code{@var{Z}(c) @geq{} 0}). Default is 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl}(c) ## @itemx @var{Xu}(c) ## Lower and upper bounds for class @math{c} throughput. ## ## @item @var{Rl}(c) ## @itemx @var{Ru}(c) ## Lower and upper bounds for class @math{c} response time. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth ## C. Sevcik, @cite{Quantitative System Performance: Computer System ## Analysis Using Queueing Network Models}, Prentice Hall, ## 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In ## particular, see section 5.2 ("Asymptotic Bounds"). ## @end itemize ## ## @seealso{qncsaba} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [Xl Xu Rl Ru] = qncmaba( varargin ) if ( nargin<2 || nargin>5 ) print_usage(); endif [err N S V m Z] = qncmchkparam( varargin{:} ); isempty(err) || error(err); all(m<=1) || ... error("Multiple-server nodes are not supported"); if ( sum(N) == 0 ) # handle trivial case of empty network Xl = Xu = Rl = Ru = zeros(size(S)); else D = S .* V; Dc_single = sum(D(:,(m==1)),2)'; # class c demand on single-server nodes Dc_delay = sum(D(:,(m<1)),2)'; # class c demand on delay centers Dc = sum(D,2)'; # class c total demand Dcmax = max(D,[],2)'; # maximum class c demand at any server Xl = N ./ ( dot(N,Dc_single) + Dc_delay + Z); Xu = min( 1./Dcmax, N ./ (Dc + Z) ); Rl = N ./ Xu - Z; Ru = N ./ Xl - Z; endif endfunction %!test %! fail("qncmaba([],[])", "nonempty"); %! fail("qncmaba([1 0], [1 2 3])", "2 rows"); %! fail("qncmaba([1 0], [1 2 3; 4 5 -1])", "nonnegative"); %! fail("qncmaba([1 2], [1 2 3; 4 5 6], [1 2 3])", "2 x 3"); %! fail("qncmaba([1 2], [1 2 3; 4 5 6], [1 2 3; 4 5 -1])", "nonnegative"); %! fail("qncmaba([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1])", "3 elements"); %! fail("qncmaba([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1 2])", "not supported"); %! fail("qncmaba([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1 -1],[1 2 3])", "2 elements"); %! fail("qncmaba([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1 -1],[1 -2])", "nonnegative"); %!test %! [Xl Xu Rl Ru] = qncmaba([0 0], [1 2 3; 1 2 3]); %! assert( all(Xl(:) == 0) ); %! assert( all(Xu(:) == 0) ); %! assert( all(Rl(:) == 0) ); %! assert( all(Ru(:) == 0) ); %!test %! S = [10 7 5 4; ... %! 5 2 4 6]; %! NN=20; %! Xl = Xu = Rl = Ru = Xmva = Rmva = zeros(NN,2); %! for n=1:NN %! N=[n,10]; %! [a b c d] = qncmaba(N,S); %! Xl(n,:) = a; Xu(n,:) = b; Rl(n,:) = c; Ru(n,:) = d; %! [U R Q X] = qncmmva(N,S,ones(size(S))); %! Xmva(n,:) = X(:,1)'; Rmva(n,:) = sum(R,2)'; %! endfor %! assert( all(Xl <= Xmva) ); %! assert( all(Xu >= Xmva) ); %! assert( all(Rl <= Rmva) ); %! assert( all(Xu >= Xmva) ); %!demo %! S = [10 7 5 4; ... %! 5 2 4 6]; %! NN=20; %! Xl = Xu = Rl = Ru = Xmva = Rmva = zeros(NN,2); %! for n=1:NN %! N=[n,10]; %! [a b c d] = qncmaba(N,S); %! Xl(n,:) = a; Xu(n,:) = b; Rl(n,:) = c; Ru(n,:) = d; %! [U R Q X] = qncmmva(N,S,ones(size(S))); %! Xmva(n,:) = X(:,1)'; Rmva(n,:) = sum(R,2)'; %! endfor %! subplot(2,2,1); %! plot(1:NN,Xl(:,1), 1:NN,Xu(:,1), 1:NN,Xmva(:,1), ";MVA;", "linewidth", 2); %! ylim([0, 0.2]); %! title("Class 1 throughput"); legend("boxoff"); %! subplot(2,2,2); %! plot(1:NN,Xl(:,2), 1:NN,Xu(:,2), 1:NN,Xmva(:,2), ";MVA;", "linewidth", 2); %! ylim([0, 0.2]); %! title("Class 2 throughput"); legend("boxoff"); %! subplot(2,2,3); %! plot(1:NN,Rl(:,1), 1:NN,Ru(:,1), 1:NN,Rmva(:,1), ";MVA;", "linewidth", 2); %! ylim([0, 700]); %! title("Class 1 response time"); legend("location", "northwest"); legend("boxoff"); %! subplot(2,2,4); %! plot(1:NN,Rl(:,2), 1:NN,Ru(:,2), 1:NN,Rmva(:,2), ";MVA;", "linewidth", 2); %! ylim([0, 700]); %! title("Class 2 response time"); legend("location", "northwest"); legend("boxoff"); queueing/inst/dtmcbd.m0000664000175000017500000000715314620404470014661 0ustar morenomoreno## Copyright (C) 2012, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{P} =} dtmcbd (@var{b}, @var{d}) ## ## @cindex Markov chain, discrete time ## @cindex DTMC ## @cindex discrete time Markov chain ## @cindex birth-death process, DTMC ## ## Returns the transition probability matrix @math{P} for a discrete ## birth-death process over state space @math{@{1, @dots{}, N@}}. ## For each @math{i=1, @dots{}, (N-1)}, ## @code{@var{b}(i)} is the transition probability from state ## @math{i} to @math{(i+1)}, and @code{@var{d}(i)} is the transition ## probability from state @math{(i+1)} to @math{i}. ## ## Matrix @math{\bf P} is defined as: ## ## @tex ## $$ \pmatrix{ (1-\lambda_1) & \lambda_1 & & & & \cr ## \mu_1 & (1 - \mu_1 - \lambda_2) & \lambda_2 & & \cr ## & \mu_2 & (1 - \mu_2 - \lambda_3) & \lambda_3 & & \cr ## \cr ## & & \ddots & \ddots & \ddots & & \cr ## \cr ## & & & \mu_{N-2} & (1 - \mu_{N-2}-\lambda_{N-1}) & \lambda_{N-1} \cr ## & & & & \mu_{N-1} & (1-\mu_{N-1}) } ## $$ ## @end tex ## @ifnottex ## @example ## @group ## / \ ## | 1-b(1) b(1) | ## | d(1) (1-d(1)-b(2)) b(2) | ## | d(2) (1-d(2)-b(3)) b(3) | ## | | ## | ... ... ... | ## | | ## | d(N-2) (1-d(N-2)-b(N-1)) b(N-1) | ## | d(N-1) 1-d(N-1) | ## \ / ## @end group ## @end example ## @end ifnottex ## ## @noindent where @math{\lambda_i} and @math{\mu_i} are the birth and ## death probabilities, respectively. ## ## @seealso{ctmcbd} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function P = dtmcbd( b, d ) if ( nargin != 2 ) print_usage(); endif ( isvector( b ) && isvector( d ) ) || ... error( "birht and death must be vectors" ); b = b(:); # make b a column vector d = d(:); # make d a column vector size_equal( b, d ) || ... error( "birth and death vectors must have the same length" ); all( b >= 0 ) || ... error( "birth probabilities must be >= 0" ); all( d >= 0 ) || ... error( "death probabilities must be >= 0" ); all( ([b; 0] + [0; d]) <= 1 ) || ... error( "d(i)+b(i+1) must be <= 1"); P = diag( b, 1 ) + diag( d, -1 ); P += diag( 1-sum(P,2) ); endfunction %!test %! birth = [.5 .5 .3]; %! death = [.6 .2 .3]; %! fail("dtmcbd(birth,death)","must be"); %!demo %! birth = [ .2 .3 .4 ]; %! death = [ .1 .2 .3 ]; %! P = dtmcbd( birth, death ); %! disp(P) queueing/inst/dtmcmtta.m0000664000175000017500000001710214620404470015234 0ustar morenomoreno## Copyright (C) 2012, 2014, 2016, 2018, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{t} @var{N} @var{B}] =} dtmcmtta (@var{P}) ## @deftypefnx {Function File} {[@var{t} @var{N} @var{B}] =} dtmcmtta (@var{P}, @var{p0}) ## ## @cindex mean time to absorption, DTMC ## @cindex absorption probabilities, DTMC ## @cindex fundamental matrix ## @cindex DTMC ## @cindex discrete time Markov chain ## @cindex Markov chain, discrete time ## ## Compute the expected number of steps before absorption for a ## DTMC with state space @math{@{1, @dots{}, N@}} ## and transition probability matrix @var{P}. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(i,j) ## @math{N \times N} transition probability matrix. ## @code{@var{P}(i,j)} is the transition probability from state ## @math{i} to state @math{j}. ## ## @item @var{p0}(i) ## Initial state occupancy probabilities (vector of length @math{N}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{t} ## @itemx @var{t}(i) ## When called with a single argument, @var{t} is a vector of length ## @math{N} such that @code{@var{t}(i)} is the expected number of steps ## before being absorbed in any absorbing state, starting from state ## @math{i}; if @math{i} is absorbing, @code{@var{t}(i) = 0}. When ## called with two arguments, @var{t} is a scalar, and represents the ## expected number of steps before absorption, starting from the initial ## state occupancy probability @var{p0}. ## ## @item @var{N}(i) ## @itemx @var{N}(i,j) ## When called with a single argument, @var{N} is the @math{N \times N} ## fundamental matrix for @var{P}. @code{@var{N}(i,j)} is the expected ## number of visits to transient state @var{j} before absorption, if the ## system started in transient state @var{i}. The initial state is counted ## if @math{i = j}. When called with two arguments, @var{N} is a vector ## of length @math{N} such that @code{@var{N}(j)} is the expected number ## of visits to transient state @var{j} before absorption, given initial ## state occupancy probability @var{P0}. ## ## @item @var{B}(i) ## @itemx @var{B}(i,j) ## When called with a single argument, @var{B} is a @math{N \times N} ## matrix where @code{@var{B}(i,j)} is the probability of being ## absorbed in state @math{j}, starting from transient state @math{i}; ## if @math{j} is not absorbing, @code{@var{B}(i,j) = 0}; if @math{i} ## is absorbing, @code{@var{B}(i,i) = 1} and @code{@var{B}(i,j) = 0} ## for all @math{i \neq j}. When called with two arguments, @var{B} is ## a vector of length @math{N} where @code{@var{B}(j)} is the ## probability of being absorbed in state @var{j}, given initial state ## occupancy probabilities @var{p0}. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item Grinstead, Charles M.; Snell, J. Laurie (July ## 1997). @cite{Introduction to Probability}, Ch. 11: Markov ## Chains. American Mathematical Society. ISBN 978-0821807491. ## @end itemize ## ## @seealso{ctmcmtta} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [t N B] = dtmcmtta( P, p0 ) persistent epsilon = 10*eps; if ( nargin < 1 || nargin > 2 ) print_usage(); endif [K err] = dtmcchkP(P); (K>0) || ... error(err); if ( nargin == 2 ) ( isvector(p0) && length(p0) == K && all(p0>=0) && abs(sum(p0)-1.0). ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{V} =} qncsvisits (@var{P}) ## @deftypefnx {Function File} {@var{V} =} qncsvisits (@var{P}, @var{r}) ## ## Compute the mean number of visits to the service centers of a ## single class, closed network with @math{K} service centers. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(i,j) ## probability that a request which completed service at center ## @math{i} is routed to center @math{j} (@math{K \times K} matrix). ## For closed networks it must hold that @code{sum(@var{P},2)==1}. The ## routing graph must be strongly connected, meaning that each node ## must be reachable from every other node. ## ## @item @var{r} ## Index of the reference station, @math{r \in @{1, @dots{}, K@}}; ## Default @code{@var{r}=1}. The traffic equations are solved by ## imposing the condition @code{@var{V}(r) = 1}. A request returning to ## the reference station completes its activity cycle. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{V}(k) ## average number of visits to service center @math{k}, assuming ## @math{r} as the reference station. ## ## @end table ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function V = qncsvisits( P, r ) if ( nargin < 1 || nargin > 2 ) print_usage(); endif issquare(P) || ... error("P must be a square matrix"); [res err] = dtmcchkP(P); (res>0) || ... error( "invalid transition probability matrix P" ); K = rows(P); if ( nargin < 2 ) r = 1; else isscalar(r) || ... error("r must be a scalar"); (r>=1 && r<=K) || ... error("r must be an integer in the range [1, %d]",K); endif V = zeros(size(P)); A = P-eye(K); b = zeros(1,K); A(:,r) = 0; A(r,r) = 1; b(r) = 1; V = b/A; ## Make sure that no negative values appear (sometimes, numerical ## errors produce tiny negative values instead of zeros) V = max(0,V); endfunction %!test %! P = [-1 0; 0 0]; %! fail( "qncsvisits(P)", "invalid" ); %! P = [1 0; 0.5 0]; %! fail( "qncsvisits(P)", "invalid" ); %! P = [1 2 3; 1 2 3]; %! fail( "qncsvisits(P)", "square" ); %! P = [0 1; 1 0]; %! fail( "qncsvisits(P,0)", "range" ); %! fail( "qncsvisits(P,3)", "range" ); %!test %! %! ## Closed, single class network %! %! P = [0 0.3 0.7; 1 0 0; 1 0 0]; %! V = qncsvisits(P); %! assert( V*P,V,1e-5 ); %! assert( V, [1 0.3 0.7], 1e-5 ); %!test %! %! ## Test tolerance of the qncsvisits() function. %! ## This test builds transition probability matrices and tries %! ## to compute the visit counts on them. %! %! for k=[5, 10, 20, 50] %! P = reshape(1:k^2, k, k); %! P = P ./ repmat(sum(P,2),1,k); %! V = qncsvisits(P); %! assert( V*P, V, 1e-5 ); %! endfor %!demo %! P = [0 0.3 0.7; ... %! 1 0 0 ; ... %! 1 0 0 ]; %! V = qncsvisits(P) queueing/inst/dtmctaexps.m0000664000175000017500000000533214620404470015575 0ustar morenomoreno## Copyright (C) 2012, 2014, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{M} =} dtmctaexps (@var{P}, @var{n}, @var{p0}) ## @deftypefnx {Function File} {@var{M} =} dtmctaexps (@var{P}, @var{p0}) ## ## @cindex time-alveraged sojourn time, DTMC ## @cindex discrete time Markov chain ## @cindex Markov chain, discrete time ## @cindex DTMC ## ## Compute the @emph{time-averaged sojourn times} @code{@var{M}(i)}, ## defined as the fraction of time spent in state @math{i} during the ## first @math{n} transitions (or until absorption), assuming that the ## state occupancy probabilities at time 0 are @var{p0}. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(i,j) ## @math{N \times N} transition probability matrix. ## ## @item @var{n} ## Number of transitions during which the time-averaged expected sojourn times ## are computed (scalar, @math{@var{n} @geq{} 0}). if @math{@var{n} = 0}, ## returns @var{p0}. ## ## @item @var{p0}(i) ## Initial state occupancy probabilities (vector of length @math{N}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{M}(i) ## If this function is called with three arguments, @code{@var{M}(i)} is ## the expected fraction of steps @math{@{0, @dots{}, n@}} spent in ## state @math{i}, assuming that the state occupancy probabilities at ## time zero are @var{p0}. If this function is called with two ## arguments, @code{@var{M}(i)} is the expected fraction of steps spent ## in state @math{i} until absorption. @var{M} is a vector of length ## @math{N}. ## ## @end table ## ## @seealso{dtmcexps} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function M = dtmctaexps( P, varargin ) persistent epsilon = 10*eps; if ( nargin < 2 || nargin > 3 ) print_usage(); endif L = dtmcexps(P,varargin{:}); M = L ./ sum(L); endfunction %!test %! P = dtmcbd([1 1 1 1], [0 0 0 0]); %! p0 = [1 0 0 0 0]; %! L = dtmctaexps(P,p0); %! assert( L, [.25 .25 .25 .25 0], 10*eps ); queueing/inst/ctmcmtta.m0000664000175000017500000000756114620404470015243 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{t} =} ctmcmtta (@var{Q}, @var{p}) ## ## @cindex Markov chain, continuous time ## @cindex continuous time Markov chain ## @cindex CTMC ## @cindex mean time to absorption, CTMC ## ## Compute the Mean-Time to Absorption (MTTA) of the CTMC described by ## the infinitesimal generator matrix @var{Q}, starting from initial ## occupancy probabilities @var{p}. If there are no absorbing states, this ## function fails with an error. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{Q}(i,j) ## @math{N \times N} infinitesimal generator matrix. @code{@var{Q}(i,j)} ## is the transition rate from state @math{i} to state @math{j}, @math{i ## \neq j}. The matrix @var{Q} must satisfy the condition ## @math{\sum_{j=1}^N Q_{i,j} = 0} ## ## @item @var{p}(i) ## probability that the system is in state @math{i} ## at time 0, for each @math{i=1, @dots{}, N} ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{t} ## Mean time to absorption of the process represented by matrix @var{Q}. ## If there are no absorbing states, this function fails. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Bolch, S. Greiner, H. de Meer and ## K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and ## Performance Evaluation with Computer Science Applications}, Wiley, ## 1998. ## @end itemize ## ## @seealso{ctmcexps} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function t = ctmcmtta( Q, p ) persistent epsilon = 10*eps; if ( nargin != 2 ) print_usage(); endif [N err] = ctmcchkQ(Q); (N>0) || ... error(err); ( isvector(p) && length(p) == N && all(p>=0) && abs(sum(p)-1.0). ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{lambda}, @var{S}, @var{C}, @var{P}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{lambda}, @var{S}, @var{C}, @var{P}, @var{m}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{N}, @var{S}, @var{C}, @var{P}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{N}, @var{S}, @var{C}, @var{P}, @var{m}) ## ## @cindex closed network, single class ## @cindex open network, single class ## @cindex closed network, finite capacity ## @cindex blocking queueing network ## @cindex RS blocking ## ## Compute utilization, response time, average queue length and ## throughput for open or closed queueing networks with finite capacity ## and a single class of requests. ## Blocking type is Repetitive-Service (RS). This function explicitly ## generates and solve the underlying Markov chain, and thus might ## require a large amount of memory. ## ## More specifically, networks which can me analyzed by this ## function have the following properties: ## ## @itemize @bullet ## ## @item There exists only a single class of customers. ## ## @item The network has @math{K} service centers. Center ## @math{k \in @{1, @dots{}, K@}} ## has @math{m_k > 0} servers, and has a total (finite) capacity of ## @math{C_k \geq m_k} which includes both buffer space and servers. ## The buffer space at service center @math{k} is therefore ## @math{C_k - m_k}. ## ## @item The network can be open, with external arrival rate to ## center @math{k} equal to ## @math{\lambda_k}, or closed with fixed ## population size @math{N}. For closed networks, the population size ## @math{N} must be strictly less than the network capacity: ## @math{N < \sum_{k=1}^K C_k}. ## ## @item Average service times are load-independent. ## ## @item @math{P_{i, j}} is the probability that requests completing ## execution at center @math{i} are transferred to ## center @math{j}, @math{i \neq j}. For open networks, a request may leave the system ## from any node @math{i} with probability @math{1-\sum_{j=1}^K P_{i, j}}. ## ## @item Blocking type is Repetitive-Service (RS). Service ## center @math{j} is @emph{saturated} if the number of requests is equal ## to its capacity @math{C_j}. Under the RS blocking discipline, ## a request completing service at center @math{i} which is being ## transferred to a saturated server @math{j} is put back at the end of ## the queue of @math{i} and will receive service again. Center @math{i} ## then processes the next request in queue. External arrivals to a ## saturated servers are dropped. ## ## @end itemize ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda}(k) ## @itemx @var{N} ## If the first argument is a vector @var{lambda}, it is considered to be ## the external arrival rate @code{@var{lambda}(k) @geq{} 0} to service center ## @math{k} of an open network. If the first argument is a scalar, it is ## considered as the population size @var{N} of a closed network; in this case ## @var{N} must be strictly ## less than the network capacity: @code{@var{N} < sum(@var{C})}. ## ## @item @var{S}(k) ## average service time at service center @math{k} ## ## @item @var{C}(k) ## capacity of service center @math{k}. The capacity includes both ## the buffer and server space @code{@var{m}(k)}. Thus the buffer space is ## @code{@var{C}(k)-@var{m}(k)}. ## ## @item @var{P}(i,j) ## transition probability from service center ## @math{i} to service center @math{j}. ## ## @item @var{m}(k) ## number of servers at service center ## @math{k}. Note that @code{@var{m}(k) @geq{} @var{C}(k)} for each @var{k}. ## If @var{m} is omitted, all service centers are assumed to have a ## single server (@code{@var{m}(k) = 1} for all @math{k}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(k) ## center @math{k} utilization. ## ## @item @var{R}(k) ## response time on service center @math{k}. ## ## @item @var{Q}(k) ## average number of customers in the ## service center @math{k}, @emph{including} the request in service. ## ## @item @var{X}(k) ## throughput of service center @math{k}. ## ## @end table ## ## @strong{NOTES} ## ## The space complexity of this implementation is @math{O(\prod_{k=1}^K (C_k + 1)^2)}. The time complexity is dominated by ## the time needed to solve a linear system with @math{\prod_{k=1}^K (C_k + 1)} unknowns. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qnmarkov( x, S, C, P, m ) if ( nargin < 4 || nargin > 5 ) print_usage(); endif isvector(S) || error( "S must be a vector" ); K = length(S); # number of service centers if ( nargin < 5 ) m = ones(1,K); else size_equal(m,S) || error( "m must have the same langth as S" ); endif ( [K,K] == size(P) && all( all(P>=0)) && all(sum(P,2) <= 1)) || ... error( "P must be SxS and nonnegative" ); if ( isscalar(x) ) is_open = false; N = x; # closed network ( N < sum(C) ) || ... error( "The population size exceeds the network capacity" ); all( abs(sum(P,2)-1) < 1000*eps ) || ... error( "P for closed networks cannot have exit nodes" ); else is_open = true; lambda = x; # open network size_equal(lambda, S ) || ... error( "lambda must have the same langth as S" ); endif ( all(m > 0) && all(m <= C) ) || ... error( "Capacities C must be greater or equal than m" ); q_size = prod( C+1 ); # number of states of the system ## The infinitesimal generator matrix Q_markovmight be sparse, so it ## would be appropriate to represent it as a sparse matrix. In this ## case the UMFPACK library must be installed to solve the @math{{\bf ## A}x=b} sparse system. Since I'm not sure everyone built Octave with ## sparse matrix support, I leave Q_markov as a full matrix here. Q_markov = zeros( q_size, q_size ); cur_state = zeros(1, K); if ( is_open ) valid_populations = linspace(0, sum(C), sum(C)+1); else valid_populations = [ N ]; endif ## exit_prob(i) is the probability that a job leaves the system from node i exit_prob = 1 - sum(P,2); for n=valid_populations pop_mix = qncmpopmix( n, C ); for cur_state=pop_mix' # for each feasible configuration with n customers cur_idx = sub2cell( C, cur_state ); for i=1:K if ( is_open ) # for open networks only ## handle new external arrival to center i if ( lambda(i) > 0 && cur_state(i) < C(i) ) next_state = cur_state; next_state(i) += 1; next_idx = sub2cell( C, next_state ); Q_markov( cur_idx, next_idx ) = lambda(i); endif ## handle requests that leave the system from center i ## exit_prob = 1-sum(P(i,:)); if ( exit_prob(i) > 0 && cur_state(i) > 0 ) next_state = cur_state; next_state(i) -= 1; next_idx = sub2cell( C, next_state ); Q_markov( cur_idx, next_idx ) = min(m(i), cur_state(i))*exit_prob(i)/S(i); endif endif # end open networks only ## for both open and closed networks for j=[1:(i-1) (i+1):K] ## check whether a job can move from server i to server j!=i if ( cur_state(i) > 0 && cur_state(j) < C(j) && P(i,j) > 0 ) next_state = cur_state; next_state(i) -= 1; next_state(j) += 1; next_idx = sub2cell( C, next_state ); Q_markov( cur_idx, next_idx ) = min(m(i), cur_state(i))*P(i,j)/S(i); endif endfor endfor endfor endfor ##spy( Q_markov ); ## complete the diagonal elements of the matrix Q d = sum(Q_markov,2); Q_markov -= diag( d ); ## Solve the ctmc prob = ctmc( Q_markov ); ## Compute the average queue length p = zeros(K, max(C)+1); # p(k,i+1) = prob that there are i requests at service center k for n=valid_populations pop_mix = qncmpopmix( n, C ); for cur_state=pop_mix' cur_idx = sub2cell( C, cur_state ); for k=1:K i=cur_state(k); p(k,i+1) += prob(cur_idx); endfor endfor endfor ## We can now compute all the performance measures U = R = Q = X = zeros(1,K); for k=1:K j = [0:m(k)-1]; U(k) = 1 - sum( ( m(k) - j ) ./ m(k) .* p(k,1+j) ); ##X(k) = U(k)/S(k); j = [1:C(k)]; Q(k) = sum( j .* p(k,1+j) ); ##R(k) = Q(k)/X(k); endfor X = U./S; R = Q./X; endfunction %!test %! S = [5 2.5]; %! P = [0 1; 1 0]; %! C = [3 3]; %! m = [1 1]; %! [U R Q X] = qnmarkov( 3, S, C, P, m ); %! assert( U, [0.9333 0.4667], 1e-4 ); %! assert( X, [0.1867 0.1867], 1e-4 ); %! assert( R, [12.1429 3.9286], 1e-4 ); ## Example 7.5 p. 292 Bolch et al. %!test %! S = [1/0.8 1/0.6 1/0.4]; %! P = [0.6 0.3 0.1; 0.2 0.3 0.5; 0.4 0.1 0.5]; %! C = [3 3 3]; %! [U R Q X] = qnmarkov( 3, S, C, P ); %! assert( U, [0.543 0.386 0.797], 1e-3 ); %! assert( Q, [0.873 0.541 1.585], 1e-3 ); ## Example 10.19, p. 551 Bolch et al. %!## %! S = [2 0.9]; %! C = [7 5]; %! P = [0 1; 1 0]; %! [U R Q X] = qnmarkov( 10, S, C, P ); %! assert( Q, [6.73 3.27], 1e-3 ); ## Example 8.1 p. 317 Bolch et al. %!test %! S = [1/0.8 1/0.6 1/0.4]; %! P = [(1-0.667-0.2) 0.667 0.2; 1 0 0; 1 0 0]; %! m = [2 3 1]; %! C = [3 3 3]; %! [U R Q X] = qnmarkov( 3, S, C, P, m ); %! assert( U, [0.590 0.350 0.473], 1e-3 ); %! assert( Q(1:2), [1.290 1.050], 1e-3 ); ## This is a simple test of an open QN with fixed capacity queues. There ## are two service centers, S1 and S2. C(1) = 2 and C(2) = 1. Transition ## probability from S1 to S2 is 1. Transition probability from S2 to S1 ## is p. %!test %! p = 0.5; # transition prob. from S2 to S1 %! mu = [1 2]; # Service rates %! C = [2 1]; # Capacities %! lambda = [0.5 0]; # arrival rate at service center 1 %! %! PP = [ 0 1; p 0 ]; %! [U R Q X] = qnmarkov( lambda, 1./mu, C, PP ); %! ## Now we generate explicitly the infinitesimal generator matrix %! ## of the underlying MC. %! ## 00 01 10 11 20 21 %! QQ = [ 0 0 lambda(1) 0 0 0; ... ## 00 %! mu(2)*(1-p) 0 mu(2)*p lambda(1) 0 0; ... ## 01 %! 0 mu(1) 0 0 lambda(1) 0; ... ## 10 %! 0 0 mu(2)*(1-p) 0 mu(2)*p lambda(1); ... ## 11 %! 0 0 0 mu(1) 0 0; ... ## 20 %! 0 0 0 0 mu(2)*(1-p) 0 ]; ## 21 %! ## Complete matrix %! sum_el = sum(QQ,2); %! QQ -= diag(sum_el); %! q = ctmc(QQ); %! ## Compare results %! assert( U(1), 1-sum(q([1, 2])), 1e-5 ); %! assert( U(2), 1-sum(q([1,3,5])), 1e-5 ); ## This is a closed network with fixed-capacity queues. The population ## size N is such that blocking never occurs, so this model can be ## analyzed using the conventional MVA algorithm. MVA and qnmarkov() ## must produce the same results. %!test %! P = [0 0.5 0.5; 1 0 0; 1 0 0]; %! C = [6 6 6]; %! S = [1 0.8 1.8]; %! N = 6; %! [U1 R1 Q1 X1] = qnclosed( N, S, qncsvisits(P) ); %! [U2 R2 Q2 X2] = qnmarkov( N, S, C, P ); %! assert( U1, U2, 1e-6 ); %! assert( R1, R2, 1e-6 ); %! assert( Q1, Q2, 1e-6 ); %! assert( X1, X2, 1e-6 ); ## return a linear index corresponding to index idx on a ## multidimensional vector of dimension(s) dim function i = sub2cell( dim, idx ) idx_cell = num2cell( idx+1 ); i = sub2ind( dim+1, idx_cell{:} ); endfunction queueing/inst/engset.m0000664000175000017500000000737714620404470014721 0ustar morenomoreno## Copyright (C) 2014, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{B} =} engset (@var{A}, @var{m}, @var{n}) ## ## @cindex Engset loss formula ## ## Evaluate the Engset loss formula. ## ## The Engset formula computes the blocking probability ## @math{P_b(A,m,n)} for a system with a finite population of @math{n} ## users, @math{m} identical servers, no queue, individual service ## rate @math{\mu}, individual arrival rate @math{\lambda} (i.e., the ## time until a user tries to request service is exponentially ## distributed with mean @math{1/\lambda}), and offered load ## @math{A=\lambda/\mu}. ## ## @tex ## @math{P_b(A, m, n)} is defined for @math{n > m} as: ## ## $$ ## P_b(A, m, n) = {{\displaystyle{A^m {n \choose m}}} \over {\displaystyle{\sum_{k=0}^m A^k {n \choose k}}}} ## $$ ## ## and is 0 if @math{n @leq{} m}. ## @end tex ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{A} ## Offered load, defined as @math{A = \lambda / \mu} where ## @math{\lambda} is the mean arrival rate and @math{\mu} the mean ## service rate of each individual server (real, @math{A > 0}). ## ## @item @var{m} ## Number of identical servers (integer, @math{m @geq{} 1}). Default @math{m = 1} ## ## @item @var{n} ## Number of requests (integer, @math{n @geq{} 1}). Default @math{n = 1} ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{B} ## The value @math{P_b(A, m, n)} ## ## @end table ## ## @var{A}, @var{m} or @math{n} can be vectors, and in this case, the ## results will be vectors as well. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Zeng, @cite{Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function}, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296 ## @end itemize ## ## @seealso{erlangb, erlangc} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function P = engset(A, m, n) if ( nargin < 1 || nargin > 3 ) print_usage(); endif ( isnumeric(A) && all( A(:) > 0 ) ) || error("A must be positive"); if ( nargin < 2 ) m = 1; else ( isnumeric(m) && all( fix(m(:)) == m(:)) && all( m(:) > 0 ) ) || error("m must be a positive integer"); endif if ( nargin < 3 ) n = 1; else ( isnumeric(n) && all( fix(n(:)) == n(:)) && all( n(:) > 0 ) ) || error("n must be a positive integer"); endif [err A m n] = common_size(A, m, n); if ( err ) error("parameters are not of common size"); endif P = arrayfun( @__engset_compute, A, m, n); endfunction ## Compute P_b(A,m,n) recursively function P = __engset_compute(A, m, n) if ( m >= n ) P = 0.0; else P = 1.0; for i = 1:m P=(A*(n-i)*P)/(i+A*(n-i)*P); endfor endif endfunction %!test %! fail("erlangb(1, -1)", "positive"); %! fail("erlangb(-1, 1)", "positive"); %! fail("erlangb(1, 0)", "positive"); %! fail("erlangb(0, 1)", "positive"); %! fail("erlangb('foo',1)", "positive"); %! fail("erlangb(1,'bar')", "positive"); %! fail("erlangb([1 1],[1 1 1])","common size"); queueing/inst/qncmmvaap.m0000664000175000017500000000414514620404470015405 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvaap (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvaap (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}, @var{iter_max}) ## ## @cindex Mean Value Analysys (MVA), approximate ## @cindex MVA, approximate ## @cindex closed network, multiple classes ## @cindex multiclass network, closed ## ## This function is deprecated. Plase use @code{qncmmvabs} instead. ## ## @seealso{qncmmvabs} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qncmmvaap( N, S, V, m, Z, tol, iter_max ) persistent warned = false; if (!warned) warned = true; warning("qn:deprecated-function", "qncmmvaap is deprecated. Please use qncmmvabs instead"); endif [U R Q X] = qncmmvabs( varargin{:} ); endfunction queueing/inst/qncmnpop.m0000664000175000017500000000561614620404470015261 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{H} =} qncmnpop (@var{N}) ## ## @cindex population mix ## @cindex closed network, multiple classes ## ## Given a network with @math{C} customer classes, this function ## computes the number of @math{k}-mixes @code{@var{H}(r,k)} that can ## be constructed by the multiclass MVA algorithm by allocating ## @math{k} customers to the first @math{r} classes. ## @xref{doc-qncmpopmix} for the definition of @math{k}-mix. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N}(c) ## number of class-@math{c} requests in the system. The total number ## of requests in the network is @code{sum(@var{N})}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{H}(r,k) ## is the number of @math{k} mixes that can be constructed allocating ## @math{k} customers to the first @math{r} classes. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item Zahorjan, J. and Wong, E. @cite{The solution of separable queueing ## network models using mean value analysis}. SIGMETRICS ## Perform. Eval. Rev. 10, 3 (Sep. 1981), 80-85. DOI ## @uref{http://doi.acm.org/10.1145/1010629.805477, 10.1145/1010629.805477} ## @end itemize ## ## @seealso{qncmmva,qncmpopmix} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function H = qncmnpop( N ) (isvector(N) && all( N > 0 ) ) || ... error( "N must be a vector of strictly positive integers" ); N = N(:)'; # make N a row vector Ns = sum(N); R = length(N); ## In the implementation below we initialize the variable ## @code{TOTAL_POP} variable to 0 instead of @code{@var{N}(1)} as in ## the paper. Moreover, we increment @code{TOTAL_POP} ## @code{@var{N}(r)} at each iteration, instead of ## @code{@var{N}(r-1)} as in the paper. total_pop = N(1); H = zeros(R, Ns+1); H(1,1:N(1)+1) = 1; for r=2:R total_pop += N(r); for n=0:total_pop range = max(0,n-N(r)) : n; H(r,n+1) = sum( H(r-1, range+1 ) ); endfor endfor endfunction %!test %! H = qncmnpop( [1 2 2] ); %! assert( H, [1 1 0 0 0 0; 1 2 2 1 0 0; 1 3 5 5 3 1] ); queueing/inst/qnosbsb.m0000664000175000017500000000574414620404470015077 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosbsb (@var{lambda}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosbsb (@var{lambda}, @var{S}, @var{V}) ## ## @cindex bounds, balanced system ## @cindex open network ## ## Compute Balanced System Bounds for single-class, open networks with ## @math{K} service centers. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## overall arrival rate to the system (scalar, @code{@var{lambda} @geq{} 0}). ## ## @item @var{D}(k) ## service demand at center @math{k} (@code{@var{D}(k) @geq{} 0}). ## ## @item @var{S}(k) ## service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). ## ## @item @var{V}(k) ## mean number of visits at center @math{k} (@code{@var{V}(k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k}. This function only supports ## @math{M/M/1} queues, therefore @var{m} must be ## @code{ones(size(S))}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl} ## @item @var{Xu} ## Lower and upper bounds on the system throughput. @var{Xl} is always ## set to @math{0}, since there can be no lower bound on open ## networks throughput. ## ## @item @var{Rl} ## @itemx @var{Ru} ## Lower and upper bounds on the system response time. ## ## @end table ## ## @seealso{qnosaba} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [X_lower X_upper R_lower R_upper] = qnosbsb( varargin ) if ( nargin < 2 || nargin > 4 ) print_usage(); endif [err lambda S V m] = qnoschkparam( varargin{:} ); isempty(err) || error(err); all(m==1) || ... error("this function supports M/M/1 servers only"); D = S .* V; D_max = max(D); D_tot = sum(D); D_ave = mean(D_tot); X_upper = 1/D_max; X_lower = 0; R_lower = D_tot / (1-lambda*D_ave); R_upper = D_tot / (1-lambda*D_max); endfunction %!test %! fail( "qnosbsb( 0.1, [] )", "vector" ); %! fail( "qnosbsb( 0.1, [0 -1])", "nonnegative" ); %! fail( "qnosbsb( 0, [1 2] )", "lambda" ); %! fail( "qnosbsb( -1, [1 2])", "lambda" ); %!test %! [Xl Xu Rl Ru] = qnosbsb(0.1,[1 2 3]); %! assert( Xl, 0 ); queueing/inst/qncmmvabs.m0000664000175000017500000002450414620404470015412 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018, 2019, 2020, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmvabs (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}, @var{iter_max}) ## ## @cindex Mean Value Analysys (MVA), approximate ## @cindex MVA, approximate ## @cindex closed network, multiple classes ## @cindex multiclass network, closed ## ## Approximate Mean Value Analysis (MVA) for closed, multiclass ## queueing networks with @math{K} service centers and @math{C} ## customer classes. ## ## This implementation uses Bard and Schweitzer approximation. It is ## based on the assumption that the queue length at service center ## @math{k} with population set @math{{\bf N}-{\bf 1}_c} is ## approximated with ## ## @tex ## $$Q_k({\bf N}-{\bf 1}_c) \approx {n-1 \over n} Q_k({\bf N})$$ ## @end tex ## @ifnottex ## @example ## @group ## Q_k(N-1c) ~ (n-1)/n Q_k(N) ## @end group ## @end example ## @end ifnottex ## ## where @math{\bf N} is a valid population mix, @math{{\bf N}-{\bf 1}_c} ## is the population mix @math{\bf N} with one class @math{c} customer ## removed, and @math{n = \sum_c N_c} is the total number of requests. ## ## This implementation works for networks with infinite server (IS) ## and single-server nodes only. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N}(c) ## number of class @math{c} requests in the system (@code{@var{N}(c) @geq{} 0}). ## ## @item @var{S}(c,k) ## mean service time for class @math{c} customers at center @math{k} ## (@code{@var{S}(c,k) @geq{} 0}). ## ## @item @var{V}(c,k) ## average number of visits of class @math{c} requests to center ## @math{k} (@code{@var{V}(c,k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k}. If @code{@var{m}(k) < 1}, ## then the service center @math{k} is assumed to be a delay center ## (IS). If @code{@var{m}(k) == 1}, service center @math{k} is a ## regular queueing center (FCFS, LCFS-PR or PS) with a single server ## node. If omitted, each service center has a single server. Note ## that multiple server nodes are not supported. ## ## @item @var{Z}(c) ## class @math{c} external delay (@code{@var{Z} @geq{} 0}). Default is 0. ## ## @item @var{tol} ## Stopping tolerance (@code{@var{tol}>0}). The algorithm stops if ## the queue length computed on two subsequent iterations are less than ## @var{tol}. Default is @math{10^{-5}}. ## ## @item @var{iter_max} ## Maximum number of iterations (@code{@var{iter_max}>0}. ## The function aborts if convergenge is not reached within the maximum ## number of iterations. Default is 100. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(c,k) ## If @math{k} is a FCFS, LCFS-PR or PS node, then @code{@var{U}(c,k)} ## is the utilization of class @math{c} requests on service center ## @math{k}. If @math{k} is an IS node, then @code{@var{U}(c,k)} is the ## class @math{c} @emph{traffic intensity} at device @math{k}, ## defined as @code{@var{U}(c,k) = @var{X}(c)*@var{S}(c,k)} ## ## @item @var{R}(c,k) ## response time of class @math{c} requests at service center @math{k}. ## ## @item @var{Q}(c,k) ## average number of class @math{c} requests at service center @math{k}. ## ## @item @var{X}(c,k) ## class @math{c} throughput at service center @math{k}. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Y. Bard, @cite{Some Extensions to Multiclass Queueing Network Analysis}, ## proc. 4th Int. Symp. on Modelling and Performance Evaluation of ## Computer Systems, Feb 1979, pp. 51--62. ## ## @item ## P. Schweitzer, @cite{Approximate Analysis of Multiclass Closed ## Networks of Queues}, Proc. Int. Conf. on Stochastic Control and ## Optimization, jun 1979, pp. 25--29. ## @end itemize ## ## This implementation is based on Edward D. Lazowska, John Zahorjan, G. ## Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System ## Performance: Computer System Analysis Using Queueing Network Models}, ## Prentice Hall, ## 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In ## particular, see section 7.4.2.2 ("Approximate Solution ## Techniques"). This implementation is slightly different from the one ## described above, as it computes the average response times @math{R} ## instead of the residence times. ## ## @seealso{qncmmva} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qncmmvabs( N, S, V, m, Z, tol, iter_max ) if ( nargin < 3 || nargin > 7 ) print_usage(); endif isvector(N) && all( N>=0 ) || ... error( "N must be a vector of positive integers" ); N = N(:)'; # make N a row vector C = length(N); ## Number of classes K = columns(S); ## Number of service centers size(S) == [C,K] || ... error( "S size mismatch" ); size(V) == [C,K] || ... error( "V size mismatch" ); if ( nargin < 4 || isempty(m) ) m = ones(1,K); else isvector(m) || ... error( "m must be a vector"); m = m(:)'; # make m a row vector ( length(m) == K && all( m <= 1 ) ) || ... error( "m must be <= 1 and have %d elements", K ); endif if ( nargin < 5 || isempty(Z) ) Z = zeros(1,C); else isvector(Z) || ... error( "Z must be a vector" ); Z = Z(:)'; # make Z a row vector ( length(Z) == C && all(Z >= 0 ) ) || ... error( "Z must be >= 0 and have %d elements", C ); endif if ( nargin < 6 || isempty(tol) ) tol = 1e-5; endif if ( nargin < 7 || isempty(iter_max) ) iter_max = 100; endif ## Check consistency of parameters all(S(:) >= 0) || ... error( "S contains negative values" ); all(V(:) >= 0) || ... error( "V contains negative values" ); ## Initialize results R = zeros( C, K ); Xc = zeros( 1, C ); # Xc(c) is the class c throughput Q = zeros( C, K ); D = V .* S; ## Initialization of temporaries iter = 0; A = zeros( C, K ); Q = diag(N/K)*ones(C,K); # Q(c,k) = N(c) / K i_single=find(m==1); i_multi=find(m<1); ## Main loop N(N==0)=1; do iter++; Qold = Q; ## A(c,k) = (N(c)-1)/N(c) * Q(c,k) + sum_{j=1, j|=c}^C Qold(j,k) A = diag( (N-1) ./ N )*Q + ( (1 - eye(C)) * Qold ); ## R(c,k) = ## S(c,k) is k is a delay center ## S(c,k) * (1+A(c,k)) if k is a queueing center; R(:,i_multi) = S(:,i_multi); R(:,i_single) = S(:,i_single) .* ( 1 + A(:,i_single)); ## X(c) = N(c) / (sum_k R(c,k) * V(c,k)) Xc = N ./ (Z + sum(R.*V,2)'); ## Q(c,k) = X(c) * R(c,k) * V(c,k) Q = (diag(Xc)*R).*V; ## err = norm(Q-Qold); err = norm((Q-Qold)./Qold, "inf"); until (erriter_max); if ( iter > iter_max ) warning( "qncmmvabs(): Convergence not reached after %d iterations", iter_max ); endif X = diag(Xc)*V; # X(c,k) = X(c) * V(c,k) U = diag(Xc)*D; # U(c,k) = X(c) * D(c,k) # U(N==0,:) = R(N==0,:) = Q(N==0,:) = X(N==0,:) = 0; endfunction %!test %! S = [ 1 3 3; 2 4 3]; %! V = [ 1 1 3; 1 1 3]; %! N = [ 1 1 ]; %! m = [1 ; 1 ]; %! Z = [2 2 2]; %! fail( "qncmmvabs(N,S,V,m,Z)", "m must be" ); %! m = [1 ; 1 ; 1]; %! fail( "qncmmvabs(N,S,V,m,Z)", "Z must be" ); %!test %! S = [ 1 3; 2 4]; %! V = [ 1 1; 1 1]; %! N = [ 1 1 ]; %! m = ones(1,2); %! [U R Q X] = qncmmvabs(N,S,V,m); %! assert( Q, [ .192 .808; .248 .752 ], 1e-3 ); %! Xc = ( X(:,1)./V(:,1) )'; %! assert( Xc, [ .154 .104 ], 1e-3 ); %! # Compute the (overall) class-c system response time %! R_c = N ./ Xc; %! assert( R_c, [ 6.508 9.614 ], 5e-3 ); %!demo %! S = [ 1, 1, 1, 1; 2, 1, 3, 1; 4, 2, 3, 3 ]; %! V = ones(3,4); %! N = [10 5 1]; %! m = [1 0 1 1]; %! [U R Q X] = qncmmvabs(N,S,V,m); %!demo %! ## The following code produces Fig. 7 from the paper: M. Marzolla, "A GNU %! ## Octave package for Queueing Networks and Markov Chains analysis", %! ## submitted to the ACM Transactions on Mathematical Software. %! %! N = 300; # total number of jobs %! S = [100 140 200 30 50 20 10; # service demands %! 180 10 70 10 90 130 30; %! 280 160 150 90 20 50 18]; %! Z = [2400 1800 2100]; # mean duration of CPU burst %! V = ones(size(S)); # number of visits %! m = ones(1,columns(S)); # number of servers %! %! beta = linspace(0.1, 0.9, 50); # population mix %! Xsys = Rsys = NA(length(beta), length(beta)); %! %! pop = zeros(1,rows(S)); %! tic; %! for i=1:length(beta) %! for j=1:length(beta) %! pop(1) = round(beta(i)*N); %! pop(2) = round(beta(j)*N); %! pop(3) = N - pop(1) - pop(2); %! if (all(pop > 0)) %! [U R Q X] = qncmmvabs( pop, S, V, m, Z, 1e-5, 1000 ); %! X1 = X(1,2) / V(1,2); %! X2 = X(2,2) / V(2,2); %! X3 = X(3,2) / V(3,2); %! Xsys(i,j) = X1 + X2 + X3; %! Rsys(i,j) = N / Xsys(i,j); %! endif %! endfor %! endfor %! toc; %! minX = min(Xsys(:)); %! maxX = max(Xsys(:)); %! Xnew = Xsys; Xnew(isna(Xnew)) = maxX+1; %! mycmap = jet; %! mycmap(end,:) = 1; # make the last colormap entry white %! imshow(Xnew, [minX, maxX], "Xdata", beta, "Ydata", beta, "colormap", mycmap); %! colorbar; %! hold on; %! title("System throughput"); %! xlabel("\\beta_2"); %! ylabel("\\beta_1"); %! [XX YY] = meshgrid(beta, beta); %! contour(XX, YY, Xsys, "k", "linewidth", 1.5); %! axis on; %! hold off; queueing/inst/qncscmva.m0000664000175000017500000001721514620404470015237 0ustar morenomoreno## Copyright (C) 2011, 2012, 2016, 2018, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncscmva (@var{N}, @var{S}, @var{Sld}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncscmva (@var{N}, @var{S}, @var{Sld}, @var{V}, @var{Z}) ## ## @cindex conditional MVA (CMVA) ## @cindex Mean Value Analysis, conditional (CMVA) ## @cindex closed network, single class ## @cindex CMVA ## ## Conditional MVA (CMVA) algorithm, a numerically stable variant of ## MVA. This function supports a network of @math{M @geq{} 1} service ## centers and a single delay center. Servers @math{1, @dots{}, (M-1)} ## are load-independent; server @math{M} is load-dependent. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## Number of requests in the system, @code{@var{N} @geq{} 0}. If ## @code{@var{N} == 0}, this function returns @code{@var{U} = @var{R} ## = @var{Q} = @var{X} = 0} ## ## @item @var{S}(k) ## mean service time on server @math{k = 1, @dots{}, (M-1)} ## (@code{@var{S}(k) > 0}). If there are no fixed-rate servers, then ## @code{S = []} ## ## @item @var{Sld}(n) ## inverse service rate at server @math{M} (the load-dependent server) ## when there are @math{n} requests, @math{n=1, @dots{}, N}. ## @code{@var{Sld}(n) = } @math{1 / \mu(n)}. ## ## @item @var{V}(k) ## average number of visits to service center @math{k=1, @dots{}, M}, ## where @code{@var{V}(k) @geq{} 0}. @code{@var{V}(1:M-1)} are the ## visit rates to the fixed rate servers; @code{@var{V}(M)} is the ## visit rate to the load dependent server. ## ## @item @var{Z} ## External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(k) ## center @math{k} utilization (@math{k=1, @dots{}, M}) ## ## @item @var{R}(k) ## response time of center @math{k} (@math{k=1, @dots{}, M}). The ## system response time @var{Rsys} can be computed as @code{@var{Rsys} ## = @var{N}/@var{Xsys} - Z} ## ## @item @var{Q}(k) ## average number of requests at center @math{k} (@math{k=1, @dots{}, M}). ## ## @item @var{X}(k) ## center @math{k} throughput (@math{k=1, @dots{}, M}). ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Casale. @cite{A note on stable flow-equivalent aggregation in ## closed networks}. Queueing Syst. Theory Appl., 60:193–-202, December ## 2008, @uref{http://dx.doi.org/10.1007/s11134-008-9093-6, 10.1007/s11134-008-9093-6} ## @end itemize ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qncscmva( N, S, Sld, V, Z ) ## This is a numerically stable implementation of the MVA algorithm, ## described in G. Casale, A note on stable flow-equivalent aggregation in ## closed networks. Queueing Syst. Theory Appl., 60:193–-202, December ## 2008, http://dx.doi.org/10.1007/s11134-008-9093-6 if ( nargin < 4 || nargin > 5 ) print_usage(); endif isscalar(N) && N >= 0 || ... error("N must be a positive scalar"); (isempty(S) || isvector(S)) || ... error("S must be a vector"); S = S(:)'; # make S a row vector M = length(S)+1; # total number of service centers (excluding the delay center) isvector(Sld) && length(Sld) == N && all(Sld>=0) || ... error("Sld must be a vector with %d elements >= 0", N); Sld = Sld(:)'; # Make Sld a row vector isvector(V) && length(V) == M && all(V>=0) || ... error("V must be a vector with %d elements", M); V = V(:)'; # Make V a row vector ## The reference paper assumes queue M (LD center) as reference. ## Therefore, we need to rescale V V(M) > 0 || ... error("V(M) must be >0"); V = V / V(M); if ( nargin == 5 ) isscalar(Z) && Z>=0 || ... error("Z must be nonnegative"); else Z = 0; endif if ( N == 0 ) U = R = Q = X = zeros(1,M); return; endif ## Di(1+k) = service demand of server k=0,1,...,M-1 (server 0 is the delay center) Di = zeros(1,M); Di(1) = Z; Di(2:M) = S .* V(1:M-1); ## DM(n,t), n=1, ..., N, t=1, ..., N DM = zeros(N,N); mu = 1./Sld; # rate function ## Ri(1+k,:,:) = response time of server k=0,1,...,M Ri = zeros(1+M,N,N); ## Qi(k,1+n,t) = queue length of server k=1,...,M, n=0,1,...,N, t=1,...,N+1 Qi = zeros(M,1+N,N+1); Xs = zeros(N,N); # Xs = system throughput ## Main MVA loop for n=1:N for t=1:(N-n+1) if ( n==1 ) DM(n,t) = 1/mu(t); else # n>=2 DM(n,t) = Xs(n-1,t)/Xs(n-1,t+1)*DM(n-1,t); endif Ri(1+0,n,t) = Di(1+0); i=1:M-1; Ri(1+i,n,t) = Di(1+i).*(1+Qi(i,1+n-1,t))'; Ri(1+M,n,t) = DM(n,t)*(1+Qi(M,1+n-1,t+1)); Xs(n,t) = n/sum(Ri(:,n,t)); i=1:M-1; Qi(i,1+n,t) = Di(1+i) .* Xs(n,t) .* (1+Qi(i,1+n-1,t))'; Qi(M,1+n,t) = DM(n,t) * Xs(n,t) * (1+Qi(M,1+n-1,t+1)); endfor endfor X = Xs(N,1).*V; Q = Qi(1:M,1+N,1)'; ## Note that the result R is the *response time*, while the value ## computed by the reference paper is the *residence time*. The ## response time is equal to the residence time divided by the visit ## ratios. R = Ri(2:M+1,N,1)' ./ V; U = [Di(2:M) DM(N,1)] .* X ./ V; endfunction %!test %! N=5; %! S = [1 0.3 0.8 0.9]; %! V = [1 1 1 1]; %! [U1 R1 Q1 X1] = qncscmva( N, S(1:3), repmat(S(4),1,N), V ); %! [U2 R2 Q2 X2] = qncsmva(N, S, V); %! assert( X1, X2, 1e-5 ); %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 ); %! assert( Q1, Q2, 1e-5 ); %!test %! N=5; %! S = [1 1 1 1 1; ... %! 1 1 1 1 1; ... %! 1 1 1 1 1; ... %! 1 1/2 1/3 1/4 1/5]; %! V = [1 1 1 1]; %! [U1 R1 Q1 X1] = qncscmva( N, S(1:3,1), S(4,:), V ); %! [U2 R2 Q2 X2] = qncsmvald(N, S, V); %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 ); %! assert( Q1, Q2, 1e-5 ); %! assert( X1, X2, 1e-5 ); %!test %! N=5; %! S = [1 1 1 1 1; ... %! 1 1 1 1 1; ... %! 1 1 1 1 1; ... %! 1 1/2 1/3 1/4 1/5]; %! V = [1 2 1 1]; %! Z = 3; %! [U1 R1 Q1 X1] = qncscmva( N, S(1:3,1), S(4,:), V, Z ); %! [U2 R2 Q2 X2] = qncsmvald(N, S, V, Z); %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 ); %! assert( Q1, Q2, 1e-5 ); %! assert( X1, X2, 1e-5 ); %!demo %! maxN = 90; # Max population size %! Rmva = Rconv = Rcmva = zeros(1,maxN); # Results %! S = 4; Z = 10; m = 8; %! old = warning("query","qn:numerical-instability"); %! warning("off","qn:numerical-instability"); %! for N=1:maxN %! [U R] = qncsmva(N,S,1,m,Z); # Use MVA %! Rmva(N) = R(1); %! [U R] = qncsconv(N,[S Z],[1 1],[m -1]); # Use Convolution %! Rconv(N) = R(1); %! if ( N > m ) %! Scmva = S ./ min(1:N,m); %! else %! Scmva = S ./ (1:N); %! endif %! [U R] = qncscmva(N,[],Scmva,1,Z); # Use CMVA %! Rcmva(N) = R(1); %! endfor %! warning(old.state,"qn:numerical-instability"); %! plot(1:maxN, Rmva, ";MVA;", ... %! 1:maxN, Rconv, ";Convolution;", ... %! 1:maxN, Rcmva, ";CNVA;", "linewidth",2); %! xlabel("Population size (N)"); %! ylabel("Response Time"); %! ax=axis(); ax(3) = 0; ax(4) = 40; axis(ax); %! legend("location","northwest"); legend("boxoff"); queueing/inst/qnclosed.m0000664000175000017500000000733214620404470015233 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosed (@var{N}, @var{S}, @var{V}, @dots{}) ## ## @cindex closed network, single class ## @cindex closed network, multiple classes ## ## This function computes steady-state performance measures of closed ## queueing networks using the Mean Value Analysis (MVA) algorithm. The ## qneneing network is allowed to contain fixed-capacity centers, delay ## centers or general load-dependent centers. Multiple request ## classes are supported. ## ## This function dispatches the computation to one of ## @code{qncsemva}, @code{qncsmvald} or @code{qncmmva}. ## ## @itemize ## ## @item If @var{N} is a scalar, the network is assumed to have a single ## class of requests; in this case, the exact MVA algorithm is used to ## analyze the network. If @var{S} is a vector, then @code{@var{S}(k)} ## is the average service time of center @math{k}, and this function ## calls @code{qncsmva} which supports load-independent ## service centers. If @var{S} is a matrix, @code{@var{S}(k,i)} is the ## average service time at center @math{k} when @math{i=1, @dots{}, N} ## jobs are present; in this case, the network is analyzed with the ## @code{qncmmvald} function. ## ## @item If @var{N} is a vector, the network is assumed to have multiple ## classes of requests, and is analyzed using the exact multiclass ## MVA algorithm as implemented in the @code{qncmmva} function. ## ## @end itemize ## ## @seealso{qncsmva, qncsmvald, qncmmva} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qnclosed( N, S, V, varargin ) if ( nargin < 3 ) print_usage(); endif if ( isscalar(N) ) if ( isvector(S) ) [U R Q X] = qncsmva( N, S, V, varargin{:} ); else [U R Q X] = qncsmvald( N, S, V, varargin{:} ); endif else [U R Q X] = qncmmva( N, S, V, varargin{:} ); endif endfunction %!demo %! P = [0 0.3 0.7; 1 0 0; 1 0 0]; # Transition probability matrix %! S = [1 0.6 0.2]; # Average service times %! m = ones(size(S)); # All centers are single-server %! Z = 2; # External delay %! N = 15; # Maximum population to consider %! V = qncsvisits(P); # Compute number of visits %! X_bsb_lower = X_bsb_upper = X_ab_lower = X_ab_upper = X_mva = zeros(1,N); %! for n=1:N %! [X_bsb_lower(n) X_bsb_upper(n)] = qncsbsb(n, S, V, m, Z); %! [X_ab_lower(n) X_ab_upper(n)] = qncsaba(n, S, V, m, Z); %! [U R Q X] = qnclosed( n, S, V, m, Z ); %! X_mva(n) = X(1)/V(1); %! endfor %! close all; %! plot(1:N, X_ab_lower,"g;Asymptotic Bounds;", ... %! 1:N, X_bsb_lower,"k;Balanced System Bounds;", ... %! 1:N, X_mva,"b;MVA;", "linewidth", 2, ... %! 1:N, X_bsb_upper,"k", 1:N, X_ab_upper,"g" ); %! axis([1,N,0,1]); legend("location","southeast"); legend("boxoff"); %! xlabel("Number of Requests n"); ylabel("System Throughput X(n)"); queueing/inst/qncmmva.m0000664000175000017500000007670314620404470015075 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2016, 2018, 2020, 2022 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S} ) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{P}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{P}, @var{r}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmmva (@var{N}, @var{S}, @var{P}, @var{r}, @var{m}) ## ## @cindex Mean Value Analysys (MVA) ## @cindex closed network, multiple classes ## @cindex multiclass network, closed ## ## Compute steady-state performance measures for closed, multiclass ## queueing networks using the Mean Value Analysys (MVA) algorithm. ## ## Queueing policies at service centers can be any of the following: ## ## @table @strong ## ## @item FCFS ## (First-Come-First-Served) customers are served in order of arrival; ## multiple servers are allowed. For this kind of queueing discipline, ## average service times must be class-independent. ## ## @item PS ## (Processor Sharing) customers are served in parallel by a single ## server, each customer receiving an equal share of the service rate. ## ## @item LCFS-PR ## (Last-Come-First-Served, Preemptive Resume) customers are served in ## reverse order of arrival by a single server and the last arrival ## preempts the customer in service who will later resume service at the ## point of interruption. ## ## @item IS ## (Infinite Server) customers are delayed independently of other ## customers at the service center (there is effectively an infinite ## number of servers). ## ## @end table ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N}(c) ## number of class @math{c} requests; @code{@var{N}(c) @geq{} 0}. If ## class @math{c} has no requests (@code{@var{N}(c) == 0}), then for ## all @var{k}, this function returns ## @code{@var{U}(c,k) = @var{R}(c,k) = @var{Q}(c,k) = @var{X}(c,k) = 0} ## ## @item @var{S}(c,k) ## mean service time for class @math{c} requests at center @math{k} ## (@code{@var{S}(c,k) @geq{} 0}). If the service time at center ## @math{k} is class-dependent, then center @math{k} is assumed ## to be of type @math{-/G/1}--PS (Processor Sharing). If center ## @math{k} is a FCFS node (@code{@var{m}(k)>1}), then the service ## times @strong{must} be class-independent, i.e., all classes ## @strong{must} have the same service time. ## ## @item @var{V}(c,k) ## average number of visits of class @math{c} requests at ## center @math{k}; @code{@var{V}(c,k) @geq{} 0}, default is 1. ## @strong{If you pass this argument, class switching is not allowed} ## ## @item @var{P}(r,i,s,j) ## probability that a class @math{r} request completing service at center ## @math{i} is routed to center @math{j} as a class @math{s} request; the ## reference stations for each class are specified with the paramter ## @var{r}. @strong{If you pass argument @var{P}, class switching is ## allowed}; however, you can not specify any external delay (i.e., ## @var{Z} must be zero) and all servers must be fixed-rate or ## infinite-server nodes (@code{@var{m}(k) @leq{} 1} for all ## @math{k}). ## ## @item @var{r}(c) ## reference station for class @math{c}. If omitted, station 1 is the ## reference station for all classes. See @command{qncmvisits}. ## ## @item @var{m}(k) ## If @code{@var{m}(k)<1}, then center @math{k} is assumed to be a delay ## center (IS node @math{-/G/\infty}). If @code{@var{m}(k)==1}, then ## service center @math{k} is a regular queueing center ## (@math{M/M/1}--FCFS, @math{-/G/1}--LCFS-PR or @math{-/G/1}--PS). ## Finally, if @code{@var{m}(k)>1}, center @math{k} is a ## @math{M/M/m}--FCFS center with @code{@var{m}(k)} identical servers. ## Default is @code{@var{m}(k)=1} for each @math{k}. ## ## @item @var{Z}(c) ## class @math{c} external delay (think time); @code{@var{Z}(c) @geq{} ## 0}. Default is 0. This parameter can not be used if you pass a ## routing matrix as the second parameter of @code{qncmmva}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(c,k) ## If @math{k} is a FCFS, LCFS-PR or PS node (@code{@var{m}(k) @geq{} ## 1}), then @code{@var{U}(c,k)} is the class @math{c} utilization at ## center @math{k}, @math{0 @leq{} U(c,k) @leq{} 1}. If @math{k} is an ## IS node, then @code{@var{U}(c,k)} is the class @math{c} @emph{traffic ## intensity} at center @math{k}, defined as @code{@var{U}(c,k) = ## @var{X}(c,k)*@var{S}(c,k)}. In this case the value of ## @code{@var{U}(c,k)} may be greater than one. ## ## @item @var{R}(c,k) ## class @math{c} response time at center @math{k}. The class @math{c} ## @emph{residence time} at center @math{k} is @code{@var{R}(c,k) * ## @var{C}(c,k)}. The total class @math{c} system response time is ## @code{dot(@var{R}, @var{V}, 2)}. ## ## @item @var{Q}(c,k) ## average number of class @math{c} requests at center @math{k}. The ## total number of requests at center @math{k} is ## @code{sum(@var{Q}(:,k))}. The total number of class @math{c} ## requests in the system is @code{sum(@var{Q}(c,:))}. ## ## @item @var{X}(c,k) ## class @math{c} throughput at center @math{k}. The class @math{c} ## throughput can be computed as @code{@var{X}(c,1) / @var{V}(c,1)}. ## ## @end table ## ## @strong{NOTES} ## ## If the function call specifies the visit ratios @var{V}, then class ## switching is @strong{not} allowed. If the function call specifies ## the routing probability matrix @var{P}, then class switching ## @strong{is} allowed; however, in this case all nodes are restricted ## to be fixed rate servers or delay centers: multiple-server and ## general load-dependent centers are not supported. ## ## In presence of load-dependent servers (e.g., if @code{@var{m}(i)>1} ## for some @math{i}), the MVA algorithm is known to be numerically ## unstable. Generally this problem shows up as negative values for the ## computed response times or utilizations. This is not a problem with the ## @code{queueing} package, but with the MVA algorithm; ## as such, there is no known workaround at the moment (aoart from using a ## different solution technique, if available). This function prints a ## warning if it detects numerical problems; you can disable the warning ## with the command @code{warning("off", "qn:numerical-instability")}. ## ## Given a network with @math{K} service centers, @math{C} job classes ## and population vector @math{{\bf N}=\left[N_1, @dots{}, N_C\right]}, the MVA ## algorithm requires space @math{O(C \prod_i (N_i + 1))}. The time ## complexity is @math{O(CK\prod_i (N_i + 1))}. This implementation is ## slightly more space-efficient (see details in the code). While the ## space requirement can be mitigated by using some optimizations, the ## time complexity can not. If you need to analyze large closed networks ## you should consider the @command{qncmmvaap} function, which implements ## the approximate MVA algorithm. Note however that @command{qncmmvaap} ## will only provide approximate results. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed ## Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, April ## 1980, pp. 313--322. @uref{http://doi.acm.org/10.1145/322186.322195, 10.1145/322186.322195} ## @end itemize ## ## This implementation is based on G. Bolch, S. Greiner, H. de Meer and ## K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and ## Performance Evaluation with Computer Science Applications}, Wiley, ## 1998 and Edward D. Lazowska, John Zahorjan, G. Scott Graham, and ## Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer ## System Analysis Using Queueing Network Models}, Prentice Hall, ## 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In ## particular, see section 7.4.2.1 ("Exact Solution Techniques"). ## ## @seealso{qnclosed, qncmmvaapprox, qncmvisits} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qncmmva( varargin ) if ( nargin < 2 || nargin > 5 ) print_usage(); endif if ( nargin == 2 || ndims(varargin{3}) == 2 ) [err N S V m Z] = qncmchkparam( varargin{:} ); isempty(err) || error(err); [U R Q X] = __qncmmva_nocs( N, S, V, m, Z ); else [U R Q X] = __qncmmva_cs( varargin{:} ); endif endfunction ############################################################################## ## Analyze closed, multiclass QNs with class switching function [U R Q X] = __qncmmva_cs( N, S, P, r, m ) if ( nargin < 3 || nargin > 5 ) print_usage(); endif isvector(N) && all( N>=0 ) || ... error( "N must be >=0" ); N = N(:)'; # make N a row vector C = length(N); ## Number of classes ( ndims(S) == 2 ) || ... error( "S must be a matrix" ); K = columns(S); ## Number of service centers size(S) == [C,K] || ... error( "S size mismatch (is %dx%d, should be %dx%d)", rows(S), columns(S), C, K ); ndims(P) == 4 && size(P) == [C,K,C,K] || ... error( "P size mismatch (should be %dx%dx%dx%d)",C,K,C,K ); if ( nargin < 4 ) r = ones(1,C); # reference station else if (isscalar(r)) r = r*ones(1,C); endif ( isvector(r) && length(r) == C ) || ... error("r must be a vector with %d elements", C); r = r(:)'; all( r>=1 && r<=K ) || ... error("elements of r are out of range [1,%d]",K); endif if ( nargin < 5 ) m = ones(1,K); else isvector(m) || ... error( "m must be a vector" ); m = m(:)'; # make m a row vector length(m) == K || ... error( "m size mismatch (should be %d, is %d)", K, length(m) ); endif ## Check consistency of parameters all(S(:) >= 0) || ... error( "S must be >= 0" ); all( any(S>0,2) ) || ... error( "S must contain at least a value >0 for each row" ); all(P(:)>= 0) || ... error( "P must be >=0" ); U = R = Q = X = zeros(C,K); ## 1. Compute visit counts [V ch] = qncmvisits(P,r); ## 2. Identify chains nch = max(ch); ## 3. Compute visit counts for the equivalent network Vstar = zeros(nch,K); for q=1:nch r = (ch == q); Vstar(q,:) = sum(V(r,:),1); endfor ## 4. Compute proportionality constants alpha = zeros(C,K); for r=1:C for k=find( Vstar(ch(r),:) > 0 ) alpha(r,k) = V(r,k) / Vstar( ch(r), k ); endfor endfor ## 5. Compute service times Sstar = zeros(nch,K); for q=1:nch r = (ch==q); Sstar(q,:) = dot( alpha(r,:), S(r,:), 1 ); endfor ## 6. Compute populations of superclasses Nstar = zeros(1,nch); for q=1:nch r = (ch == q); Nstar(q) = sum( N(r) ); endfor ## 7. Solve the equivalent network [Ustar Rstar Qstar Xstar Qnm1] = __qncmmva_nocs( Nstar, Sstar, Vstar, m, zeros(size(Nstar)) ); ## 8. Compute solutions of the original network for r=1:C for k=1:K R(r,k) = S(r,k) * (1 + Qnm1(ch(r),k)*(m(k)==1)); X(r,k) = alpha(r,k) * Xstar(ch(r),k); Q(r,k) = X(r,k) * R(r,k); U(r,k) = S(r,k) * X(r,k) / max(1,m(k)); endfor endfor ## 9. Check for numerical instability if ( any(U(:)<0) || any(R(:)<0) ) warning("qn:numerical-instability", "Numerical instability detected. Type 'help qncmmva' for details"); endif endfunction ############################################################################## ## Analyze closed, multiclass QNs WITHOUT class switching ## ## This implementation is based on: ## ## Herb Schwetman, "Implementing the Mean Value Algorithm for the ## Solution of Queueing Network Models", technical report OSD-TR-355, ## dept. of Computer Science, Purdue University, feb. 1982. ## function [U R Q X Qnm1] = __qncmmva_nocs( N, S, V, m, Z ) assert( nargin == 5 ); all( any(S>0,2) ) || ... error( "S must contain at least a value >0 for each row" ); [C K] = size(S); ## ensure that the service times for multiserver nodes ## are class-independent for k=find(m>1) all( S(:,k) == S(1,k) ) || ... error( "Service times for FCFS node %d are not class-independent", k ); endfor ## Initialize results R = zeros( C, K ); X = zeros( 1, C ); D = S .* V; ## The multiclass MVA algorithm requires to store the queue lengths Q( ## _n_, k ) at center k where the population vector is _n_. The space ## required would be K*prod(N+1), but this can be reduced by ## considering that, at each iteration of the main MVA loop, the total ## number of requests is n; therefore it is sufficient to consider the ## first (C-1) components of vector _n_ to uniquely identify the cell ## containing Q( _n_, k ). See Schwetman for a better explanation. bufsize = prod((N+1)(1:end-1)); Q_next = Q = zeros( bufsize,K ); p = cell(1,K); for k=find(m>1) ## p{i}(j+1,k+1) is the probability to have j jobs at node i ## where the network is in state k p{k} = zeros( m(k)+1,bufsize ); p{k}(1,__getidx(N,0*N)) = 1; endfor Qnm1= zeros(C,K); ## Qnm1(c,k) is the number of requests in center k, provided that the population size is N-1_c (N is the total population vector). This value is needed by __qncmmva_cs. Qnm1 is only filled for M/M/1 or PS centers. The values are not computed for PS nodes dd = zeros(1,C); for c=find(N>0) h = zeros(1,C); h(c) = 1; dd(c) = __getidx(N,h)-1; endfor for n=1:sum(N) ## MVA iteration for population size n n_bar = zeros(1, C); const = min(n, N); mp = 0; while ( all(n_bar(C) <= const(C)) ) ## Fill the current configuration (algorithm 3b, p. 10, Schwetman) x=n-mp; i=1; while ( x>0 && i<=C ) n_bar(i) = min(x,const(i)); x -= n_bar(i); mp += n_bar(i); i += 1; endwhile idx = __getidx( N, n_bar ); R = S; ## Compute response time for LI servers k=find(m==1); for c=find(n_bar>0) ## idx-dd(c) is the index of element n_bar - 1_c R(c,k) = S(c,k).*(1 + Q( idx-dd(c), k ) ); Qnm1(c,k) = Q( idx-dd(c), k); ## for FCFS nodes with class-dependent service times, ## it is possible to use the following approximation ## (p. 469 Bolch et al.) ## ## R(c,k) = S(c,k) + sum( S(:,k) * Q(idx(:), k) ); ## R(c,k) = S(c,k) + sum( S(:,k) .* Q(idx, k) .* V(:,k) ) / sum(V(:,k)); endfor ## Compute response time for LD servers for k=find(m>1) j=0:m(k)-2; # range for c=find(n_bar > 0 ) R(c,k) = S(c,k)/m(k)*(1 + Q( idx-dd(c), k ) + ... dot(m(k)-j-1,p{k}(j+1,idx-dd(c)) ) ); endfor endfor X = n_bar ./ ( Z + dot(R,V,2)' ); # X(c) = N(c) / ( Z(c) + sum_k R(c,k) * V(c,k) ) ## Q_k = sum_c X(c) * R(c,k) * V(c,k) Q_next( idx, : ) = (X * (R .* V))'; ## Update marginal probabilities for LD servers for k=find(m>1) j = 1:m(k)-1; s = zeros(size(j)); for r=find(n_bar>0) s+=(D(r,k)*X(r)*p{k}(j,idx-dd(r)))'; endfor p{k}(j+1,idx) = s./j; p{k}(1,idx) = 1-1/m(k)*(dot( D(:,k),X ) + ... dot( m(k)-j, p{k}(j+1,idx) ) ); endfor #{ ## The following "if" is in the paper, but it makes the algorithm ## incorrect. Therefore, it is commented out. if ( n_bar(C) == N(C) ) break; endif #} ## Advance to next feasible configuration (Algorithm 3c, p. 10 Schwetman) i = 1; sw = true; while sw if ( ( mp==n || n_bar(i)==const(i)) && ( i14.323 %! assert( U, [14.323 0 .358; 0 4.707 .157], 1e-3 ); %! # I replaced 14.3->14.323 %! assert( X, [14.323 0 14.323; 0 .314 .314 ], 1e-3 ); %! # I replaced 14.3->14.323 %! assert( Q, [14.323 0 .677; 0 4.707 .293 ], 1e-3 ); %! assert( R, [1 0 .047; 0 15 .934 ], 1e-3 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law ## Example 9.5 p. 337, Bolch et al. %!test %! S = [ 0.2 0.4 1; 0.2 0.6 2 ]; %! V = [ 1 0.6 0.4; 1 0.3 0.7 ]; %! N = [ 2 1 ]; %! m = [ 2 1 -1 ]; %! [U R Q X] = qncmmva(N,S,V,m); %! assert( Q, [ 0.428 0.726 0.845; 0.108 0.158 0.734 ], 1e-3 ); %! assert( X(1,1), 2.113, 1e-3 ); # CHECK %! assert( X(2,1), 0.524, 1e-3 ); # CHECK %! assert( all(U(:)<=1) ); %! assert( Q, R.*X, 1e-5 ); # Little's Law ## Multiclass network with two classes; however, class 2 has 0 requests. ## Therefore, we check that the results for class 1 are the same as those ## computed by the single-class MVA %!test %! C = 2; # two classes %! K = 4; # four servers %! S = V = zeros(C,K); %! S(1,:) = linspace(1,2,K); %! S(2,:) = linspace(2,3,K); %! V(1,:) = linspace(4,1,K); %! V(2,:) = linspace(6,3,K); %! N = [10 0]; # class 2 has no customers %! [U1 R1 Q1 X1] = qncmmva(N,S,V); %! [U2 R2 Q2 X2] = qncsmva(N(1),S(1,:),V(1,:)); %! assert( U1(1,:), U2, 1e-5 ); %! assert( R1(1,:), R2, 1e-5 ); %! assert( Q1(1,:), Q2, 1e-5 ); %! assert( X1(1,:), X2, 1e-5 ); ## This is example 5(b) page 7 of ## http://docs.lib.purdue.edu/cstech/259/ ## "Testing network-of-queues software", technical report CSD-TR 330, %!test %! Z = [1 15]; %! V = [1; 1]; %! S = [.025; .5]; %! N = [15; 5]; %! [U R Q X] = qncmmva(N, S, V, 1, Z); %! assert( U, [.358; .157], 1e-3 ); %! assert( Q, [.677; .293], 1e-3 ); %! assert( X, [14.323; .314], 1e-3 ); ## NOTE: X(1,1) = 14.3 in Schwetman %! assert( R, [.047; .934], 1e-3 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law ## This is example of Figure 6, page 9 of ## http://docs.lib.purdue.edu/cstech/259/ ## "Testing network-of-queues software", technical report CSD-TR 330, %!test %! C = 2; %! K = 6; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = P(2,1,2,2) = 1; %! P(1,2,1,3) = P(1,2,1,4) = P(1,2,1,5) = P(1,2,1,6) = .25; %! P(2,2,2,3) = P(2,2,2,4) = P(2,2,2,5) = P(2,2,2,6) = .25; %! P(1,3,1,1) = P(1,4,1,1) = P(1,5,1,1) = P(1,6,1,1) = .9; %! P(1,3,1,2) = P(1,4,1,2) = P(1,5,1,2) = P(1,6,1,2) = .1; %! P(2,3,2,1) = P(2,4,2,1) = P(2,5,2,1) = P(2,6,2,1) = .05; %! P(2,3,2,2) = P(2,4,2,2) = P(2,5,2,2) = P(2,6,2,2) = .95; %! N = [40 4]; %! S = [ 5.0 .010 .035 .035 .035 .035; ... %! 10.0 .100 .035 .035 .035 .035 ]; %! V = qncmvisits(P); %! [U R Q X] = qncmmva(N, S, V, [-1 1 1 1 1 1]); %! # The results below were computed with JMVA; the numbers %! # in the paper appears to be incorrect. %! assert( U, [39.457941 0.087684 0.076724 0.076724 0.076724 0.076724; ... %! 2.772704 0.554541 0.048522 0.048522 0.048522 0.048522 ], 1e-5 ); %! assert( R.*V, [5 0.024363 0.011081 0.011081 0.011081 0.011081; ... %! 10 3.636155 0.197549 0.197549 0.197549 0.197549 ], 1e-5 ); %! assert( Q(:,1), [39.457941 2.772704]', 1e-5 ); %! assert( Q(:,2), [0.192262 1.008198]', 1e-5 ); %! assert( Q(:,3), [0.087449 0.054775]', 1e-5 ); %! assert( Q(:,4), Q(:,5), 1e-5 ); %! assert( Q(:,5), Q(:,6), 1e-5 ); %! assert( X(:,1), [7.891588 0.277270]', 1e-5 ); %! assert( X(:,2), [8.768431 5.545407]', 1e-5 ); %! assert( X(:,3), [2.192108 1.386352]', 1e-5 ); %! assert( X(:,4), X(:,5), 1e-5 ); %! assert( X(:,5), X(:,6), 1e-5 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law ## If there is no class switching, we must get the same results as ## the plain application of multiclass MVA %!test %! C = 2; # two classes %! K = 4; # four servers %! C = 2; K = 4; %! P = zeros(C,K,C,K); %! S = zeros(C,K); %! %! # Routing %! %! # class 1 routing %! P(1,1,1,1) = .05; %! P(1,1,1,2) = .45; %! P(1,1,1,3) = .5; %! P(1,2,1,1) = 1; %! P(1,3,1,1) = 1; %! # class 2 routing %! P(2,1,2,1) = .01; %! P(2,1,2,3) = .5; %! P(2,1,2,4) = .49; %! P(2,3,2,1) = 1; %! P(2,4,2,1) = 1; %! %! # Compute visits %! %! V = qncmvisits(P); %! %! # Define population and service times %! %! N = [3 2]; %! S = [0.01 0.09 0.10 0.08; ... %! 0.05 0.09 0.10 0.08]; %! [U1 R1 Q1 X1] = qncmmva(N,S,V); # this invokes __qncmmva_nocs %! [U2 R2 Q2 X2] = qncmmva(N,S,P); # this invokes __qncmmva_cs %! assert( U2, U1, 1e-5 ); %! assert( R2, R1, 1e-5 ); %! assert( Q2, Q1, 1e-5 ); %! assert( X2, X1, 1e-5 ); ## Example from table 5, p. 23, Herb Schwetman, "Implementing the Mean ## Value Algorith for the Solution of Queueing Network Models", ## Technical Report CSD-TR-355, Department of Computer Sciences, Purdue ## University, feb 15, 1982. %!test %! S = [1 0 .025; 0 15 .5]; %! V = [1 0 1; 0 1 1]; %! N = [15 5]; %! m = [-1 -1 1]; %! [U R Q X] = qncmmva(N,S,V,m); %! assert( U, [14.323 0 .358; 0 4.707 .157], 1e-3 ); %! assert( R, [1.0 0 .047; 0 15 .934], 1e-3 ); %! assert( Q, [14.323 0 .677; 0 4.707 .293], 1e-3 ); %! assert( X, [14.323 0 14.323; 0 .314 .314], 1e-3 ); ## Same test as above, but using routing probabilities instead of ## visits. Also, reordered the nodes such that server 1 is the PS node ## labeled "Sys 3" in the example; server 2 is the IS labeled "APL1" and ## server e is the IS labeled "IMS2" %!test %! S = [.025 1 15; .5 1 15 ]; %! P = zeros(2,3,2,3); %! P(1,1,1,2) = P(1,2,1,1) = 1; %! P(2,1,2,3) = P(2,3,2,1) = 1; %! N = [15 5]; %! m = [1 -1 -1]; %! r = [1 1]; # reference station is station 1 %! [U R Q X] = qncmmva(N,S,P,r,m); %! # I replaced 14.3->14.323 %! assert( U, [0.358 14.323 0; 0.156 0 4.707], 1e-3 ); %! # I replaced 14.3->14.323 %! assert( X, [14.323 14.3230 0; .314 0 .314 ], 1e-3 ); %! # I replaced 14.3->14.323 %! assert( Q, [.677 14.323 0; .293 0 4.707], 1e-3 ); %! assert( R, [.047 1 15.0; .934 1 15.0], 1e-3 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law ## Example figure 9 Herb Schwetman "Implementing the Mean ## Value Algorith for the Solution of Queueing Network Models", ## Technical Report CSD-TR-355, Department of Computer Sciences, Purdue ## University, feb 15, 1982. %!test %! C = 2; K = 3; %! S = [.01 .07 .10; ... %! .05 .07 .10 ]; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = .7; %! P(1,1,1,3) = .2; %! P(1,1,2,1) = .1; %! P(2,1,2,2) = .3; %! P(2,1,2,3) = .5; %! P(2,1,1,1) = .2; %! P(1,2,1,1) = P(2,2,2,1) = 1; %! P(1,3,1,1) = P(2,3,2,1) = 1; %! N = [3 0]; %! [U R Q X] = qncmmva(N, S, P); %! assert( R, [.015 .133 .163; .073 .133 .163], 1e-3 ); %! assert( X, [12.609 8.826 2.522; 6.304 1.891 3.152], 1e-3 ); %! assert( Q, [.185 1.175 .412; .462 .252 .515], 1e-3 ); %! assert( U, [.126 .618 .252; .315 .132 .315], 1e-3 ); ## Example from Schwetman (figure 7, page 9 of ## http://docs.lib.purdue.edu/cstech/259/ ## "Testing network-of-queues software, technical report CSD-TR 330, ## Purdue University). Note that the results for that network (table 9 ## of the reference above) seems to be wrong. The "correct" results ## below have been computed using the multiclass MVA implementation of ## JMT (http://jmt.sourceforge.net/) %!test %! V = [ 1.00 0.45 0.50 0.00; ... %! 1.00 0.00 0.50 0.49 ]; %! N = [3 2]; %! S = [0.01 0.09 0.10 0.08; ... %! 0.05 0.09 0.10 0.08]; %! [U R Q X] = qncmmva(N, S, V); %! assert( U, [ 0.1215 0.4921 0.6075 0.0000; ... %! 0.3433 0.0000 0.3433 0.2691 ], 1e-4 ); %! assert( Q, [ 0.2131 0.7539 2.0328 0.0000; ... %! 0.5011 0.0000 1.1839 0.3149 ], 1e-4 ); %! assert( R.*V, [0.0175 0.0620 0.1672 0.0000; ... %! 0.0729 0.0000 0.1724 0.0458 ], 1e-4 ); %! assert( X, [12.1517 5.4682 6.0758 0.0000; ... %! 6.8669 0.0000 3.4334 3.3648 ], 1e-4 ); ## The following test case was used in a bug report from F. Paolieri. It ## consists of a three-class network with four nodes. There is just ## one job for each class n; that job visits node 1 and node 1+n. ## Singe service times at nodes 2:4 are all the same, and service time ## at node 1 is class-independent, we expect that all performance ## measures for nodes 2:4 are equal. %!test %! N = [1 1 1]; %! S = [0.20000 0.02000 0.00000 0.00000; %! 0.20000 0.00000 0.02000 0.00000; %! 0.20000 0.00000 0.00000 0.02000]; %! V = [1 1 0 0; %! 1 0 1 0; %! 1 0 0 1]; %! [U R Q X] = qncmmva(N,S,V); %! assert( Q(1,2), Q(2,3), 1e-5); %! assert( Q(2,3), Q(3,4), 1e-5); %! assert( abs(max(Q(:,1)) - min(Q(:,1))) < 1e-5 ); ## This example is from G. Casale and G. Serazzi. Quantitative system ## evaluation with java modeling tools. In Proceedings of the second ## joint WOSP/SIPEW international conference on Performance engineering, ## ICPE '11, pages 449-454, New York, NY, USA, 2011. ACM %!demo %! Ntot = 100; # total population size %! b = linspace(0.1,0.9,10); # fractions of class-1 requests %! S = [20 80 31 14 23 12; ... %! 90 30 33 20 14 7]; %! V = ones(size(S)); %! X1 = X1 = XX = zeros(size(b)); %! R1 = R2 = RR = zeros(size(b)); %! for i=1:length(b) %! N = [fix(b(i)*Ntot) Ntot-fix(b(i)*Ntot)]; %! # printf("[%3d %3d]\n", N(1), N(2) ); %! [U R Q X] = qncmmva( N, S, V ); %! X1(i) = X(1,1) / V(1,1); %! X2(i) = X(2,1) / V(2,1); %! XX(i) = X1(i) + X2(i); %! R1(i) = dot(R(1,:), V(1,:)); %! R2(i) = dot(R(2,:), V(2,:)); %! RR(i) = Ntot / XX(i); %! endfor %! subplot(2,1,1); %! plot(b, X1, ";Class 1;", "linewidth", 2, ... %! b, X2, ";Class 2;", "linewidth", 2, ... %! b, XX, ";System;", "linewidth", 2 ); %! legend("location","south"); legend("boxoff"); %! ylabel("Throughput"); %! subplot(2,1,2); %! plot(b, R1, ";Class 1;", "linewidth", 2, ... %! b, R2, ";Class 2;", "linewidth", 2, ... %! b, RR, ";System;", "linewidth", 2 ); %! legend("location","south"); legend("boxoff"); %! xlabel("Population mix \\beta for Class 1"); %! ylabel("Resp. Time"); %!demo %! S = [1 0 .025; 0 15 .5]; %! P = zeros(2,3,2,3); %! P(1,1,1,3) = P(1,3,1,1) = 1; %! P(2,2,2,3) = P(2,3,2,2) = 1; %! V = qncmvisits(P,[3 3]); # reference station is station 3 %! N = [15 5]; %! m = [-1 -1 1]; %! [U R Q X] = qncmmva(N,S,V,m) ## Example shown on Figure 9: Herb Schwetman, "Implementing the Mean ## Value Algorith for the Solution of Queueing Network Models", ## Technical Report CSD-TR-355, Department of Computer Sciences, Purdue ## University, feb 15, 1982. %!demo %! C = 2; K = 3; %! S = [.01 .07 .10; ... %! .05 .07 .10 ]; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = .7; P(1,1,1,3) = .2; P(1,1,2,1) = .1; %! P(2,1,2,2) = .3; P(2,1,2,3) = .5; P(2,1,1,1) = .2; %! P(1,2,1,1) = P(2,2,2,1) = 1; %! P(1,3,1,1) = P(2,3,2,1) = 1; %! N = [3 0]; %! [U R Q X] = qncmmva(N, S, P) %!demo %! S = [10 7 5 4; %! 5 2 4 6]; %! NN = 100; %! Xl_aba = Xu_aba = Xl_bsb = Xu_bsb = Xl_cb = Xu_cb = Xmva = Rmva = zeros(NN,2); %! for n=1:NN %! N=[n,10]; %! [a b] = qncmaba(N,S); %! Xl_aba(n,:) = a; Xu_aba(n,:) = b; %! [a b] = qncmbsb(N,S); %! Xl_bsb(n,:) = a; Xu_bsb(n,:) = b; %! [a b] = qncmcb(N,S); %! Xl_cb(n,:) = a; Xu_cb(n,:) = b; %! [U R Q X] = qncmmva(N,S,ones(size(S))); %! Xmva(n,:) = X(:,1)'; %! endfor %! subplot(1,2,1); %! plot(1:NN, Xl_aba(:,1), "--k", %! 1:NN, Xu_aba(:,1), "--k;ABA;", %! 1:NN, Xu_bsb(:,1), ":k;BSB;", %! 1:NN, Xl_cb(:,1), "-.k", %! 1:NN, Xu_cb(:,1), "-.k;CB;", %! 1:NN, Xmva(:,1), "k;MVA;", "linewidth", 2); %! xlabel("N. of requests"); %! ylim([0, 0.2]); %! title("Class 1 throughput"); legend("boxoff"); %! subplot(1,2,2); %! plot(1:NN, Xl_aba(:,2), "--k", %! 1:NN, Xu_aba(:,2), "--k;ABA;", %! 1:NN, Xu_bsb(:,2), ":k;BSB;", %! 1:NN, Xl_cb(:,2), "-.k", %! 1:NN, Xu_cb(:,2), "-.k;CB;", %! 1:NN, Xmva(:,2), "-k;MVA;", "linewidth", 2); %! xlabel("N. of requests"); %! ylim([0, 0.2]); %! title("Class 2 throughput"); %! legend("boxoff"); %! legend("location", "east"); queueing/inst/qncmcb.m0000664000175000017500000001215414620404470014664 0ustar morenomoreno## Copyright (C) 2012, 2016, 2018, 2020, 2022 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmcb (@var{N}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmcb (@var{N}, @var{S}, @var{V}) ## ## @cindex multiclass network, closed ## @cindex closed multiclass network ## @cindex bounds, composite ## @cindex composite bounds ## ## Compute Composite Bounds (CB) on system throughput and response time for closed multiclass networks. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N}(c) ## number of class @math{c} requests in the system. ## ## @item @var{D}(c, k) ## class @math{c} service demand ## at center @math{k} (@code{@var{S}(c,k) @geq{} 0}). ## ## @item @var{S}(c, k) ## mean service time of class @math{c} ## requests at center @math{k} (@code{@var{S}(c,k) @geq{} 0}). ## ## @item @var{V}(c,k) ## average number of visits of class @math{c} ## requests to center @math{k} (@code{@var{V}(c,k) @geq{} 0}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl}(c) ## @itemx @var{Xu}(c) ## Lower and upper bounds on class @math{c} throughput. ## ## @item @var{Rl}(c) ## @itemx @var{Ru}(c) ## Lower and upper bounds on class @math{c} response time. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Teemu Kerola, @cite{The Composite Bound Method (CBM) for Computing ## Throughput Bounds in Multiple Class Environments}, Performance ## Evaluation Vol. 6, Issue 1, March 1986, DOI ## @uref{http://dx.doi.org/10.1016/0166-5316(86)90002-7, ## 10.1016/0166-5316(86)90002-7}. Also available as ## @uref{http://docs.lib.purdue.edu/cstech/395/, Technical Report ## CSD-TR-475}, Department of Computer Sciences, Purdue University, mar ## 13, 1984 (Revised Aug 27, 1984). ## @end itemize ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [Xl Xu Rl Ru] = qncmcb( varargin ) if ( nargin < 2 || nargin > 3 ) print_usage(); endif [err N S V m Z] = qncmchkparam( varargin{:} ); isempty(err) || error(err); all(m == 1) || ... error("this function only supports single-server FCFS centers"); all(Z == 0) || ... error("this function does not support think time"); [C K] = size(S); D = S .* V; [Xl] = qncmbsb(N, D); Xu = zeros(1,C); D_max = max(D,[],2)'; for r=1:C ## This is equation (13) from T. Kerola, The Composite Bound Method ## (CBM) for Computing Throughput Bounds in Multiple Class ## Environments, Technical Report CSD-TR-475, Purdue University, ## march 13, 1984 (revised august 27, 1984) ## http://docs.lib.purdue.edu/cstech/395/ ## The only modification here is to apply also the upper bound ## 1/D_max(r). s = (1:C != r); # boolean array tmp = (1 - Xl(s)*D(s,:)) ./ D(r,:); Xu(r) = min([tmp 1/D_max(r)]); endfor Rl = N ./ Xu; Ru = N ./ Xl; endfunction %!test %! S = [10 7 5 4; ... %! 5 2 4 6]; %! NN=20; %! Xl = Xu = Rl = Ru = Xmva = Rmva = zeros(NN,2); %! for n=1:NN %! N=[n,10]; %! [a b c d] = qncmcb(N,S); %! Xl(n,:) = a; Xu(n,:) = b; Rl(n,:) = c; Ru(n,:) = d; %! [U R Q X] = qncmmva(N,S,ones(size(S))); %! Xmva(n,:) = X(:,1)'; Rmva(n,:) = sum(R,2)'; %! endfor %! assert( all(Xl <= Xmva) ); %! assert( all(Xu >= Xmva) ); %! assert( all(Rl <= Rmva) ); %! assert( all(Xu >= Xmva) ); %!demo %! S = [10 7 5 4; ... %! 5 2 4 6]; %! NN=20; %! Xl = Xu = Rl = Ru = Xmva = Rmva = zeros(NN,2); %! for n=1:NN %! N=[n,10]; %! [a b c d] = qncmcb(N,S); %! Xl(n,:) = a; Xu(n,:) = b; Rl(n,:) = c; Ru(n,:) = d; %! [U R Q X] = qncmmva(N,S,ones(size(S))); %! Xmva(n,:) = X(:,1)'; Rmva(n,:) = sum(R,2)'; %! endfor %! subplot(2,2,1); %! plot(1:NN,Xl(:,1), 1:NN,Xu(:,1), 1:NN,Xmva(:,1), ";MVA;", "linewidth", 2); %! ylim([0, 0.2]); %! title("Class 1 throughput"); legend("boxoff"); %! subplot(2,2,2); %! plot(1:NN,Xl(:,2), 1:NN,Xu(:,2), 1:NN,Xmva(:,2), ";MVA;", "linewidth", 2); %! ylim([0, 0.2]); %! title("Class 2 throughput"); legend("boxoff"); %! subplot(2,2,3); %! plot(1:NN,Rl(:,1), 1:NN,Ru(:,1), 1:NN,Rmva(:,1), ";MVA;", "linewidth", 2); %! ylim([0, 700]); %! title("Class 1 response time"); legend("location", "northwest"); legend("boxoff"); %! subplot(2,2,4); %! plot(1:NN,Rl(:,2), 1:NN,Ru(:,2), 1:NN,Rmva(:,2), ";MVA;", "linewidth", 2); %! ylim([0, 700]); %! title("Class 2 response time"); legend("location", "northwest"); legend("boxoff"); queueing/inst/qncmpopmix.m0000664000175000017500000001154514620404470015617 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {pop_mix =} qncmpopmix (@var{k}, @var{N}) ## ## @cindex population mix ## @cindex closed network, multiple classes ## ## Return the set of population mixes for a closed multiclass queueing ## network with exactly @var{k} customers. Specifically, given a ## closed multiclass QN with @math{C} customer classes, where there ## are @code{@var{N}(c)} class @math{c} requests, @math{c = 1, @dots{}, C} ## a @math{k}-mix @math{M} is a vector of length @math{C} with the following ## properties: ## ## @itemize ## @item @math{0 @leq{} M_c @leq{} @var{N}(c)} for all @math{c = 1, @dots{}, C}; ## @item @math{\sum_{c=1}^C M_c = k} ## @end itemize ## ## In other words, a @math{k}-mix is an allocation of @math{k} ## requests to @math{C} classes such that the number of requests ## assigned to class @math{c} does not exceed the maximum value ## @code{@var{N}(c)}. ## ## @var{pop_mix} is a matrix with @math{C} columns, such ## that each row represents a valid mix. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{k} ## Size of the requested mix (scalar, @code{@var{k} @geq{} 0}). ## ## @item @var{N}(c) ## number of class @math{c} requests (@code{@var{k} @leq{} sum(@var{N})}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{pop_mix}(i,c) ## number of class @math{c} requests in the @math{i}-th population ## mix. The number of mixes is @code{rows(@var{pop_mix})}. ## ## @end table ## ## If you are interested in the number of @math{k}-mixes only, you can ## use the funcion @code{qnmvapop}. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Herb Schwetman, @cite{Implementing the Mean Value Algorithm for the ## Solution of Queueing Network Models}, Technical Report ## @uref{http://docs.lib.purdue.edu/cstech/286/, 80-355}, Department of Computer ## Sciences, Purdue University, revised February 15, 1982. ## @end itemize ## ## The slightly different problem of enumerating all tuples @math{k_1, ## @dots{}, k_N} such that @math{\sum_i k_i = k} and @math{k_i ## @geq{} 0}, for a given @math{k @geq{} 0} has been described in ## S. Santini, @cite{Computing the Indices for a Complex Summation}, ## unpublished report, available at ## @url{http://arantxa.ii.uam.es/~ssantini/writing/notes/s668_summation.pdf} ## ## @seealso{qncmnpop} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function pop_mix = qncmpopmix( k, population ) if ( nargin != 2 ) print_usage(); endif isvector( population ) && all( population>=0 ) || ... error( "N must be an array >=0" ); R = length(population); # number of classes ( isscalar(k) && k >= 0 && k <= sum(population) ) || ... error( "valid range for k is [0, %d]", sum(population)); N = zeros(1, R); const = min(k, population); mp = 0; pop_mix = []; # Init result while ( N(R) <= const(R) ) x=k-mp; ## Fill the current configuration i=1; while ( x>0 && i<=R ) N(i) = min(x,const(i)); x = x-N(i); mp = mp+N(i); i = i+1; endwhile ## here the configuration is filled. add it to the set of mixes assert( sum(N), k ); pop_mix = [pop_mix; N]; ## advance to the next feasible configuration i = 1; sw = true; while sw if ( ( mp==k || N(i)==const(i)) && ( i. ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{M} =} ctmctaexps (@var{Q}, @var{t}, @var{p0}) ## @deftypefnx {Function File} {@var{M} =} ctmctaexps (@var{Q}, @var{p0}) ## ## @cindex Markov chain, continuous time ## @cindex time-alveraged sojourn time, CTMC ## @cindex continuous time Markov chain ## @cindex CTMC ## ## Compute the @emph{time-averaged sojourn time} @code{@var{M}(i)}, ## defined as the fraction of the time interval @math{[0,t]} (or until ## absorption) spent in state @math{i}, assuming that the state ## occupancy probabilities at time 0 are @var{p}. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{Q}(i,j) ## Infinitesimal generator matrix. @code{@var{Q}(i,j)} is the transition ## rate from state @math{i} to state @math{j}, ## @math{1 @leq{} i,j @leq{} N}, @math{i \neq j}. The ## matrix @var{Q} must also satisfy the condition @math{\sum_{j=1}^N Q_{i,j} = 0} ## ## @item @var{t} ## Time. If omitted, the results are computed until absorption. ## ## @item @var{p0}(i) ## initial state occupancy probabilities. @code{@var{p0}(i)} is the ## probability that the system is in state @math{i} at time 0, @math{i ## = 1, @dots{}, N} ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{M}(i) ## When called with three arguments, @code{@var{M}(i)} is the expected ## fraction of the interval @math{[0,t]} spent in state @math{i} ## assuming that the state occupancy probability at time zero is ## @var{p}. When called with two arguments, @code{@var{M}(i)} is the ## expected fraction of time until absorption spent in state @math{i}; ## in this case the mean time to absorption is @code{sum(@var{M})}. ## ## @end table ## ## @seealso{ctmcexps} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function M = ctmctaexps( Q, varargin ) persistent epsilon = 10*eps; if ( nargin < 2 || nargin > 3 ) print_usage(); endif L = ctmcexps(Q,varargin{:}); M = L ./ repmat(sum(L,2),1,columns(L)); endfunction %!test %! Q = [ 0 0.1 0 0; ... %! 0.9 0 0.1 0; ... %! 0 0.9 0 0.1; ... %! 0 0 0 0 ]; %! Q -= diag( sum(Q,2) ); %! M = ctmctaexps(Q, [1 0 0 0]); %! assert( sum(M), 1, 10*eps ); %!demo %! lambda = 0.5; %! N = 4; %! birth = lambda*linspace(1,N-1,N-1); %! death = zeros(1,N-1); %! Q = diag(birth,1)+diag(death,-1); %! Q -= diag(sum(Q,2)); %! t = linspace(1e-5,30,100); %! p = zeros(1,N); p(1)=1; %! M = zeros(length(t),N); %! for i=1:length(t) %! M(i,:) = ctmctaexps(Q,t(i),p); %! endfor %! clf; %! plot(t, M(:,1), ";State 1;", "linewidth", 2, ... %! t, M(:,2), ";State 2;", "linewidth", 2, ... %! t, M(:,3), ";State 3;", "linewidth", 2, ... %! t, M(:,4), ";State 4 (absorbing);", "linewidth", 2 ); %! legend("location","east"); legend("boxoff"); %! xlabel("Time"); %! ylabel("Time-averaged Expected sojourn time"); ## This example is from: David I. Heimann, Nitin Mittal, Kishor S. Trivedi, ## "Availability and Reliability Modeling for Computer Systems", sep 1989, ## section 2.5 %!demo %! sec = 1; %! min = sec*60; %! hour = 60*min; %! day = 24*hour; %! %! # state space enumeration {2, RC, RB, 1, 0} %! a = 1/(10*min); # 1/a = duration of reboot (10 min) %! b = 1/(30*sec); # 1/b = reconfiguration time (30 sec) %! g = 1/(5000*hour); # 1/g = processor MTTF (5000 hours) %! d = 1/(4*hour); # 1/d = processor MTTR (4 hours) %! c = 0.9; # coverage %! Q = [ -2*g 2*c*g 2*(1-c)*g 0 0; ... %! 0 -b 0 b 0; ... %! 0 0 -a a 0; ... %! d 0 0 -(g+d) g; ... %! 0 0 0 d -d]; %! p = ctmc(Q); %! printf("System availability: %f\n",p(1)+p(4)); %! TT = linspace(0,1*day,101); %! PP = ctmctaexps(Q,TT,[1 0 0 0 0]); %! A = At = Abart = zeros(size(TT)); %! A(:) = p(1) + p(4); # steady-state availability %! for n=1:length(TT) %! t = TT(n); %! p = ctmc(Q,t,[1 0 0 0 0]); %! At(n) = p(1) + p(4); # instantaneous availability %! Abart(n) = PP(n,1) + PP(n,4); # interval base availability %! endfor %! clf; %! semilogy(TT,A,";Steady-state;", ... %! TT,At,";Instantaneous;", ... %! TT,Abart,";Interval base;"); %! ax = axis(); %! ax(3) = 1-1e-5; %! axis(ax); %! legend("boxoff"); queueing/inst/qncsmvablo.m0000664000175000017500000001403714620404470015570 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvablo (@var{N}, @var{S}, @var{M}, @var{P} ) ## ## @cindex queueing network with blocking ## @cindex blocking queueing network ## @cindex closed network, finite capacity ## @cindex MVABLO ## ## Approximate MVA algorithm for closed queueing networks with blocking. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## number of requests in the system. @var{N} must be strictly greater ## than zero, and less than the overall network capacity: @code{0 < ## @var{N} < sum(@var{M})}. ## ## @item @var{S}(k) ## average service time on server @math{k} (@code{@var{S}(k) > 0}). ## ## @item @var{M}(k) ## capacity of center @math{k}. The capacity is the maximum number of requests in a service ## center, including the request in service (@code{@var{M}(k) @geq{} 1}). ## ## @item @var{P}(i,j) ## probability that a request which completes ## service at server @math{i} will be transferred to server @math{j}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(k) ## center @math{k} utilization. ## ## @item @var{R}(k) ## average response time of service center @math{k}. ## ## @item @var{Q}(k) ## average number of requests in service center @math{k} (including ## the request in service). ## ## @item @var{X}(k) ## center @math{k} throughput. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Ian F. Akyildiz, @cite{Mean Value Analysis for Blocking Queueing ## Networks}, IEEE Transactions on Software Engineering, vol. 14, n. 2, ## april 1988, pp. 418--428. @uref{http://dx.doi.org/10.1109/32.4663, 10.1109/32.4663} ## @end itemize ## ## @seealso{qnopen, qnclosed} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qncsmvablo( K, S, M, P ) ## Note that we use "K" instead of "N" as the number of requests in ## order to be compliant with the paper by Akyildiz describing this ## algorithm. if ( nargin != 4 ) print_usage(); endif ( isscalar(K) && K > 0 ) || ... error( "K must be a positive integer" ); isvector(S) && all(S>0) || ... error ("S must be a vector > 0"); S = S(:)'; # make S a row vector N = length(S); ( isvector(M) && length(M) == N ) || ... error( "M must be a vector with %d elements", N ); all( M >= 1) || ... error( "M must be >= 1"); M = M(:)'; # make M a row vector (K < sum(M)) || ... error( "The population size K=%d exceeds the total system capacity %d", K, sum(M) ); [na err] = dtmcchkP(P); ( na>0 ) || ... error( err ); rows(P) == N || ... error("The number of rows of P must be equal to the length of S"); ## Note: in this implementation we make use of the same notation found ## in Akyildiz's paper cited in the REFERENCES above, with the minor ## exception of using 'v' instead of 'e' as the visit count vector. ## k_bar(i) is the average number of jobs in the i-th server, lambda ## is the network throughput, t_bar(i) is the mean residence time ## (time spent in queue and in service) for requests in the i-th ## service center. ## Initialization k_bar_m1 = zeros(1,N); # k_bar(k-1) BT = zeros(1,N); z = ones(1,N); lambda = 0; ## Computation of the visit counts v = qncsvisits(P); D = S .* v; # Service demand ## Main loop for k=1:K do ## t_bar_i(k) = S(i) *(z_i(k) + k_bar_i(k-1))+BT_i(k) t_bar = S .* ( z + k_bar_m1 ) + BT; lambda = k / dot(v,t_bar); k_bar = t_bar .* v * lambda; if ( any(k_bar>M) ) i = find( k_bar > M, 1 ); z(i) = 0; BT = BT + S(i) * ( v .* P(:,i)' ) / v(i); endif until( all(k_bar<=M) ); k_bar_m1 = k_bar; endfor R = t_bar; X = v * lambda; # Throughputs ## w_bar = t_bar - S - BT; # mean waiting time U = X .* S; Q = X .* R; endfunction %!test %! fail( "qncsmvablo( 10, [1 1], [4 5], [0 1; 1 0] )", "capacity"); %! fail( "qncsmvablo( 6, [1 1], [4 5], [0 1; 1 1] )", "stochastic"); %! fail( "qncsmvablo( 5, [1 1 1], [1 1], [0 1; 1 1] )", "3 elements"); %!test %! # This is the example on section v) p. 422 of the reference paper %! M = [12 10 14]; %! P = [0 1 0; 0 0 1; 1 0 0]; %! S = [1/1 1/2 1/3]; %! K = 27; %! [U R Q X]=qncsmvablo( K, S, M, P ); %! assert( R, [11.80 1.66 14.4], 1e-2 ); %!test %! # This is example 2, i) and ii) p. 424 of the reference paper %! M = [4 5 5]; %! S = [1.5 2 1]; %! P = [0 1 0; 0 0 1; 1 0 0]; %! K = 10; %! [U R Q X]=qncsmvablo( K, S, M, P ); %! assert( R, [6.925 8.061 4.185], 1e-3 ); %! K = 12; %! [U R Q X]=qncsmvablo( K, S, M, P ); %! assert( R, [7.967 9.019 8.011], 1e-3 ); %!test %! # This is example 3, i) and ii) p. 424 of the reference paper %! M = [8 7 6]; %! S = [0.2 1.2 1.4]; %! P = [ 0 0.5 0.5; 1 0 0; 1 0 0 ]; %! K = 10; %! [U R Q X] = qncsmvablo( K, S, M, P ); %! assert( R, [1.674 5.007 7.639], 1e-3 ); %! K = 12; %! [U R Q X] = qncsmvablo( K, S, M, P ); %! assert( R, [2.166 5.372 6.567], 1e-3 ); %!test %! # Network which never blocks, central server model %! M = [50 50 50]; %! S = [1 1/0.8 1/0.4]; %! P = [0 0.7 0.3; 1 0 0; 1 0 0]; %! K = 40; %! [U1 R1 Q1] = qncsmvablo( K, S, M, P ); %! V = qncsvisits(P); %! [U2 R2 Q2] = qncsmva( K, S, V ); %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 ); %! assert( Q1, Q2, 1e-5 ); queueing/inst/qncsgb.m0000664000175000017500000002177114620404470014703 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018, 2022 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}, @var{Ql}, @var{Qu}] =} qncsgb (@var{N}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}, @var{Ql}, @var{Qu}] =} qncsgb (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}, @var{Ql}, @var{Qu}] =} qncsgb (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}, @var{Ql}, @var{Qu}] =} qncsgb (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## ## @cindex bounds, geometric ## @cindex geometric bounds ## @cindex closed network ## ## Compute Geometric Bounds (GB) on system throughput, system response ## time and server queue lenghts for closed, single-class networks ## with @math{K} service centers and @math{N} requests. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## number of requests in the system (scalar, @code{@var{N} > 0}). ## ## @item @var{D}(k) ## service demand of service center @math{k} (vector of length ## @math{K}, @code{@var{D}(k) @geq{} 0}). ## ## @item @var{S}(k) ## mean service time at center @math{k} (vector of length @math{K}, ## @code{@var{S}(k) @geq{} 0}). ## ## @item @var{V}(k) ## visit ratio to center @math{k} ## (vector of length @math{K}, @code{@var{V}(k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k}. This function only supports ## @math{M/M/1} queues, therefore @var{m} must be ## @code{ones(size(S))}. ## ## @item @var{Z} ## external delay (think time, @code{@var{Z} @geq{} 0}, scalar). Default is 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl} ## @itemx @var{Xu} ## Lower and upper bound on the system throughput. If @code{@var{Z}>0}, ## these bounds are computed using @emph{Geometric Square-root Bounds} ## (GSB). If @code{@var{Z}==0}, these bounds are computed using @emph{Geometric Bounds} (GB) ## ## @item @var{Rl} ## @itemx @var{Ru} ## Lower and upper bound on the system response time. These bounds ## are derived from @var{Xl} and @var{Xu} using Little's Law: ## @code{@var{Rl} = @var{N} / @var{Xu} - @var{Z}}, ## @code{@var{Ru} = @var{N} / @var{Xl} - @var{Z}} ## ## @item @var{Ql}(k) ## @itemx @var{Qu}(k) ## lower and upper bounds of center @math{K} queue length. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Casale, R. R. Muntz, G. Serazzi, @cite{Geometric Bounds: a ## Non-Iterative Analysis Technique for Closed Queueing Networks}, IEEE ## Transactions on Computers, 57(6):780-794, June ## 2008. @uref{http://doi.ieeecomputersociety.org/10.1109/TC.2008.37, ## 10.1109/TC.2008.37} ## @end itemize ## ## In this implementation we set @math{X^+} and @math{X^-} as the upper ## and lower Asymptotic Bounds as computed by the @command{qncsab} ## function, respectively. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [X_lower X_upper R_upper R_lower Q_lower Q_upper] = qncsgb( varargin ) ## This implementation is based on the paper: G.Casale, R.R.Muntz, ## G.Serazzi. Geometric Bounds: a Noniterative Analysis Technique for ## Closed Queueing Networks IEEE Transactions on Computers, ## 57(6):780-794, Jun 2008. ## http://doi.ieeecomputersociety.org/10.1109/TC.2008.37 ## The original paper uses the symbol "L" instead of "D" to denote the ## loadings of service centers. In this function we adopt the same ## notation as the paper. if ( nargin < 2 || ( nargin > 5 && nargin != 7 ) ) print_usage(); endif [err N S V m Z] = qncschkparam( varargin{:} ); isempty(err) || error(err); ## This function requires N>0 N > 0 || ... error( "N must be > 0" ); all(m==1) || ... error("this function only supports single server nodes"); L = S .* V; L_tot = sum(L); L_max = max(L); M = length(L); if ( nargin < 6 ) [X_minus X_plus] = qncsaba(N,L,ones(size(L)),m,Z); else X_minus = varargin{6}; X_plus = varargin{7}; endif ##[X_minus X_plus] = [0 1/L_max]; [Q_lower Q_upper] = __compute_Q( N, L, Z, X_plus, X_minus); [Q_lower_Nm1 Q_upper_Nm1] = __compute_Q( N-1, L, Z, X_plus, X_minus); if ( Z > 0 ) ## Use Geometric Square-root Bounds (GSB) i = find(L=0) ) || error( "N is not valid" ); L_tot = sum(L); L_max = max(L); M = length(L); m_max = sum( L == L_max ); y = Y = zeros(1,M); ## first, handle the case of servers with loading less than the ## maximum that is, L(i) < L_max i=find(L 0" ); %! fail( "qncsgb( -1, [1 2])", "nonnegative" ); %! fail( "qncsgb( 1, [1 2],1,[1 -1])", "single server" ); %!# shared test function %!function test_gb( D, expected, Z=0 ) %! for i=1:rows(expected) %! N = expected(i,1); %! [X_lower X_upper Q_lower Q_upper] = qncsgb(N,D,1,1,Z); %! X_exp_lower = expected(i,2); %! X_exp_upper = expected(i,3); %! assert( [N X_lower X_upper], [N X_exp_lower X_exp_upper], 1e-4 ) %! endfor %!## %! # table IV %! D = [ 0.1 0.1 0.09 0.08 ]; %! # N X_lower X_upper %! expected = [ 2 4.3040 4.3174; ... %! 5 6.6859 6.7524; ... %! 10 8.1521 8.2690; ... %! 20 9.0947 9.2431; ... %! 80 9.8233 9.8765 ]; %! test_gb(D, expected); %!## %! # table V %! D = [ 0.1 0.1 0.09 0.08 ]; %! Z = 1; %! # N X_lower X_upper %! expected = [ 2 1.4319 1.5195; ... %! 5 3.3432 3.5582; ... %! 10 5.7569 6.1410; ... %! 20 8.0856 8.6467; ... %! 80 9.7147 9.8594]; %! test_gb(D, expected, Z); %!test %! P = [0 0.3 0.7; 1 0 0; 1 0 0]; %! S = [1 0.6 0.2]; %! m = ones(1,3); %! V = qncsvisits(P); %! Z = 2; %! Nmax = 20; %! tol = 1e-5; # compensate for numerical inaccuracies %! ## Test case with Z>0 %! for n=1:Nmax %! [X_gb_lower X_gb_upper NC NC Q_gb_lower Q_gb_upper] = qncsgb(n, S.*V, 1, 1, Z); %! [U R Q X] = qnclosed( n, S, V, m, Z ); %! X_mva = X(1)/V(1); %! assert( X_gb_lower <= X_mva+tol ); %! assert( X_gb_upper >= X_mva-tol ); %! assert( Q_gb_lower <= Q+tol ); # compensate for numerical errors %! assert( Q_gb_upper >= Q-tol ); # compensate for numerical errors %! endfor %!test %! P = [0 0.3 0.7; 1 0 0; 1 0 0]; %! S = [1 0.6 0.2]; %! V = qncsvisits(P); %! Nmax = 20; %! tol = 1e-5; # compensate for numerical inaccuracies %! ## Test case with Z=0 %! for n=1:Nmax %! [X_gb_lower X_gb_upper NC NC Q_gb_lower Q_gb_upper] = qncsgb(n, S.*V); %! [U R Q X] = qnclosed( n, S, V ); %! X_mva = X(1)/V(1); %! assert( X_gb_lower <= X_mva+tol ); %! assert( X_gb_upper >= X_mva-tol ); %! assert( Q_gb_lower <= Q+tol ); %! assert( Q_gb_upper >= Q-tol ); %! endfor queueing/inst/qncsconvld.m0000664000175000017500000001747514620404470015606 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsconvld (@var{N}, @var{S}, @var{V}) ## ## @cindex closed network ## @cindex normalization constant ## @cindex convolution algorithm ## @cindex load-dependent service center ## ## Convolution algorithm for product-form, single-class closed ## queueing networks with @math{K} general load-dependent service ## centers. ## ## This function computes steady-state performance measures for ## single-class, closed networks with load-dependent service centers ## using the convolution algorithm; the normalization constants are also ## computed. The normalization constants are returned as vector ## @code{@var{G}=[@var{G}(1), @dots{}, @var{G}(N+1)]} where ## @code{@var{G}(i+1)} is the value of @math{G(i)}. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## Number of requests in the system (@code{@var{N}>0}). ## ## @item @var{S}(k,n) ## mean service time at center @math{k} where there are @math{n} ## requests, @math{1 @leq{} n @leq{} N}. @code{@var{S}(k,n)} @math{= 1 / \mu_{k,n}}, where @math{\mu_{k,n}} is the service rate of center ## @math{k} when there are @math{n} requests. ## ## @item @var{V}(k) ## visit count of service center @math{k} ## (@code{@var{V}(k) @geq{} 0}). The length of @var{V} is the number of ## servers @math{K} in the network. ## ## @end table ## ## @strong{OUTPUT} ## ## @table @code ## ## @item @var{U}(k) ## center @math{k} utilization. ## ## @item @var{R}(k) ## average response time at center @math{k}. ## ## @item @var{Q}(k) ## average number of requests in center @math{k}. ## ## @item @var{X}(k) ## center @math{k} throughput. ## ## @item @var{G}(n) ## Normalization constants (vector). @code{@var{G}(n+1)} ## corresponds to @math{G(n)}, as array indexes in Octave start ## from 1. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Herb Schwetman, @cite{Some Computational Aspects of Queueing Network ## Models}, Technical Report ## @uref{http://docs.lib.purdue.edu/cstech/285/, CSD-TR-354}, Department ## of Computer Sciences, Purdue University, February 1981 (revised). ## ## @item ## M. Reiser, H. Kobayashi, @cite{On The Convolution Algorithm for ## Separable Queueing Networks}, In Proceedings of the 1976 ACM ## SIGMETRICS Conference on Computer Performance Modeling Measurement and ## Evaluation (Cambridge, Massachusetts, United States, March 29--31, ## 1976). SIGMETRICS '76. ACM, New York, NY, ## pp. 109--117. @uref{http://doi.acm.org/10.1145/800200.806187, 10.1145/800200.806187} ## @end itemize ## ## This implementation is based on G. Bolch, S. Greiner, H. de Meer and ## K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and ## Performance Evaluation with Computer Science Applications}, Wiley, ## 1998, pp. 313--317. Function @command{qncsconvld} is slightly ## different from the version described in Bolch et al. because it ## supports general load-dependent centers (while the version in the book ## does not). The modification is in the definition of function ## @code{F()} in @command{qncsconvld} which has been made similar to ## function @math{f_i} defined in Schwetman, @cite{Some Computational ## Aspects of Queueing Network Models}. ## ## @seealso{qncsconv} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X G] = qncsconvld( N, S, V ) if ( nargin != 3 ) print_usage(); endif ( isscalar(N) && N>0 ) || ... error( "N must be a positive scalar" ); K = N; # To be compliant with the reference, we denote K as the population size ( isvector(V) && all(V>=0) ) || ... error( "V must be a vector >=0" ); V = V(:)'; # Make V a row vector N = length(V); # Number of service centers if ( isnumeric(S) ) ( rows(S) == N && columns(S) == K) || ... error( sprintf("S size mismatch: is %dx%d, should be %dx%d", rows(S), columns(S),K,N ) ); all(S(:)>=0) || ... error( "S must be >=0" ); endif ## Initialization G_n = G_nm1 = zeros(1,K+1); G_n(1) = 1; F_n = zeros(N,K+1); F_n(:,1) = 1; for k=1:K G_n(k+1) = F_n(1,k+1) = F(1,k,V,S); endfor ## Main convolution loop for n=2:N G_nm1 = G_n; for k=2:K+1 F_n(n,k) = F(n,k-1,V,S); endfor G_n = conv( F_n(n,:), G_nm1(:) )(1:K+1); endfor ## Done computation of G(n,k). G = G_n; G = G(:)'; # ensure G is a row vector ## Computes performance measures X = V*G(K)/G(K+1); Q = U = zeros(1,N); for i=1:N G_N_i = zeros(1,K+1); G_N_i(1) = 1; for k=1:K j=1:k; G_N_i(k+1) = G(k+1)-dot( F_n(i,j+1), G_N_i(k-j+1) ); endfor k=0:K; p_i(k+1) = F_n(i,k+1)./G(K+1).*G_N_i(K-k+1); Q(i) = dot( k, p_i( k+1 ) ); U(i) = 1-p_i(1); endfor R = Q ./ X; endfunction %!test %! K=3; %! S = [ 1 1 1; 1 1 1 ]; %! V = [ 1 .667 .2 ]; %! fail( "qncsconvld(K,S,V)", "size mismatch" ); %!test %! # Example 8.1 p. 318 Bolch et al. %! K=3; %! S = [ 1/0.8 ./ [1 2 2]; %! 1/0.6 ./ [1 2 3]; %! 1/0.4 ./ [1 1 1] ]; %! V = [ 1 .667 .2 ]; %! [U R Q X G] = qncsconvld( K, S, V ); %! assert( G, [1 2.861 4.218 4.465], 5e-3 ); %! assert( X, [0.945 0.630 0.189], 1e-3 ); %! assert( Q, [1.290 1.050 0.660], 1e-3 ); %! assert( R, [1.366 1.667 3.496], 1e-3 ); %!test %! # Example 8.3 p. 331 Bolch et al. %! # compare results of convolution with those of mva %! K = 6; %! S = [ 0.02 0.2 0.4 0.6 ]; %! V = [ 1 0.4 0.2 0.1 ]; %! [U_mva R_mva Q_mva X_mva] = qncsmva(K, S, V); %! [U_con R_con Q_con X_con G] = qncsconvld(K, repmat(S',1,K), V ); %! assert( U_mva, U_con, 1e-5 ); %! assert( R_mva, R_con, 1e-5 ); %! assert( Q_mva, Q_con, 1e-5 ); %! assert( X_mva, X_con, 1e-5 ); %!test %! # Compare the results of convolution to those of mva %! S = [ 0.02 0.2 0.4 0.6 ]; %! K = 6; %! V = [ 1 0.4 0.2 0.1 ]; %! m = [ 1 5 2 1 ]; %! [U_mva R_mva Q_mva X_mva] = qncsmva(K, S, V); %! [U_con R_con Q_con X_con G] = qncsconvld(K, repmat(S',1,K), V); %! assert( U_mva, U_con, 1e-5 ); %! assert( R_mva, R_con, 1e-5 ); %! assert( Q_mva, Q_con, 1e-5 ); %! assert( X_mva, X_con, 1e-5 ); %!function r = S_function(k,n) %! M = [ 1/0.8 ./ [1 2 2]; %! 1/0.6 ./ [1 2 3]; %! 1/0.4 ./ [1 1 1] ]; %! r = M(k,n); %!test %! # Example 8.1 p. 318 Bolch et al. %! K=3; %! V = [ 1 .667 .2 ]; %! [U R Q X G] = qncsconvld( K, @S_function, V ); %! assert( G, [1 2.861 4.218 4.465], 5e-3 ); %! assert( X, [0.945 0.630 0.189], 1e-3 ); %! assert( Q, [1.290 1.050 0.660], 1e-3 ); %! assert( R, [1.366 1.667 3.496], 1e-3 ); ## result = F(i,j,v,S) ## ## Helper fuction to compute a generalization of equation F(i,j) as ## defined in Eq 7.61 p. 289 of Bolch, Greiner, de Meer, Trivedi ## "Queueing Networks and Markov Chains: Modeling and Performance ## Evaluation with Computer Science Applications", Wiley, 1998. This ## generalization is taken from Schwetman, "Some Computational Aspects ## of Queueing Network Models", Technical Report CSD-TR 354, Dept. of ## CS, Purdue University, Dec 1980 (see definition of f_i(n) on p. 7). function result = F(i,j,v,S) k_i = j; if ( k_i == 0 ) result = 1; else result = v(i)^k_i * prod(S(i,1:k_i)); endif endfunction queueing/inst/dtmcchkP.m0000664000175000017500000000431014620404470015151 0ustar morenomoreno## Copyright (C) 2011, 2012 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{r} @var{err}] =} dtmcchkP (@var{P}) ## ## @cindex Markov chain, discrete time ## @cindex DTMC ## @cindex discrete time Markov chain ## ## Check whether @var{P} is a valid transition probability matrix. ## ## If @var{P} is valid, @var{r} is the size (number of rows or columns) ## of @var{P}. If @var{P} is not a transition probability matrix, ## @var{r} is set to zero, and @var{err} to an appropriate error string. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [result err] = dtmcchkP( P ) if ( nargin != 1 ) print_usage(); endif result = 0; err = ""; if ( !issquare(P) ) err = "P is not a square matrix"; return; endif if ( any(P(:)<-eps) || norm( sum(P,2) - 1, "inf" ) > columns(P)*eps ) err = "P is not a stochastic matrix"; return; endif result = rows(P); endfunction %!test %! [r err] = dtmcchkP( [1 1 1; 1 1 1] ); %! assert( r, 0 ); %! assert( index(err, "square") > 0 ); %!test %! [r err] = dtmcchkP( [1 0 0; 0 0.5 0; 0 0 0] ); %! assert( r, 0 ); %! assert( index(err, "stochastic") > 0 ); %!test %! P = [0 1; 1 0]; %! assert( dtmcchkP(P), 2 ); %!test %! P = dtmcbd( linspace(0.1,0.4,10), linspace(0.4,0.1,10) ); %! assert( dtmcchkP(P), rows(P) ); %!test %! N = 1000; %! P = reshape( 1:N^2, N, N ); %! P(1:N+1:end) = 0; %! P = P ./ repmat(sum(P,2),1,N); %! assert( dtmcchkP(P), N ); queueing/inst/qnmknode.m0000664000175000017500000001247614620404470015244 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2023 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{Q} =} qnmknode (@var{"m/m/m-fcfs"}, @var{S}) ## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"m/m/m-fcfs"}, @var{S}, @var{m}) ## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"m/m/1-lcfs-pr"}, @var{S}) ## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/1-ps"}, @var{S}) ## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/1-ps"}, @var{S}, @var{s2}) ## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/inf"}, @var{S}) ## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/inf"}, @var{S}, @var{s2}) ## ## Creates a node; this function can be used together with ## @code{qnsolve}. It is possible to create either single-class nodes ## (where there is only one customer class), or multiple-class nodes ## (where the service time is given per-class). Furthermore, it is ## possible to specify load-dependent service times. String literals ## are case-insensitive, so for example @var{"-/g/inf"}, @var{"-/G/inf"} ## and @var{"-/g/INF"} are all equivalent. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{S} ## Mean service time. ## ## @itemize ## ## @item If @math{S} is a scalar, ## it is assumed to be a load-independent, class-independent service time. ## ## @item If @math{S} is a column vector, then @code{@var{S}(c)} is assumed to ## the the load-independent service time for class @math{c} customers. ## ## @item If @math{S} is a row vector, then @code{@var{S}(n)} is assumed to be ## the class-independent service time at the node, when there are @math{n} ## requests. ## ## @item Finally, if @var{S} is a two-dimensional matrix, then ## @code{@var{S}(c,n)} is assumed to be the class @math{c} service time ## when there are @math{n} requests at the node. ## ## @end itemize ## ## @item @var{m} ## Number of identical servers at the node. Default is @code{@var{m}=1}. ## ## @item @var{s2} ## Squared coefficient of variation for the service time. Default is 1.0. ## ## @end table ## ## The returned struct @var{Q} should be considered opaque to the client. ## ## @c The returned struct @var{Q} has the following fields: ## ## @c @table @var ## ## @c @item Q.node ## @c (String) type of the node; valid values are @code{"m/m/m-fcfs"}, ## @c @code{"-/g/1-lcfs-pr"}, @code{"-/g/1-ps"} (Processor-Sharing) ## @c and @code{"-/g/inf"} (Infinite Server, or delay center). ## ## @c @item Q.S ## @c Average service time. If @code{@var{Q}.S} is a vector, then ## @c @code{@var{Q}.S(i)} is the average service time at that node ## @c if there are @math{i} requests. ## ## @c @item Q.m ## @c Number of identical servers at a @code{"m/m/m-fcfs"}. Default is 1. ## ## @c @item Q.c ## @c Number of customer classes. Default is 1. ## ## @c @end table ## ## @seealso{qnsolve} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function Q = qnmknode( node, S, varargin ) ischar(node) || ... error( "Parameter \"node\" must be a string" ); node = tolower(node); isvector(S) || ismatrix(S) || ... error( "Parameter \"S\" must be a vector" ); m = 1; s2 = ones( size(S) ); if ( strcmp(node, "m/m/m-fcfs") ) ## M/M/k multiserver node if ( nargin > 3 ) print_usage(); endif if ( 3 == nargin ) m = varargin{1}; endif elseif ( strcmp(node, "m/m/1/k-fcfs") ) ## M/M/1/k finite capacity node if ( nargin > 3 ) print_usage(); endif if ( 3 == nargin ) k = varargin{1}; endif elseif ( strcmp(node, "-/g/1-lcfs-pr") ) ## -/G/1-LCFS-PR node if ( nargin != 2 && nargin != 3 ) print_usage(); endif if ( 3 == nargin ) s2 = varargin{1}; endif elseif ( strcmp(node, "-/g/1-ps") ) ## -/G/1-PS (processor sharing) node if ( nargin != 2 && nargin != 3 ) print_usage(); endif if ( 3 == nargin ) s2 = varargin{1}; endif elseif ( strcmp(node, "-/g/inf") ) ## -/G/inf (Infinite Server) node if ( nargin != 2 && nargin != 3 ) print_usage(); endif if ( 3 == nargin ) s2 = varargin{1}; endif else error( "Unknown node type \"%s\". node type must be one of \"m/m/m-fcfs\", \"-/g/1-lcfs-pr\", \"-/g/1-ps\" and \"-/g/inf\"", node ); endif ( isnumeric(m) && m>=1 ) || ... error("m must be >=1"); ( isnumeric(s2) && s2>= 0 ) || ... error("s2 must be >=0"); Q = struct( "node", node, "m", m, "S", S, "s2", s2, "c", rows(S), "comment", "" ); endfunction %!test %! fail( "qnmknode( 'pippo', 1 )", "must be one" ); %! fail( "qnmknode( '-/g/1-ps', 1, 1, 1)", "Invalid call" ); queueing/inst/qnomaba.m0000664000175000017500000000670414620404470015043 0ustar morenomoreno## Copyright (C) 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnomaba (@var{lambda}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Rl}] =} qnomaba (@var{lambda}, @var{S}, @var{V}) ## ## @cindex bounds, asymptotic ## @cindex open network ## @cindex multiclass network, open ## ## Compute Asymptotic Bounds for open, multiclass networks with @math{K} ## service centers and @math{C} customer classes. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda}(c) ## class @math{c} arrival rate to the system (vector of length ## @math{C}, @code{@var{lambda}(c) > 0}). ## ## @item @var{D}(c, k) ## class @math{c} service demand at center @math{k} (@math{C \times K} ## matrix, @code{@var{D}(c, k) @geq{} 0}). ## ## @item @var{S}(c, k) ## mean service time of class @math{c} requests at center @math{k} ## (@math{C \times K} matrix, @code{@var{S}(c, k) @geq{} 0}). ## ## @item @var{V}(c, k) ## mean number of visits of class @math{c} requests at center @math{k} ## (@math{C \times K} matrix, @code{@var{V}(c, k) @geq{} 0}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl}(c) ## @item @var{Xu}(c) ## lower and upper bounds of class @math{c} throughput. ## @code{@var{Xl}(c)} is always @math{0} since there can be no lower ## bound on the throughput of open networks (vector of length ## @math{C}). ## ## @item @var{Rl}(c) ## @item @var{Ru}(c) ## lower and upper bounds of class @math{c} response time. ## @code{@var{Ru}(c)} is always @code{+inf} since there can be no ## upper bound on the response time of open networks (vector of length ## @math{C}). ## ## @end table ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [X_lower X_upper R_lower R_upper] = qnomaba( lambda, S, V ) if ( nargin < 2 || nargin > 3 ) print_usage(); endif (isvector(lambda) && length(lambda)>0) || ... error( "lambda must be a nonempty vector" ); all(lambda > 0) || ... error( "lambda must contain positive values" ); lambda = lambda(:)'; C = length(lambda); ( ismatrix(S) && rows(S)==C ) || ... error( "S/D must be a matrix >=0 with %d rows", C ); all(S(:)>=0) || ... error( "S/D must contain nonnegative values" ); K = columns(S); if ( nargin < 3 ) V = ones(size(S)); else ( ismatrix(V) && size_equal(S,V) ) || ... error( "V must be a %d x %d matrix", C, K); all(V(:)>=0) || ... error( "V must contain nonnegative values" ); endif D = S.*V; X_lower = zeros(1,C); X_upper = 1./max(D,[],2)'; R_lower = sum(D,2)'; R_upper = +inf(1,C); endfunction %!test %! fail( "qnomaba( [1 1], [1 1 1; 1 1 1; 1 1 1] )", "2 rows" ); queueing/inst/ctmcfpt.m0000664000175000017500000000617214620404470015064 0ustar morenomoreno## Copyright (C) 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{M} =} ctmcfpt (@var{Q}) ## @deftypefnx {Function File} {@var{m} =} ctmcfpt (@var{Q}, @var{i}, @var{j}) ## ## @cindex first passage times, CTMC ## @cindex CTMC ## @cindex continuous time Markov chain ## @cindex Markov chain, continuous time ## ## Compute mean first passage times for an irreducible continuous-time ## Markov chain. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{Q}(i,j) ## Infinitesimal generator matrix. @var{Q} is a @math{N \times N} ## square matrix where @code{@var{Q}(i,j)} is the transition rate from ## state @math{i} to state @math{j}, for @math{1 @leq{} i, j @leq{} N}, ## @math{i \neq j}. Transition rates must be nonnegative, and ## @math{\sum_{j=1}^N Q_{i,j} = 0} ## ## @item @var{i} ## Initial state. ## ## @item @var{j} ## Destination state. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{M}(i,j) ## average time before state ## @var{j} is visited for the first time, starting from state @var{i}. ## We let @code{@var{M}(i,i) = 0}. ## ## @item m ## @var{m} is the average time before state @var{j} is visited for the first ## time, starting from state @var{i}. ## ## @end table ## ## @seealso{ctmcmtta} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function result = ctmcfpt( Q, i, j ) persistent epsilon = 10*eps; if ( nargin != 1 && nargin != 3 ) print_usage(); endif [N err] = ctmcchkQ(Q); (N>0) || ... error(err); if ( nargin == 1 ) result = zeros(N,N); for j=1:N QQ = Q; QQ(j,:) = 0; # make state j absorbing for i=1:N p0 = zeros(1,N); p0(i) = 1; result(i,j) = ctmcmtta(QQ,p0); endfor endfor else (isscalar(i) && i>=1 && j<=N) || error("i must be an integer in the range 1..%d", N); (isvector(j) && all(j>=1) && all(j<=N)) || error("j must be an integer or vector with elements in 1..%d", N); j = j(:)'; # make j a row vector Q(j,:) = 0; # make state(s) j absorbing p0 = zeros(1,N); p0(i) = 1; result = ctmcmtta(Q,p0); endif endfunction %!demo %! Q = [ -1.0 0.9 0.1; ... %! 0.1 -1.0 0.9; ... %! 0.9 0.1 -1.0 ]; %! M = ctmcfpt(Q) %! m = ctmcfpt(Q,1,3) %!test %! N = 10; %! Q = reshape(1:N^2,N,N); %! Q(1:N+1:end) = 0; %! Q -= diag(sum(Q,2)); %! M = ctmcfpt(Q); %! assert( all(diag(M) < 10*eps) ); queueing/inst/qncsconv.m0000664000175000017500000001724414620404470015260 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsconv (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsconv (@var{N}, @var{S}, @var{V}, @var{m}) ## ## @cindex closed network, single class ## @cindex normalization constant ## @cindex convolution algorithm ## ## Analyze product-form, single class closed networks with @math{K} service centers using the convolution algorithm. ## ## Load-independent service centers, multiple servers (@math{M/M/m} ## queues) and IS nodes are supported. For general load-dependent ## service centers, use @code{qncsconvld} instead. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## Number of requests in the system (@code{@var{N}>0}). ## ## @item @var{S}(k) ## average service time on center @math{k} (@code{@var{S}(k) @geq{} 0}). ## ## @item @var{V}(k) ## visit count of service center @math{k} (@code{@var{V}(k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k}. If @code{@var{m}(k) < 1}, ## center @math{k} is a delay center (IS); if @code{@var{m}(k) @geq{} ## 1}, center @math{k} it is a regular @math{M/M/m} queueing center ## with @code{@var{m}(k)} identical servers. Default is ## @code{@var{m}(k) = 1} for all @math{k}. ## ## @end table ## ## @strong{OUTPUT} ## ## @table @code ## ## @item @var{U}(k) ## center @math{k} utilization. ## For IS nodes, @code{@var{U}(k)} is the @emph{traffic intensity} ## @code{@var{X}(k) * @var{S}(k)}. ## ## @item @var{R}(k) ## average response time of center @math{k}. ## ## @item @var{Q}(k) ## average number of customers at center @math{k}. ## ## @item @var{X}(k) ## throughput of center @math{k}. ## ## @item @var{G}(n) ## Vector of normalization constants. @code{@var{G}(n+1)} contains the value of ## the normalization constant with @math{n} requests ## @math{G(n)}, @math{n=0, @dots{}, N}. ## ## @end table ## ## @strong{NOTE} ## ## For a network with @math{K} service centers and @math{N} requests, ## this implementation of the convolution algorithm has time and space ## complexity @math{O(NK)}. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Jeffrey P. Buzen, @cite{Computational Algorithms for Closed Queueing ## Networks with Exponential Servers}, Communications of the ACM, volume ## 16, number 9, September 1973, ## pp. 527--531. @uref{http://doi.acm.org/10.1145/362342.362345, 10.1145/362342.362345} ## @end itemize ## ## This implementation is based on G. Bolch, S. Greiner, H. de Meer and ## K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and ## Performance Evaluation with Computer Science Applications}, Wiley, ## 1998, pp. 313--317. ## ## @seealso{qncsconvld} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X G] = qncsconv( varargin ) if ( nargin < 3 || nargin > 4 ) print_usage(); endif ## To be compliant with the reference, we use K to denote the ## population size [err K S V m] = qncschkparam( varargin{:} ); isempty(err) || error(err); N = length(S); # Number of service centers ## This implementation is based on G. Bolch, S. Greiner, H. de Meer ## and K. Trivedi, Queueing Networks and Markov Chains: Modeling and ## Performance Evaluation with Computer Science Applications, Wiley, ## 1998, pp. 313--317. ## First, we remember the indexes of IS nodes i_delay = find(m<1); m( i_delay ) = K; # IS nodes are handled as if they were M/M/K nodes with number of servers equal to the population size K, such that queueing never occurs. ## Initialization G_n = G_nm1 = zeros(1,K+1); F_n = zeros(N,K+1); F_n(:,1) = 1; k=1:K; G_n(1) = 1; G_n(k+1) = F_n(1,k+1) = F(1,k,V,S,m); ## Main convolution loop for n=2:N G_nm1 = G_n; k=1:K; F_n(n,1+k) = F(n,k,V,S,m); # G_n(1) = 1; G_n = conv( F_n(n,:), G_nm1(:) )(1:K+1); endfor ## Done computation of G(n,k). G = G_n(:)'; # ensure G is a row vector ## Computes performance measures X = V*G(K)/G(K+1); U = X .* S ./ m; ## Adjust utilization of delay centers U(i_delay) = X(i_delay) .* S(i_delay); Q = zeros(1,N); i_multi = find(m>1); for i=i_multi G_N_i = zeros(1,K+1); G_N_i(1) = 1; for k=1:K j=1:k; G_N_i(k+1) = G(k+1)-dot( F_n(i,j+1), G_N_i(k-j+1) ); endfor k=0:K; p_i(k+1) = F_n(i,k+1)./G(K+1).*G_N_i(K-k+1); Q(i) = dot( k, p_i( k+1 ) ); endfor i_single = find(m==1); for i=i_single k=1:K; Q(i) = sum( ( V(i)*S(i) ) .^ k .* G(K+1-k)/G(K+1) ); endfor R = Q ./ X; endfunction %!test %! # Example 8.1 p. 318 Bolch et al. %! K=3; %! S = [ 1/0.8 1/0.6 1/0.4 ]; %! m = [2 3 1]; %! V = [ 1 .667 .2 ]; %! [U R Q X G] = qncsconv( K, S, V, m ); %! assert( G, [1 2.861 4.218 4.465], 5e-3 ); %! assert( X, [0.945 0.630 0.189], 1e-3 ); %! assert( U, [0.590 0.350 0.473], 1e-3 ); %! assert( Q, [1.290 1.050 0.660], 1e-3 ); %! assert( R, [1.366 1.667 3.496], 1e-3 ); %!test %! # Example 8.3 p. 331 Bolch et al. %! # compare results of convolution to those of mva %! S = [ 0.02 0.2 0.4 0.6 ]; %! K = 6; %! V = [ 1 0.4 0.2 0.1 ]; %! [U_mva R_mva Q_mva X_mva G_mva] = qncsmva(K, S, V); %! [U_con R_con Q_con X_con G_con] = qncsconv(K, S, V); %! assert( U_mva, U_con, 1e-5 ); %! assert( R_mva, R_con, 1e-5 ); %! assert( Q_mva, Q_con, 1e-5 ); %! assert( X_mva, X_con, 1e-5 ); %! assert( G_mva, G_con, 1e-5 ); %!test %! # Compare the results of convolution to those of mva %! S = [ 0.02 0.2 0.4 0.6 ]; %! K = 6; %! V = [ 1 0.4 0.2 0.1 ]; %! m = [ 1 -1 2 1 ]; # center 2 is IS %! [U_mva R_mva Q_mva X_mva] = qncsmva(K, S, V, m); %! [U_con R_con Q_con X_con G] = qncsconv(K, S, V, m ); %! assert( U_mva, U_con, 1e-5 ); %! assert( R_mva, R_con, 1e-5 ); %! assert( Q_mva, Q_con, 1e-5 ); %! assert( X_mva, X_con, 1e-5 ); ## result = F(i,j,v,S,m) ## ## Helper fuction to compute F(i,j) as defined in Eq 7.61 p. 289 of ## Bolch, Greiner, de Meer, Trivedi "Queueing Networks and Markov ## Chains: Modeling and Performance Evaluation with Computer Science ## Applications", Wiley, 1998. This function has been vectorized, ## and accepts a vector as parameter j. function result = F(i,j,v,S,m) isscalar(i) || ... error( "i must be a scalar" ); k_i = j; if ( m(i) == 1 ) result = ( v(i)*S(i) ).^k_i; else ii = find(k_i<=m(i)); ## if k_i<=m(i) result(ii) = ( v(i)*S(i) ).^k_i(ii) ./ factorial(k_i(ii)); ii = find(k_i>m(i)); ## if k_i>m(i) result(ii) = ( v(i)*S(i) ).^k_i(ii) ./ ( factorial(m(i))*m(i).^(k_i(ii)-m(i)) ); endif endfunction %!demo %! n = [1 2 0]; %! N = sum(n); # Total population size %! S = [ 1/0.8 1/0.6 1/0.4 ]; %! m = [ 2 3 1 ]; %! V = [ 1 .667 .2 ]; %! [U R Q X G] = qncsconv( N, S, V, m ); %! p = [0 0 0]; # initialize p %! # Compute the probability to have n(k) jobs at service center k %! for k=1:3 %! p(k) = (V(k)*S(k))^n(k) / G(N+1) * ... %! (G(N-n(k)+1) - V(k)*S(k)*G(N-n(k)) ); %! printf("Prob( n(%d) = %d )=%f\n", k, n(k), p(k) ); %! endfor queueing/inst/dtmcexps.m0000664000175000017500000001022014620404470015240 0ustar morenomoreno## Copyright (C) 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{L} =} dtmcexps (@var{P}, @var{n}, @var{p0}) ## @deftypefnx {Function File} {@var{L} =} dtmcexps (@var{P}, @var{p0}) ## ## @cindex expected sojourn times, DTMC ## @cindex DTMC ## @cindex discrete time Markov chain ## @cindex Markov chain, discrete time ## ## Compute the expected number of visits to each state during the first ## @var{n} transitions, or until abrosption. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(i,j) ## @math{N \times N} transition matrix. @code{@var{P}(i,j)} is the ## transition probability from state @math{i} to state @math{j}. ## ## @item @var{n} ## Number of steps during which the expected number of visits are ## computed (@math{@var{n} @geq{} 0}). If @code{@var{n}=0}, returns ## @var{p0}. If @code{@var{n} > 0}, returns the expected number of ## visits after exactly @var{n} transitions. ## ## @item @var{p0}(i) ## Initial state occupancy probabilities; @code{@var{p0}(i)} is ## the probability that the system is in state @math{i} at step 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{L}(i) ## When called with two arguments, @code{@var{L}(i)} is the expected ## number of visits to state @math{i} before absorption. When ## called with three arguments, @code{@var{L}(i)} is the expected number ## of visits to state @math{i} during the first @var{n} transitions. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item Grinstead, Charles M.; Snell, J. Laurie (July ## 1997). @cite{Introduction to Probability}, Ch. 11: Markov ## Chains. American Mathematical Society. ISBN 978-0821807491. ## @end itemize ## ## @seealso{ctmcexps} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function L = dtmcexps ( P, varargin ) persistent epsilon = 10*eps; if ( nargin < 2 || nargin > 3 ) print_usage(); endif [K err] = dtmcchkP(P); (K>0) || ... error(err); if ( nargin == 2 ) p0 = varargin{1}; else n = varargin{1}; p0 = varargin{2}; endif ( isvector(p0) && length(p0) == K && all(p0>=0) && abs(sum(p0)-1.0)=0 || ... error("n must be >= 0"); n = fix(n); L = zeros(sizeof(p0)); ## It is know that ## ## I + P + P^2 + P^3 + ... + P^n = (I-P)^-1 * (I-P^(n+1)) ## ## and therefore we could succintly write ## ## L = p0*inv(eye(K)-P)*(eye(K)-P^(n+1)); ## ## Unfortunatly, the method above is numerically unstable (at least ## for small values of n), so we use the crude approach below. PP = p0; L = zeros(1,K); for p=0:n L += PP; PP *= P; endfor else ## identify transient states tr = find(diag(P) < 1); k = length(tr); # number of transient states if ( k == K ) error("There are no absorbing states"); endif N = zeros(size(P)); tmpN = inv(eye(k) - P(tr,tr)); # matrix N = (I-Q)^-1 N(tr,tr) = tmpN; L = p0*N; endif endfunction %!test %! P = dtmcbd([1 1 1 1], [0 0 0 0]); %! L = dtmcexps(P,[1 0 0 0 0]); %! t = dtmcmtta(P,[1 0 0 0 0]); %! assert( L, [1 1 1 1 0] ); %! assert( sum(L), t ); %!test %! P = dtmcbd(linspace(0.1,0.4,5),linspace(0.4,0.1,5)); %! p0 = [1 0 0 0 0 0]; %! L = dtmcexps(P,0,p0); %! assert( L, p0 ); queueing/inst/qnosaba.m0000664000175000017500000000654714620404470015056 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosaba (@var{lambda}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosaba (@var{lambda}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnosaba (@var{lambda}, @var{S}, @var{V}, @var{m}) ## ## @cindex bounds, asymptotic ## @cindex open network ## ## Compute Asymptotic Bounds for open, single-class networks with @math{K} service centers. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate of requests (scalar, @code{@var{lambda} @geq{} 0}). ## ## @item @var{D}(k) ## service demand at center @math{k}. ## (vector of length @math{K}, @code{@var{D}(k) @geq{} 0}). ## ## @item @var{S}(k) ## mean service time at center @math{k}. ## (vector of length @math{K}, @code{@var{S}(k) @geq{} 0}). ## ## @item @var{V}(k) ## mean number of visits to center @math{k}. ## (vector of length @math{K}, @code{@var{V}(k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k}. ## This function only supports @math{M/M/1} queues, therefore ## @var{m} must be @code{ones(size(S))}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl} ## @item @var{Xu} ## Lower and upper bounds on the system throughput. @var{Xl} is ## always set to @math{0} since there can be no lower bound on the ## throughput of open networks (scalar). ## ## @item @var{Rl} ## @item @var{Ru} ## Lower and upper bounds on the system response time. @var{Ru} ## is always set to @code{+inf} since there can be no upper bound on the ## throughput of open networks (scalar). ## ## @end table ## ## @seealso{qnomaba} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [X_lower X_upper R_lower R_upper] = qnosaba( varargin ) if ( nargin < 2 || nargin > 4 ) print_usage(); endif [err lambda S V m] = qnoschkparam( varargin{:} ); isempty(err) || error(err); all(m==1) || ... error("this function supports M/M/1 servers only"); D = S .* V; X_lower = 0; X_upper = 1/max(D); R_lower = sum(D); R_upper = +inf; endfunction %!test %! fail( "qnosaba( 0.1, [] )", "vector" ); %! fail( "qnosaba( 0.1, [0 -1])", "nonnegative" ); %! fail( "qnosaba( 0, [1 2] )", "lambda" ); %! fail( "qnosaba( -1, [1 2])", "lambda" ); %! fail( "qnosaba( 1, [1 2 3], [1 2] )", "incompatible size"); %! fail( "qnosaba( 1, [1 2 3], [-1 2 3] )", "nonnegative"); %!test %! [Xl Xu Rl Ru] = qnosaba( 1, [1 1] ); %! assert( Xl, 0 ); %! assert( Ru, +inf ); queueing/inst/qsmm1k.m0000664000175000017500000001302614620404470014631 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pK}] =} qsmm1k (@var{lambda}, @var{mu}, @var{K}) ## @deftypefnx {Function File} {@var{pn} =} qsmm1k (@var{lambda}, @var{mu}, @var{K}, @var{n}) ## ## @cindex @math{M/M/1/K} system ## ## Compute utilization, response time, average number of requests and ## throughput for a @math{M/M/1/K} finite capacity system. ## ## In a @math{M/M/1/K} queue there is a single server and a queue with ## finite capacity: the maximum number of requests in the system ## (including the request being served) is @math{K}, and the maximum ## queue length is therefore @math{K-1}. ## ## @tex ## The steady-state probability @math{\pi_n} that there are @math{n} ## jobs in the system, @math{0 @leq{} n @leq{} K}, is: ## ## $$ ## \pi_n = {(1-a)a^n \over 1-a^{K+1}} ## $$ ## ## where @math{a = \lambda/\mu}. ## @end tex ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate (@code{@var{lambda}>0}). ## ## @item @var{mu} ## Service rate (@code{@var{mu}>0}). ## ## @item @var{K} ## Maximum number of requests allowed in the system (@code{@var{K} @geq{} 1}). ## ## @item @var{n} ## Number of requests in the (@code{0 @leq{} @var{n} @leq{} K}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U} ## Service center utilization, which is defined as @code{@var{U} = 1-@var{p0}} ## ## @item @var{R} ## Service center response time ## ## @item @var{Q} ## Average number of requests in the system ## ## @item @var{X} ## Service center throughput ## ## @item @var{p0} ## Steady-state probability that there are no requests in the system ## ## @item @var{pK} ## Steady-state probability that there are @math{K} requests in the system ## (i.e., that the system is full) ## ## @item @var{pn} ## Steady-state probability that there are @math{n} requests in the system ## (including the one being served). ## ## @end table ## ## If this function is called with less than four arguments, ## @var{lambda}, @var{mu} and @var{K} can be vectors of the ## same size. In this case, the results will be vectors as well. ## ## @seealso{qsmm1,qsmminf,qsmmm} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U_or_pn R Q X p0 pK] = qsmm1k( lambda, mu, K, n ) if ( nargin < 3 || nargin > 4 ) print_usage(); endif ( isvector(lambda) && isvector(mu) && isvector(K) ) || ... error( "lambda, mu, K must be vectors of the same size" ); [err lambda mu K] = common_size( lambda, mu, K ); if ( err ) error( "Parameters are not of common size" ); endif all( K>0 ) || ... error( "K must be >0" ); ( all( lambda>0 ) && all( mu>0 ) ) || ... error( "lambda and mu must be >0" ); a = lambda./mu; if (nargin < 4) U_or_pn = R = Q = X = p0 = pK = 0*lambda; ## persistent tol = 1e-7; ## if a!=1 ## i = find( abs(a-1)>tol ); i = find( a != 1 ); p0(i) = (1-a(i))./(1-a(i).^(K(i)+1)); pK(i) = (1-a(i)).*(a(i).^K(i))./(1-a(i).^(K(i)+1)); Q(i) = a(i)./(1-a(i)) - (K(i)+1)./(1-a(i).^(K(i)+1)).*(a(i).^(K(i)+1)); ## if a==1 ## i = find( abs(a-1)<=tol ); i = find( a == 1 ); p0(i) = pK(i) = 1./(K(i)+1); Q(i) = K(i)/2; ## Compute other performance measures U_or_pn = 1-p0; X = lambda.*(1-pK); R = Q ./ X; else (length(lambda) == 1) || error("lambda must be a scalar if this function is called with four arguments"); isvector(n) || error("n must be a vector"); (all(n >= 0) && all(n <= K)) || error("n must be >= 0 and <= K"); n = n(:)'; if (a != 1) # we know that a must be a scalar U_or_pn = ((1 - a) * a.^n) ./ (1 - a^(K+1)); else U_or_pn = 1/(K+1) * ones(size(n)); endif endif endfunction %!test %! lambda = mu = 1; %! K = 10; %! [U R Q X p0] = qsmm1k(lambda,mu,K); %! assert( Q, K/2, 1e-7 ); %! assert( U, 1-p0, 1e-7 ); %!test %! lambda = 1; %! mu = 1.2; %! K = 10; %! [U R Q X p0 pK] = qsmm1k(lambda, mu, K); %! prob = qsmm1k(lambda, mu, K, 0:K); %! assert( p0, prob(1), 1e-7 ); %! assert( pK, prob(K+1), 1e-7 ); %!test %! # Compare the result with the equivalent Markov chain %! lambda = 0.8; %! mu = 0.8; %! K = 10; %! [U1 R1 Q1 X1] = qsmm1k( lambda, mu, K ); %! birth = lambda*ones(1,K); %! death = mu*ones(1,K); %! q = ctmc(ctmcbd( birth, death )); %! U2 = 1-q(1); %! Q2 = dot( [0:K], q ); %! assert( U1, U2, 1e-4 ); %! assert( Q1, Q2, 1e-4 ); %!demo %! ## Given a M/M/1/K queue, compute the steady-state probability pk %! ## of having n requests in the systen. %! lambda = 0.2; %! mu = 0.25; %! K = 10; %! n = 0:10; %! pn = qsmm1k(lambda, mu, K, n); %! plot(n, pn, "-o", "linewidth", 2); %! xlabel("N. of requests (n)"); %! ylabel("p_n"); %! title(sprintf("M/M/1/%d system, \\lambda = %g, \\mu = %g", K, lambda, mu)); queueing/inst/qncsmvald.m0000664000175000017500000001540714620404470015415 0ustar morenomoreno## Copyright (C) 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvald (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvald (@var{N}, @var{S}, @var{V}, @var{Z}) ## ## @cindex Mean Value Analysys (MVA) ## @cindex MVA ## @cindex closed network, single class ## @cindex load-dependent service center ## ## Mean Value Analysis algorithm for closed, single class queueing ## networks with @math{K} service centers and load-dependent service ## times. This function supports FCFS, LCFS-PR, PS and IS nodes. For ## networks with only fixed-rate centers and multiple-server ## nodes, the function @code{qncsmva} is more efficient. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## Population size (number of requests in the system, @code{@var{N} @geq{} 0}). ## If @code{@var{N} == 0}, this function returns @code{@var{U} = @var{R} = @var{Q} = @var{X} = 0} ## ## @item @var{S}(k,n) ## mean service time at center @math{k} ## where there are @math{n} requests, @math{1 @leq{} n ## @leq{} N}. @code{@var{S}(k,n)} @math{= 1 / \mu_{k}(n)}, ## where @math{\mu_{k}(n)} is the service rate of center @math{k} ## when there are @math{n} requests. ## ## @item @var{V}(k) ## average number of visits to service center @math{k} (@code{@var{V}(k) @geq{} 0}). ## ## @item @var{Z} ## external delay ("think time", @code{@var{Z} @geq{} 0}); default 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(k) ## utilization of service center @math{k}. The ## utilization is defined as the probability that service center ## @math{k} is not empty, that is, @math{U_k = 1-\pi_k(0)} where ## @math{\pi_k(0)} is the steady-state probability that there are 0 ## jobs at service center @math{k}. ## ## @item @var{R}(k) ## response time on service center @math{k}. ## ## @item @var{Q}(k) ## average number of requests in service center @math{k}. ## ## @item @var{X}(k) ## throughput of service center @math{k}. ## ## @end table ## ## @strong{NOTES} ## ## In presence of load-dependent servers, the MVA algorithm is known ## to be numerically unstable. Generally this problem manifests itself ## as negative response times or utilization. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed ## Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, ## April 1980, pp. 313--322. @uref{http://doi.acm.org/10.1145/322186.322195, 10.1145/322186.322195} ## @end itemize ## ## This implementation is described in G. Bolch, S. Greiner, H. de Meer ## and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling ## and Performance Evaluation with Computer Science Applications}, Wiley, ## 1998, Section 8.2.4.1, ``Networks with Load-Dependent Service: Closed ## Networks''. ## ## @seealso{qncsmva} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qncsmvald( N, S, V, Z ) if ( nargin < 3 || nargin > 4 ) print_usage(); endif isvector(V) && all(V>=0) || ... error( "V must be a vector >= 0" ); V = V(:)'; # make V a row vector K = length(V); # Number of servers isscalar(N) && N >= 0 || ... error( "N must be >= 0" ); ( ismatrix(S) && rows(S) == K && columns(S) >= N ) || ... error( "S size mismatch: is %dx%d, should be %dx%d", rows(S), columns(S), K, N ); all(S(:)>=0) || ... error( "S must be >= 0" ); if ( nargin < 4 ) Z = 0; else isscalar(Z) && Z>=0 || ... error( "Z must be >= 0" ); endif ## Initialize results p = zeros( K, N+1 ); # p(k,i+1) is the probability that there are i jobs at server k, given that the network population is j p(:,1) = 1; U = R = Q = X = zeros( 1, K ); X_s = 0; # System throughput ## Main MVA loop, iterates over the population size for n=1:N # over population size j=1:n; ## for i=1:K ## R(i) = sum( j.*S(i,j).*p(i,j) ); ## endfor R = sum( repmat(j,K,1).*S(:,1:n).*p(:,1:n), 2)'; R_s = dot( V, R ); # System response time X_s = n / (Z+R_s); # System Throughput ## G_N = G_Nm1 / X_s; G_Nm1 = G_N; ## prepare for next iteration for i=1:K p(i, 1+j) = X_s * S(i,j) .* p(i,j) * V(i); p(i, 1) = 1-sum(p(i,1+j)); endfor endfor Q = X_s * ( V .* R ); U = 1-p(:,1)'; # Service centers utilization X = X_s * V; # Service centers throughput endfunction ## Check degenerate case of N==0 (general LD case) %!test %! N = 0; %! S = [1 2; 3 4; 5 6; 7 8]; %! V = [1 1 1 4]; %! [U R Q X] = qncsmvald(N, S, V); %! assert( U, 0*V ); %! assert( R, 0*V ); %! assert( Q, 0*V ); %! assert( X, 0*V ); %!test %! # Exsample 3.42 p. 577 Jain %! V = [ 16 10 5 ]; %! N = 20; %! S = [ 0.125 0.3 0.2 ]; %! Sld = repmat( S', 1, N ); %! Z = 4; %! [U1 R1 Q1 X1] = qncsmvald(N,Sld,V,Z); %! [U2 R2 Q2 X2] = qncsmva(N,S,V,ones(1,3),Z); %! assert( U1, U2, 1e-3 ); %! assert( R1, R2, 1e-3 ); %! assert( Q1, Q2, 1e-3 ); %! assert( X1, X2, 1e-3 ); %!test %! # Example 8.7 p. 349 Bolch et al. %! N = 3; %! Sld = 1 ./ [ 2 4 4; ... %! 1.667 1.667 1.667; ... %! 1.25 1.25 1.25; ... %! 1 2 3 ]; %! V = [ 1 .5 .5 1 ]; %! [U R Q X] = qncsmvald(N,Sld,V); %! assert( Q, [0.624 0.473 0.686 1.217], 1e-3 ); %! assert( R, [0.512 0.776 1.127 1], 1e-3 ); %! assert( all( U<=1) ); %!test %! # Example 8.4 p. 333 Bolch et al. %! N = 3; %! S = [ .5 .6 .8 1 ]; %! m = [2 1 1 N]; %! Sld = zeros(3,N); %! Sld(1,:) = .5 ./ [1 2 2]; %! Sld(2,:) = [.6 .6 .6]; %! Sld(3,:) = [.8 .8 .8]; %! Sld(4,:) = 1 ./ [1 2 3]; %! V = [ 1 .5 .5 1 ]; %! [U1 R1 Q1 X1] = qncsmvald(N,Sld,V); %! [U2 R2 Q2 X2] = qncsmva(N,S,V,m); %! ## Note that qncsmvald computes the utilization in a different %! ## way as qncsmva; in fact, qncsmva knows that service %! ## center i has m(i)>1 servers, but qncsmvald does not. Thus, %! ## utilizations for multiple-server nodes cannot be compared %! assert( U1([2,3]), U2([2,3]), 1e-3 ); %! assert( R1, R2, 1e-3 ); %! assert( Q1, Q2, 1e-3 ); %! assert( X1, X2, 1e-3 ); queueing/inst/qnmix.m0000664000175000017500000002117214620404470014555 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmix (@var{lambda}, @var{N}, @var{S}, @var{V}, @var{m}) ## ## @cindex Mean Value Analysys (MVA) ## @cindex mixed network ## ## Mean Value Analysis for mixed queueing networks. The network ## consists of @math{K} service centers (single-server or delay ## centers) and @math{C} independent customer chains. Both open and ## closed chains are possible. @var{lambda} is the vector of per-chain ## arrival rates (open classes); @var{N} is the vector of populations ## for closed chains. ## ## Class switching is @strong{not} allowed. Each customer class ## @emph{must} correspond to an independent chain. ## ## If the network is made of open or closed classes only, then this ## function calls @code{qnom} or @code{qncmmva} respectively, and ## prints a warning message. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda}(c) ## @itemx @var{N}(c) ## For each customer chain @math{c}: ## ## @itemize ## ## @item if @math{c} is a closed chain, then @code{@var{N}(c)>0} is the ## number of class @math{c} requests and @code{@var{lambda}(c)} must be ## zero; ## ## @item If @math{c} is an open chain, ## @code{@var{lambda}(c)>0} is the arrival rate of class @math{c} ## requests and @code{@var{N}(c)} must be zero; ## ## @end itemize ## ## @noindent In other words, for each class @math{c} the following must hold: ## ## @example ## (@var{lambda}(c)>0 && @var{N}(c)==0) || (@var{lambda}(c)==0 && @var{N}(c)>0) ## @end example ## ## @item @var{S}(c,k) ## mean class @math{c} service time at center @math{k}, ## @code{@var{S}(c,k) @geq{} 0}. For FCFS nodes, service times must be ## class-independent. ## ## @item @var{V}(c,k) ## average number of visits of class @math{c} customers to center ## @math{k} (@code{@var{V}(c,k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k}. Only single-server ## (@code{@var{m}(k)==1}) or IS (Infinite Server) nodes ## (@code{@var{m}(k)<1}) are supported. If omitted, each center is ## assumed to be of type @math{M/M/1}-FCFS. Queueing discipline for ## single-server nodes can be FCFS, PS or LCFS-PR. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(c,k) ## class @math{c} utilization at center @math{k}. ## ## @item @var{R}(c,k) ## class @math{c} response time at center @math{k}. ## ## @item @var{Q}(c,k) ## average number of class @math{c} requests at center @math{k}. ## ## @item @var{X}(c,k) ## class @math{c} throughput at center @math{k}. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. ## Sevcik, @cite{Quantitative System Performance: Computer System ## Analysis Using Queueing Network Models}, Prentice Hall, ## 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In ## particular, see section 7.4.3 ("Mixed Model Solution Techniques"). ## Note that in this function we compute the mean response time @math{R} ## instead of the mean residence time as in the reference. ## ## @item ## Herb Schwetman, @cite{Implementing the Mean Value Algorithm for the ## Solution of Queueing Network Models}, Technical Report ## @uref{http://docs.lib.purdue.edu/cstech/286/, CSD-TR-355}, Department ## of Computer Sciences, Purdue University, revised Feb 15, 1982. ## @end itemize ## ## @seealso{qncmmva, qncm} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qnmix( lambda, N, S, V, m ) if ( nargin < 4 || nargin > 5 ) print_usage(); endif isvector(lambda) || ... error( "lambda must be a vector" ); lambda = lambda(:)'; isvector(N) || ... error( "N must be a vector" ); N = N(:)'; size_equal(lambda,N) || ... error( "lambda and N must be of equal length" ); ( !any( lambda>0 & N>0 ) ) || ... error("A class cannot be open and closed at the same time. Check lambda and N" ); ( all( lambda>0 | N>0 ) ) || ... error( "A class cannot be neither open nor closed. Check lambda and N" ); size_equal(S,V) || ... error( "S and V must have the same size" ); C = length(lambda); # number of classes K = columns(S); # number of service centers rows(S) == C || ... error( "S must have %d rows", C ); if ( nargin < 5 ) m = ones(1,K); else isvector( m ) || ... error( "m must be a vector" ); m = m(:)'; size_equal(lambda,m) || ... error( "lambda and m must be of equal length" ); endif all( m<=1 ) || ... error( "This function supports single-server and delay centers only. Check m" ); if ( !any(lambda>0) ) warning( "qnmix(): There are no open classes. Using qncmmva()" ); [U R Q X] = qncmmva( N, S, V, m ); return; endif if ( !any(N>0) ) warning( "qnmix(): There are no closed classes. Using qnom()" ); [U R Q X] = qnom( lambda, S, V, m ); return; endif D = S.*V; # service demands op = find( lambda>0 ); # indexes of open networks cl = find( N>0 ); # indexes of closed networks ## Initialize results U = R = Q = X = zeros(C,K); U(op,:) = diag( lambda(op) )* D(op,:); # U(c,:) = lambda(c)*D(c,:); Uo = sum(U,1); # Total utilization for open classes on service center k ## Build closed model to solve Ncl = N(cl); Scl = S; for c=cl Scl(c,:) = Scl(c,:) ./ (1-Uo); endfor Scl = Scl(cl,:); # select only rows for closed classes Vcl = V(cl,:); [Ucl Rcl Qcl Xcl] = qncmmva(Ncl, Scl, Vcl, m ); ## Results for closed classes X(cl,:) = Xcl; Q(cl,:) = Qcl; R(cl,:) = Rcl; U(cl,:) = X(cl,:) .* D(cl,:); ## Results for open classes Qc = sum(Q(cl,:),1); i_single=find(m==1); i_multi=find(m<1); for c=op R(c,i_single) = S(c,i_single).*(1+Qc) ./ (1-Uo); # This is the Response time, _not_ the residence time R(c,i_multi) = S(c,i_multi); endfor Q(op,:) = (diag(lambda(op))*V(op,:)).*R(op,:); # Q(c,k) = lambda(c)*V(c,k)*R(c,k) ## The following is needed to avoid division by zero idx = false(size(X)); idx(op,:) = ( S(op,:)>0 & V(op,:)>0 ); X(idx) = U(idx) ./ S(idx); endfunction %!test %! lambda = [1 0 0]; %! N = [1 1 1]; %! S = V = [1 1 1; 1 1 1; 1 1 1]; %! fail( "qnmix( lambda, N, S, V)", "same time"); %! N = [0 0 1]; %! fail( "qnmix( lambda, N, S, V)", "open nor closed" ); %! N = [0 1 2]; %! m = [ 1 1 2 ]; %! fail( "qnmix( lambda, N, S, V, m)", "single-server and delay" ); %! S = V = [1 1 1; 1 1 1]; %! fail( "qnmix( lambda, N, S, V)", "rows" ); %!test %! # Example p. 148 Zahorjan et al. %! lambda = [1 1/2 0 0]; %! N = [0 0 1 1]; %! V = [1 1; 1 1; 1 1; 1 1]; %! S = [1/4 1/6; 1/2 1; 1/2 1; 1 4/3]; %! [U R Q X] = qnmix(lambda, N, S, V ); %! assert( Q(3,1), 4/19, 1e-4 ); %! assert( Q(3,2), 15/19, 1e-4 ); %! assert( Q(4,1), 5/19, 1e-4 ); %! assert( Q(4,2), 14/19, 1e-4 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law %!test %! # Example 8.6 p. 345 Bolch et al. %! lambda = [0.5 0.25 0 0]; %! N = [0 0 1 1]; %! V = [2 1; 2.5 1.5; 1 0.5; 1 0.4]; %! S = [0.4 0.6; 0.8 1.6; 0.3 0.5; 0.5 0.8]; %! [U R Q X] = qnmix( lambda, N, S, V ); %! assert( U([1 2],:), [0.4 0.3; 0.5 0.6], 1e-3 ); %! assert( R([3 4],:), [4.829 6.951; 7.727 11.636], 1e-3 ); %! assert( Q([3 4],:), [0.582 0.418; 0.624 0.376], 1e-3 ); %! assert( Q([1 2],:), [8.822 5.383; 11.028 10.766], 1e-3 ); %! assert( R([1 2],:), [8.822 10.766; 17.645 28.710], 1e-3 ); %! assert( X(3,1)/V(3,1), 0.120, 1e-3 ); %! assert( X(4,1)/V(4,1), 0.081, 1e-3 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law %!test %! ## example figure 10 p. 26 Schwetman, "Implementing the Mean Value %! ## Analysis for the Solution of Queueing Network Models", Technical %! ## Report CSD-TR-355, feb 15, 1982, Purdue University. %! S = [.25 0; .25 .10]; %! V = [1 0; 1 1]; %! lambda = [1 0]; %! N = [0 3]; %! [U R Q X] = qnmix( lambda, N, S, V ); %! assert( U(1,1), .25, 1e-3 ); %! assert( X(1,1), 1.0, 1e-3 ); %! assert( [R(1,1) R(2,1) R(2,2)], [1.201 0.885 0.135], 1e-3 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law queueing/inst/qnomvisits.m0000664000175000017500000001075614620404470015643 0ustar morenomoreno## Copyright (C) 2012, 2013, 2016 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{V} =} qnomvisits (@var{P}, @var{lambda}) ## ## Compute the visit ratios to the service centers of an open multiclass network with @math{K} service centers and @math{C} customer classes. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(r,i,s,j) ## probability that a class @math{r} request which completed service at center @math{i} is ## routed to center @math{j} as a class @math{s} request. Class switching ## is supported. ## ## @item @var{lambda}(r,i) ## external arrival rate of class @math{r} requests to center @math{i}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{V}(r,i) ## visit ratio of class @math{r} requests at center @math{i}. ## ## @end table ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function V = qnomvisits( P, lambda ) if ( nargin != 2 ) print_usage(); endif ndims(P) == 4 || ... error("P must be a 4-dimensional matrix"); [C, K, C2, K2] = size( P ); (K == K2 && C == C2) || ... error( "P must be a [%d,%d,%d,%d] matrix", C, K, C, K); ( ndims(lambda) == 2 && [C,K] == size(lambda) ) || ... error( "lambda must be a %d x %d matrix", C, K ); all(lambda(:)>=0) || ... error(" lambda contains negative values" ); ## solve the traffic equations: V(s,j) = lambda(s,j) / lambda + sum_r ## sum_i V(r,i) * P(r,i,s,j), for all s,j where lambda is defined as ## sum_r sum_i lambda(r,i) A = eye(K*C) - reshape(P,[K*C K*C]); b = reshape(lambda / sum(lambda(:)), [1,K*C]); V = reshape(b/A, [C, K]); ## Make sure that no negative values appear (sometimes, numerical ## errors produce tiny negative values instead of zeros) V = max(0,V); endfunction %!test %! fail( "qnomvisits( zeros(3,3,3), [1 1 1] )", "matrix"); %!test %! C = 2; K = 4; %! P = zeros(C,K,C,K); %! # class 1 routing %! P(1,1,1,1) = .05; %! P(1,1,1,2) = .45; %! P(1,1,1,3) = .5; %! P(1,2,1,1) = 0.1; %! P(1,3,1,1) = 0.2; %! # class 2 routing %! P(2,1,2,1) = .01; %! P(2,1,2,3) = .5; %! P(2,1,2,4) = .49; %! P(2,3,2,1) = 0.2; %! P(2,4,2,1) = 0.16; %! lambda = [0.1 0 0 0.1 ; 0 0 0.2 0.1]; %! lambda_sum = sum(lambda(:)); %! V = qnomvisits(P, lambda); %! assert( all(V(:)>=0) ); %! for i=1:K %! for c=1:C %! assert(V(c,i), lambda(c,i) / lambda_sum + sum(sum(V .* P(:,:,c,i))), 1e-5); %! endfor %! endfor %!test %! # example 7.7 p. 304 Bolch et al. %! # Note that the book uses a slightly different notation than %! # what we use here. Specifically, the book defines the routing %! # probabilities as P(i,r,j,s) (i,j are service centers, r,s are job %! # classes) while the queueing package uses P(r,i,s,j). %! # A more serious problem arises in the definition of external arrivals. %! # The computation of V(r,i) as given in the book (called e_ir %! # in Eq 7.14) is performed in terms of P_{0, js}, defined as %! # "the probability in an open network that a job from outside the network %! # enters the jth node as a job of the sth class" (p. 267). This is %! # compliant with eq. 7.12 where the external class r arrival rate at center %! # i is computed as \lambda * P_{0,ir}. However, example 7.7 wrongly %! # defines P_{0,11} = P_{0,12} = 1, instead of P_{0,11} = P_{0,12} = 0.5 %! # Therefore the resulting visit ratios they obtain must be divided by two. %! P = zeros(2,3,2,3); %! lambda = S = zeros(2,3); %! P(1,1,1,2) = 0.4; %! P(1,1,1,3) = 0.3; %! P(1,2,1,1) = 0.6; %! P(1,2,1,3) = 0.4; %! P(1,3,1,1) = 0.5; %! P(1,3,1,2) = 0.5; %! P(2,1,2,2) = 0.3; %! P(2,1,2,3) = 0.6; %! P(2,2,2,1) = 0.7; %! P(2,2,2,3) = 0.3; %! P(2,3,2,1) = 0.4; %! P(2,3,2,2) = 0.6; %! lambda(1,1) = lambda(2,1) = 1; %! V = qnomvisits(P,lambda); %! assert( V, [ 3.333 2.292 1.917; 10 8.049 8.415] ./ 2, 1e-3); queueing/inst/qnsolve.m0000664000175000017500000005525714620404470015123 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2022 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"closed"}, @var{N}, @var{QQ}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"closed"}, @var{N}, @var{QQ}, @var{V}, @var{Z}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"open"}, @var{lambda}, @var{QQ}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"mixed"}, @var{lambda}, @var{N}, @var{QQ}, @var{V}) ## ## High-level function for analyzing QN models. ## ## @itemize ## ## @item For @strong{closed} networks, the following server types are ## supported: @math{M/M/m}--FCFS, @math{-/G/\infty}, @math{-/G/1}--LCFS-PR, ## @math{-/G/1}--PS and load-dependent variants. ## ## @item For @strong{open} networks, the following server types are supported: ## @math{M/M/m}--FCFS, @math{-/G/\infty} and @math{-/G/1}--PS. General ## load-dependent nodes are @emph{not} supported. Multiclass open networks ## do not support multiple server @math{M/M/m} nodes, but only ## single server @math{M/M/1}--FCFS. ## ## @item For @strong{mixed} networks, the following server types are supported: ## @math{M/M/1}--FCFS, @math{-/G/\infty} and @math{-/G/1}--PS. General ## load-dependent nodes are @emph{not} supported. ## ## @end itemize ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## @itemx @var{N}(c) ## Number of requests in the system for closed networks. For ## single-class networks, @var{N} must be a scalar. For multiclass ## networks, @code{@var{N}(c)} is the population size of closed class ## @math{c}. ## ## @item @var{lambda} ## @itemx @var{lambda}(c) ## External arrival rate (scalar) for open networks. For single-class ## networks, @var{lambda} must be a scalar. For multiclass networks, ## @code{@var{lambda}(c)} is the class @math{c} overall arrival rate. ## ## @item @var{QQ}@{i@} ## List of queues in the network. This must be a cell array ## with @math{N} elements, such that @code{@var{QQ}@{i@}} is ## a struct produced by the @code{qnmknode} function. ## ## @item @var{Z} ## External delay ("think time") for closed networks. Default 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(k) ## If @math{k} is a FCFS node, then @code{@var{U}(k)} is the utilization ## of service center @math{k}. If @math{k} is an IS node, then ## @code{@var{U}(k)} is the @emph{traffic intensity} defined as ## @code{@var{X}(k)*@var{S}(k)}. ## ## @item @var{R}(k) ## average response time of service center @math{k}. ## ## @item @var{Q}(k) ## average number of customers in service center @math{k}. ## ## @item @var{X}(k) ## throughput of service center @math{k}. ## ## @end table ## ## Note that for multiclass networks, the computed results are per-class ## utilization, response time, number of customers and throughput: ## @code{@var{U}(c,k)}, @code{@var{R}(c,k)}, @code{@var{Q}(c,k)}, ## @code{@var{X}(c,k)}. ## ## String literals are case-insensitive, so @var{"closed"}, @var{"Closed"} ## and @var{"CLoSEd"} are all equivalent. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qnsolve( network_type, varargin ) if ( nargin < 2 ) print_usage(); endif ischar(network_type) || ... error("First parameter must be a string"); network_type = tolower(network_type); if ( strcmp(network_type, "open" ) ) [U R Q X] = __qnsolve_open( varargin{:} ); elseif ( strcmp(network_type, "closed" ) ) [U R Q X] = __qnsolve_closed( varargin{:} ); elseif (strcmp(network_type, "mixed" ) ) [U R Q X] = __qnsolve_mixed( varargin{:} ); else error( "Invalid network type %s: must be one of \"open\", \"closed\" or \"mixed\"", network_type ); endif endfunction ############################################################################## ## Dispatcher function for open networks function [U R Q X] = __qnsolve_open( lambda, varargin ) if ( isscalar(lambda) ) [U R Q X] = __qnsolve_open_single( lambda, varargin{:} ); else [U R Q X] = __qnsolve_open_multi( lambda, varargin{:} ); endif endfunction ############################################################################## ## Worker function for open, single class networks function [U R Q X] = __qnsolve_open_single( lambda, QQ, V ) if ( nargin != 3 ) print_usage(); endif ( isscalar(lambda) && (lambda>0) ) || ... error( "lambda must be a scalar > 0" ); iscell(QQ) || ... error( "QQ must be a cell array" ); N = length(QQ); ( isvector(V) && length(V) == N ) || ... error( "V must be a vector of length %d", N ); V = V(:); # make V a row vector all(V>=0) || ... error( "V must be >= 0" ); ## Initialize vectors S = zeros(size(V)); m = ones(size(V)); for i=1:N QQ{i}.c == 1 || ... error( "Multiclass networks are not supported by this function" ); S(i) = QQ{i}.S; if __is_li(QQ{i}) ; # nothing to do elseif __is_multi(QQ{i}) m(i) = QQ{i}.m; elseif __is_is(QQ{i}) m(i) = -1; else error( "Unsupported type \"%s\" for node %d", QQ{i}.node, i ); endif endfor [U R Q X] = qnos( lambda, S, V, m ); __prettyprint( 0, lambda, QQ, V, U, R, Q, X ); endfunction ############################################################################## ## Worker function for open, multiclass networks function [U R Q X] = __qnsolve_open_multi( lambda, QQ, V ) if ( nargin != 3 ) print_usage(); endif isvector(lambda) && all(lambda > 0) || ... error( "lambda must be a vector >0" ); lambda = lambda(:)'; # make lambda a row vector iscell(QQ) || ... error( "QQ must be a cell array" ); C = length(lambda); K = length(QQ); [C,K] == size(V) || ... error( "V size mismatch" ); all( all( V>= 0 ) ) || ... error( "V must be >= 0 " ); S = zeros(C,K); m = ones(1,K); for i=1:K QQ{i}.c == C || ... error( "Wrong number of classes for center %d (is %d, should be %d)", i, QQ{i}.c, C ); S(:,i) = QQ{i}.S(:); if __is_li(QQ{i}) ; # nothing to do elseif __is_is(QQ{i}) m(i) = -1; else error( "Unsupported type \"%s\" for node %d", QQ{i}.node, i ); endif endfor [U R Q X] = qnom( lambda, S, V, m ); __prettyprint( 0, lambda, QQ, V, U, R, Q, X ); endfunction ############################################################################## ## Dispatcher function for closed networks function [U R Q X] = __qnsolve_closed( N, varargin ) if ( isscalar(N) ) [U R Q X] = __qnsolve_closed_single( N, varargin{:} ); else [U R Q X] = __qnsolve_closed_multi( N, varargin{:} ); endif endfunction ############################################################################## ## Worker function for closed, single-class networks function [U R Q X] = __qnsolve_closed_single( N, QQ, V, Z ) if ( nargin < 3 || nargin > 4 ) error(); endif isscalar(N) || ... error( "Multiclass networks are not supported by this function" ); iscell(QQ) || ... error( "QQ must be a cell array" ); if ( nargin < 4 ) Z = 0; else isscalar(Z) && Z >= 0 || ... error( "Z must be >= 0" ); endif K = length(QQ); ( isvector(V) && length(V) == K ) || ... error( "V must be a vector of length %d", K ); found_ld = false; for k=1:K if ( __is_ld(QQ{k}) ) found_ld = true; break; endif endfor if ( found_ld ) S = zeros(K, N); for k=1:K ( QQ{k}.c == 1 ) || ... error( "Multiclass networks are not supported by this function" ); if __is_li(QQ{k}) S(k,:) = QQ{k}.S; elseif __is_multi(QQ{k}) S(k,:) = QQ{k}.S ./ min(1:N,QQ{k}.m); elseif __is_is(QQ{k}) S(k,:) = QQ{k}.S ./ (1:N); elseif __is_ld(QQ{k}) S(k,:) = QQ{k}.S; else error( "Unsupported type \"%s\" for node %d", QQ{k}.node, k ); endif endfor [U R Q X] = qncsmvald(N, S, V, Z); else S = zeros(1,K); m = ones(1,K); for k=1:K ( QQ{k}.c == 1 ) || ... error( "Multiclass networks are not supported by this function" ); S(k) = QQ{k}.S; if __is_li(QQ{k}) # nothing to do elseif __is_multi(QQ{k}) m(k) = QQ{k}.m; elseif __is_is(QQ{k}) m(k) = -1; else error( "Unsupported type \"%s\" for node %d", QQ{k}.node, k ); endif endfor [U R Q X] = qncsmva(N, S, V, m, Z); endif __prettyprint( N, 0, QQ, V, U, R, Q, X ); endfunction ############################################################################## ## Worker function for closed, multi-class networks function [U R Q X] = __qnsolve_closed_multi( N, QQ, V, Z ) if ( nargin < 3 || nargin > 4 ) print_usage(); endif isvector(N) && all( N>0 ) || ... error( "N must be >0" ); iscell(QQ) || ... error( "QQ must be a cell array" ); C = length(N); ## Number of classes K = length(QQ); ## Number of service centers size(V) == [C,K] || ... error( "V size mismatch" ); if ( nargin < 4 ) Z = zeros(1,C); else isvector(Z) && length(Z) == C || ... error( "Z size mismatch" ); endif ## Check consistence of parameters all( all( V >= 0 ) ) || ... error( "V must be >=0" ); ## Initialize vectors i_single = i_multi = i_delay = i_ld = []; S = zeros(C,K); for i=1:K ( QQ{i}.c == C ) || ... error( "Service center %d has wrong number of classes (is %d, should be %d)", i, QQ{i}.c, C ); if __is_li(QQ{i}) i_single = [i_single i]; ( !strcmpi( QQ{i}.node, "m/m/m-fcfs" ) || all( QQ{i}.S(1) == QQ{i}.S )) || ... error( "Service times at FIFO node %d are not class-independent", i ); elseif __is_multi(QQ{i}) i_multi = [i_multi i]; elseif __is_is(QQ{i}) i_delay = [i_delay i]; elseif __is_ld(QQ{i}) columns( QQ{i}.S ) == sum(N) || ... error( "Load-dependent center %d has insufficient data (is %d, should be %d", i, columns(QQ{i}.S), sum(N) ); i_ld = [i_ld i]; else error( "Unknown or unsupported type \"%s\" for node %d", QQ{i}.node, i ); endif endfor ## Initialize results U = R = zeros( C, K ); X = zeros( 1, C ); Q_next = Q = sparse( prod(N+1),K ); p = cell(1,K); for k=i_multi ## p{i}(j+1,k+1) is the probability to have j jobs at node i ## where the network is in state k p{k} = zeros( QQ{k}.m+1,prod(N+1) ); p{k}(1,__get_idx( N, 0*N )) = 1; endfor for k=i_ld ## p{i}(j+1,k+1) is the probability to have j jobs at node i ## where the network is in state k p{k} = zeros( columns(QQ{k}.S )+1, prod(N+1) ); p{k}(1,__get_idx( N, 0*N )) = 1; endfor ## Main loop for n=1:sum(N) feasible_set = qncmpopmix( n, N ); for nn=1:rows(feasible_set) n_bar = feasible_set(nn,:); for c=1:C if ( n_bar(c) > 0 ) ## single server nodes for k=i_single n_bar_c = __minusonec(n_bar,c); idx = __get_idx( N, n_bar_c ); R(c,k) = QQ{k}.S(c)*(1 + Q( idx, k ) ); ## for FCFS nodes with class-dependent service times, ## it is possible to use the following approximation ## (p. 469 Bolch et al.) ## ## R(c,k) = S(c,k) + sum( S(:,k) * Q(idx(:), k) ); endfor ## multi server nodes for k=i_multi n_bar_c = __minusonec(n_bar,c); idx = __get_idx( N, n_bar_c ); j=0:QQ{k}.m-2; # range R(c,k) = QQ{k}.S(c)/QQ{k}.m*(1 + Q( idx, k ) + ... dot(QQ{k}.m-j-1,p{k}(j+1,idx) ) ); endfor ## General load-dependent nodes for k=i_ld n_bar_c = __minusonec(n_bar,c); idx = __get_idx( N, n_bar_c ); j=1:sum(n_bar); # range R(c,k) = sum( j .* QQ{k}.S(c,j) .* p{k}(j,idx)' ); endfor endif ## delay centers for k=i_delay R(c,k) = QQ{k}.S(c); endfor endfor # c X = n_bar ./ ( Z + dot(R,V,2)' ); # X(c) = N(c) / ( Z(c) + sum_k R(c,k) * V(c,k) ) idx = __get_idx( N, n_bar ); ## Q_k = sum_c X(c) * R(c,k) for k=1:K Q_next( idx, k ) = dot( X, R(:,k) .* V(:,k) ); endfor ## Adjust probabilities for multiple server nodes for k=i_multi s=0; # it is actually a vector j=1:QQ{k}.m-1; for r=find(n_bar>0) # I don't know how to vectorize this ii = __minusonec(n_bar,r); s+=QQ{k}.S(r)*V(r,k)*X(r)*p{k}(j,__get_idx(N,ii)); endfor p{k}(j+1,idx) = s./j; p{k}(1,idx) = 1-1/QQ{k}.m*(sum( QQ{k}.S(:) .* V(:,k) .* X(:) ) + ... dot( QQ{k}.m-j, p{k}(j+1,idx) ) ); endfor ## Adjust probabilities for general load-dependent server nodes for k=i_ld s=0; # it is actually a vector j=1:sum(n_bar); for r=find(n_bar>0) ii = __minusonec(n_bar,r); s+=QQ{k}.S(r,sum(n_bar))*V(r,k)*X(r)*p{k}(j,__get_idx(N,ii)); endfor p{k}(j+1,idx) = s; p{k}(1,idx) = 1-sum(p{k}(1+j,idx)); endfor endfor Q = Q_next; Q_next = sparse( prod(N+1), K ); endfor for k=1:K if __is_ld(QQ{k}) U(:,k) = 1-p{k}(1, __get_idx(N,N)); else U(:,k) = X(:) .* QQ{k}.S(:) .* V(:,k); # U(c,k) = X(c)*D(c,k) endif endfor Q = (diag(X)*R).*V; # dmult(X,R).*V; X = diag(X)*V; # dmult(X,V); endfunction ############################################################################## ## Compute the linear index corresponding to vector i from a population ## of N. function idx = __get_idx( N, i ) i_cell = num2cell( i+1 ); idx = sub2ind( N+1, i_cell{:} ); endfunction ############################################################################## ## Given an input vector n, returns an output vector r which is equal to ## n except that the element at the c-th position is decreased by one: ## r(c) = n(c)-1. Warning: no check is made on the parameters function r = __minusonec( n, c ) r = n; r(c) -= 1; endfunction ############################################################################## ## Worker function for mixed networks. This function delegates to qnmix function [U R Q X] = __qnsolve_mixed( lambda, N, QQ, V ) if ( nargin != 4 ) print_usage(); endif ( isvector(lambda) && isvector(N) && size_equal(lambda,N) ) || ... error( "lambda and N must be vectors of the same size" ); ( iscell(QQ) && length(QQ) == length(lambda) ) || ... error( "QQ size mismatch (is %d, should be %d)", length(QQ), length(lambda) ); C = length(lambda); # number of classes K = length(QQ); # number of service centers S = zeros(C,K); m = ones(1,K); ## fill S matrix for k=1:K if __is_ld(QQ{k}) error( "General load-dependent service center %d is not supported", k ); elseif __is_is(QQ{k}) m(k) = -1; else m(k) = QQ{k}.m; endif S(:,k) = QQ{k}.S; endfor [U R Q X] = qnmix( lambda, N, S, V, m ); __prettyprint( N, lambda, QQ, V, U, R, Q, X ); endfunction ############################################################################## ## return true iff Q is an infinite server (IS) node function result = __is_is( Q ) result = strcmp(Q.node, "-/g/inf" ); endfunction ############################################################################## ## return true iff Q is a multi-server FIFO node function result = __is_multi( Q ) result = (strcmp(Q.node, "m/m/m-fcfs") && Q.m>1); endfunction ############################################################################## ## return true iff Q is a single-server, load-dependent node function result = __is_ld( Q ) result = ( (strcmp(Q.node, "m/m/m-fcfs") || ... strcmp(Q.node, "-/g/1-lcfs-pr") || ... strcmp(Q.node, "-/g/1-ps" ) ) && ... columns( Q.S ) > 1 ); endfunction ############################################################################## ## return ture iff Q is a single-server, load-independent node function result = __is_li( Q ) result = ((Q.m==1) && (1 == columns( Q.S )) && !strcmp( Q.node, "-/g/inf" ) ); endfunction ############################################################################## ## This function is used to "pretty-print" a solved network. Used for ## debugging function __prettyprint( N, lambda, QQ, V, U, R, Q, X ) return; ## immediately return [errorcode, N, lambda] = common_size( N, lambda ); if ( errorcode) error( "N and lambda are of incompatible size" ); endif ( isvector(N) && isvector(lambda) && size_equal(lambda,N) ) || ... error( "N and lambda must be vector of the same length" ); C = length(N); K = length(QQ); # number of service centers [C,K] == size(V) || ... error( "V size mismatch" ); [C,K] == size(U) || ... error( "U size mismatch" ); [C,K] == size(R) || ... error( "R size mismatch" ); [C,K] == size(Q) || ... error( "Q size mismatch" ); [C,K] == size(X) || ... error( "X size mismatch" ); for c=1:C printf("\n"); printf("=== CLASS %d ===\n", c ); if ( N(c)>0 ) printf("Type: CLOSED\nPopulation: %d\n", N(c)) else printf("Type: OPEN\nRequests arrival rate: %6.2f\n", lambda(c)) endif printf("\n"); printf("+---+---------------+---+------+------+------+------+------+------+\n"); printf("| i | Node type | m | S(i) | V(i) | U(i) | R(i) | Q(i) | X(i) |\n"); printf("+---+---------------+---+------+------+------+------+------+------+\n"); for i=1:K if ( isscalar(QQ{i}.S(c)) ) serv = sprintf("%6.2f",QQ{i}.S(c)); else serv = "LD"; endif printf("|%3d|%-33s| | | | |\n", i, QQ{i}.comment); printf("| |%15s|%3d|%6s|%6.2f|%6.4f|%6.2f|%6.2f|%6.2f|\n", QQ{i}.node, QQ{i}.m, serv, V(c,i), U(c,i), R(c,i), Q(c,i), X(c,i) ); endfor printf("+---+---------------+---+------+------+------+------+------+------+\n"); printf("| THIS CLASS STATISTICS | ---- |%6.2f|%6.2f|%6.2f|\n", dot(R(c,:),V(c,:)), sum(Q(c,:)), X(c,1)/V(c,1) ); printf("+---+---------------+---+------+------+------+------+------+------+\n\n"); endfor endfunction %!test %! # Example 8.7 p. 349 Bolch et al. %! N = 3; %! Q1 = qnmknode( "m/m/m-fcfs", .5, 2 ); %! Q2 = qnmknode( "m/m/m-fcfs", 1/1.667 ); %! Q3 = qnmknode( "m/m/m-fcfs", 1/1.25 ); %! Q4 = qnmknode( "m/m/m-fcfs", 1./[1 2 3] ); %! V = [ 1 .5 .5 1 ]; %! [U R Q X] = qnsolve("closed",N, { Q1, Q2, Q3, Q4 }, V); %! assert( Q, [0.624 0.473 0.686 1.217], 1e-3 ); %! assert( R, [0.512 0.776 1.127 1], 1e-3 ); %!test %! # Example 8.7 p. 349 Bolch et al. %! N = 3; %! Q1 = qnmknode( "m/m/m-fcfs", 1/2, 2 ); %! Q2 = qnmknode( "m/m/m-fcfs", 1/1.667 ); %! Q3 = qnmknode( "m/m/m-fcfs", 1/1.25 ); %! Q4 = qnmknode( "-/g/inf", 1 ); %! V = [ 1 .5 .5 1 ]; %! [U R Q X] = qnsolve("closed",N, { Q1, Q2, Q3, Q4 }, V); %! assert( Q, [0.624 0.473 0.686 1.217], 1e-3 ); %! assert( R, [0.512 0.776 1.127 1], 1e-3 ); %!test %! # Example 8.4 p. 333 Bolch et al. %! N = 3; %! Q1 = qnmknode( "m/m/m-fcfs", .5, 2 ); %! Q2 = qnmknode( "m/m/m-fcfs", .6 ); %! Q3 = qnmknode( "m/m/m-fcfs", .8 ); %! Q4 = qnmknode( "-/g/inf", 1 ); %! V = [ 1 .5 .5 1 ]; %! [U R Q X] = qnsolve("closed",N, { Q1, Q2, Q3, Q4 }, V); %! assert( U(1:3), [.304 .365 .487], 1e-3 ); %! assert( X, [1.218 0.609 0.609 1.218], 1e-3 ); %!test %! # Same as above, with center 1 replaced with a load-dependent service center %! N = 3; %! Q1 = qnmknode( "m/m/m-fcfs", [.5 .25 .25] ); %! Q2 = qnmknode( "m/m/m-fcfs", .6 ); %! Q3 = qnmknode( "m/m/m-fcfs", .8 ); %! Q4 = qnmknode( "m/m/m-fcfs", [1 1/2 1/3] ); %! V = [ 1 .5 .5 1 ]; %! [U R Q X] = qnsolve("closed",N, { Q1, Q2, Q3, Q4 }, V); %! assert( U(2:3), [.365 .487], 1e-3 ); ## NOTE: Utilization U(1) is computed differently from M/M/m nodes and load-dependent M/M/1 nodes %! assert( X, [1.218 0.609 0.609 1.218], 1e-3 ); %!test %! # Example 7.4 p. 287 Bolch et al. %! QQ = { qnmknode( "m/m/m-fcfs", 0.04 ), ... %! qnmknode( "m/m/m-fcfs", 0.03 ), ... %! qnmknode( "m/m/m-fcfs", 0.06 ), ... %! qnmknode( "m/m/m-fcfs", 0.05 ) }; %! P = [ 0 0.5 0.5 0; 1 0 0 0; 0.6 0 0 0; 1 0 0 0 ]; %! lambda = [0 0 0 4]; %! [U R Q X] = qnsolve("open", sum(lambda), QQ, qnosvisits(P,lambda) ); %! assert( X, [20 10 10 4], 1e-4 ); %! assert( U, [0.8 0.3 0.6 0.2], 1e-2 ); %! assert( R, [0.2 0.043 0.15 0.0625], 1e-3 ); %! assert( Q, [4, 0.429 1.5 0.25], 1e-3 ); %!test %! V = [1 1; 1 1]; %! Q1 = qnmknode( "m/m/m-fcfs", [1;2] ); %! Q2 = qnmknode( "m/m/m-fcfs", [3;4] ); %! lambda = [3/19 2/19]; %! [U R Q] = qnsolve("open", lambda, { Q1, Q2 }, diag( lambda / sum(lambda) ) * V); %! assert( U(1,1), 3/19, 1e-6 ); %! assert( U(2,1), 4/19, 1e-6 ); %! assert( R(1,1), 19/12, 1e-6 ); %! assert( R(1,2), 57/2, 1e-6 ); %! assert( Q(1,1), .25, 1e-6 ); ## Example 9.5 p. 337, Bolch et al. %!test %! QQ = { qnmknode( "m/m/m-fcfs", [0.2; 0.2], 2 ), ... %! qnmknode( "-/g/1-ps", [0.4; 0.6] ), ... %! qnmknode( "-/g/inf", [1; 2] ) }; %! V = [ 1 0.6 0.4; 1 0.3 0.7 ]; %! N = [ 2 1 ]; %! [U R Q X] = qnsolve( "closed", N, QQ, V ); %! assert( Q, [ 0.428 0.726 0.845; 0.108 0.158 0.734 ], 1e-3 ); %! assert( X(1,1), 2.113, 1e-3 ); # CHECK %! assert( X(2,1), 0.524, 1e-3 ); # CHECK %! assert( all( all(U(:,[1,2])<=1) ) ); ## Same as above, but with general load-dependent centers %!test %! QQ = { qnmknode( "m/m/m-fcfs", [0.2 0.1 0.1; 0.2 0.1 0.1] ), ... %! qnmknode( "-/g/1-ps", [0.4; 0.6] ), ... %! qnmknode( "-/g/inf", [1; 2] ) }; %! V = [ 1 0.6 0.4; 1 0.3 0.7 ]; %! N = [ 2 1 ]; %! [U R Q X] = qnsolve( "closed", N, QQ, V ); %! assert( Q, [ 0.428 0.726 0.845; 0.108 0.158 0.734 ], 1e-3 ); %! assert( X(1,1), 2.113, 1e-3 ); # CHECK %! assert( X(2,1), 0.524, 1e-3 ); # CHECK %! assert( all( all(U(:,[1,2])<=1) ) ); %!test %! # example p. 26 Schwetman %! QQ = { qnmknode( "m/m/m-fcfs", [.25; .25] ), %! qnmknode( "-/g/1-ps", [0; .1] ) }; %! V = [1 0; 1 1]; %! lambda = [1 0]; %! N = [0 3]; %! [U R Q X] = qnsolve( "mixed", lambda, N, QQ, V ); %! assert( U(1,1), .25, 1e-3 ); %! assert( X(1,1), 1.0, 1e-3 ); %! assert( [R(1,1) R(2,1) R(2,2)], [1.201 0.885 0.135], 1e-3 ); %!demo %! QQ = { qnmknode( "m/m/m-fcfs", [0.2 0.1 0.1; 0.2 0.1 0.1] ), ... %! qnmknode( "-/g/1-ps", [0.4; 0.6] ), ... %! qnmknode( "-/g/inf", [1; 2] ) }; %! V = [ 1 0.6 0.4; ... %! 1 0.3 0.7 ]; %! N = [ 2 1 ]; %! [U R Q X] = qnsolve( "closed", N, QQ, V ); queueing/inst/qsmm1.m0000664000175000017500000001075714620404470014466 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2018, 2019, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qsmm1 (@var{lambda}, @var{mu}) ## @deftypefnx {Function File} {@var{pk} =} qsmm1 (@var{lambda}, @var{mu}, @var{k}) ## ## @cindex @math{M/M/1} system ## ## Compute utilization, response time, average number of requests and throughput for a @math{M/M/1} queue. ## ## @tex ## The steady-state probability @math{\pi_k} that there are @math{k} ## jobs in the system, @math{k \geq 0}, can be computed as: ## ## $$ ## \pi_k = (1-\rho)\rho^k ## $$ ## ## where @math{\rho = \lambda/\mu} is the server utilization. ## ## @end tex ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate (@code{@var{lambda} @geq{} 0}). ## ## @item @var{mu} ## Service rate (@code{@var{mu} > @var{lambda}}). ## ## @item @var{k} ## Number of requests in the system (@code{@var{k} @geq{} 0}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U} ## Server utilization ## ## @item @var{R} ## Server response time ## ## @item @var{Q} ## Average number of requests in the system ## ## @item @var{X} ## Server throughput. If the system is ergodic (@code{@var{mu} > ## @var{lambda}}), we always have @code{@var{X} = @var{lambda}} ## ## @item @var{p0} ## Steady-state probability that there are no requests in the system. ## ## @item @var{pk} ## Steady-state probability that there are @var{k} requests in the system. ## (including the one being served). ## ## @end table ## ## If this function is called with less than three input parameters, ## @var{lambda} and @var{mu} can be vectors of the same size. In this ## case, the results will be vectors as well. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks ## and Markov Chains: Modeling and Performance Evaluation with Computer ## Science Applications}, Wiley, 1998, Section 6.3 ## @end itemize ## ## @seealso{qsmmm, qsmminf, qsmmmk} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U_or_pk R Q X p0] = qsmm1( lambda, mu, k ) if ( nargin < 2 || nargin > 3 ) print_usage(); endif ( isvector(lambda) && isvector(mu) ) || ... error( "lambda and mu must be vectors" ); [ err lambda mu ] = common_size( lambda, mu ); if ( err ) error( "parameters are of incompatible size" ); endif lambda = lambda(:)'; mu = mu(:)'; all( lambda >= 0 ) || error( "lambda must be >= 0" ); rho = lambda ./ mu; all( rho < 1 ) || error( "Processing capacity exceeded" ); if (nargin == 2) U_or_pk = rho; # utilization p0 = 1-rho; Q = rho ./ (1-rho); R = 1 ./ ( mu .* (1-rho) ); X = lambda; else (length(lambda) == 1) || error("lambda must be a scalar if this function is called with three arguments"); isvector(k) || error("k must be a vector"); all(k>=0) || error("k must be >= 0"); k = k(:)'; # make k a row vector U_or_pk = (1 - rho).*rho.^k; endif endfunction %!test %! fail( "qsmm1(10,5)", "capacity exceeded" ); %! fail( "qsmm1(1,1)", "capacity exceeded" ); %! fail( "qsmm1([2 2], [1 1 1])", "incompatible size"); %!test %! [U R Q X P0] = qsmm1(0, 1); %! assert( U, 0 ); %! assert( R, 1 ); %! assert( Q, 0 ); %! assert( X, 0 ); %! assert( P0, 1 ); %!test %! [U R Q X P0] = qsmm1(0.2, 1.0); %! pk = qsmm1(0.2, 1.0, 0); %! assert(P0, pk); %!demo %! ## Given a M/M/1 queue, compute the steady-state probability pk %! ## of having k requests in the systen. %! lambda = 0.2; %! mu = 0.25; %! k = 0:10; %! pk = qsmm1(lambda, mu, k); %! plot(k, pk, "-o", "linewidth", 2); %! xlabel("N. of requests (k)"); %! ylabel("p_k"); %! title(sprintf("M/M/1 system, \\lambda = %g, \\mu = %g", lambda, mu)); queueing/inst/qncsmva.m0000664000175000017500000003075614620404470015101 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2016, 2018, 2020, 2021 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsmva (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsmva (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qncsmva (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## ## @cindex Mean Value Analysys (MVA) ## @cindex closed network, single class ## @cindex normalization constant ## ## Analyze closed, single class queueing networks using the exact Mean Value Analysis (MVA) algorithm. ## ## The following queueing disciplines are supported: FCFS, LCFS-PR, PS ## and IS (Infinite Server). This function supports fixed-rate service ## centers or multiple server nodes. For general load-dependent service ## centers, use the function @code{qncsmvald} instead. ## ## Additionally, the normalization constant @math{G(n)}, @math{n=0, ## @dots{}, N} is computed; @math{G(n)} can be used in conjunction with ## the BCMP theorem to compute steady-state probabilities. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## Population size (number of requests in the system, @code{@var{N} @geq{} 0}). ## If @code{@var{N} == 0}, this function returns ## @code{@var{U} = @var{R} = @var{Q} = @var{X} = 0} ## ## @item @var{S}(k) ## mean service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). ## ## @item @var{V}(k) ## average number of visits to service center @math{k} (@code{@var{V}(k) @geq{} 0}). ## ## @item @var{Z} ## External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. ## ## @item @var{m}(k) ## number of servers at center @math{k} (if @var{m} is a scalar, all ## centers have that number of servers). If @code{@var{m}(k) < 1}, ## center @math{k} is a delay center (IS); otherwise it is a regular ## queueing center (FCFS, LCFS-PR or PS) with @code{@var{m}(k)} ## servers. Default is @code{@var{m}(k) = 1} for all @math{k} (each ## service center has a single server). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(k) ## If @math{k} is a FCFS, LCFS-PR or PS node (@code{@var{m}(k) @geq{} ## 1}), then @code{@var{U}(k)} is the utilization of center @math{k}, ## @math{0 @leq{} U(k) @leq{} 1}. If @math{k} is an IS node ## (@code{@var{m}(k) < 1}), then @code{@var{U}(k)} is the @emph{traffic ## intensity} defined as @code{@var{X}(k)*@var{S}(k)}. In this case the ## value of @code{@var{U}(k)} may be greater than one. ## ## @item @var{R}(k) ## center @math{k} response time. The @emph{Residence Time} at center ## @math{k} is @code{@var{R}(k) * @var{V}(k)}. The system response ## time @var{Rsys} can be computed either as @code{@var{Rsys} = ## @var{N}/@var{Xsys} - Z} or as @code{@var{Rsys} = ## dot(@var{R},@var{V})} ## ## @item @var{Q}(k) ## average number of requests at center @math{k}. The number of ## requests in the system can be computed either as ## @code{sum(@var{Q})}, or using the formula ## @code{@var{N}-@var{Xsys}*@var{Z}}. ## ## @item @var{X}(k) ## center @math{K} throughput. The system throughput @var{Xsys} can be ## computed as @code{@var{Xsys} = @var{X}(1) / @var{V}(1)} ## ## @item @var{G}(n) ## Normalization constants. @code{@var{G}(n+1)} contains the value of ## the normalization constant @math{G(n)}, @math{n=0, @dots{}, N} as ## array indexes in Octave start from 1. @math{G(n)} can be used in ## conjunction with the BCMP theorem to compute steady-state ## probabilities. ## ## @end table ## ## @strong{NOTES} ## ## In presence of load-dependent servers (i.e., if @code{@var{m}(k)>1} ## for some @math{k}), the MVA algorithm is known to be numerically ## unstable. Generally, this issue manifests itself as negative values ## for the response times or utilizations. This is not a problem of ## the @code{queueing} toolbox, but of the MVA algorithm, and has ## currently no known solution. This function prints a warning if ## numerical problems are detected; the warning can be disabled with ## the command @code{warning("off", "qn:numerical-instability")}. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed ## Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, April ## 1980, pp. 313--322. @uref{http://doi.acm.org/10.1145/322186.322195, 10.1145/322186.322195} ## @end itemize ## ## This implementation is described in R. Jain , @cite{The Art of ## Computer Systems Performance Analysis}, Wiley, 1991, p. 577. ## Multi-server nodes are treated according to G. Bolch, S. Greiner, ## H. de Meer and K. Trivedi, @cite{Queueing Networks and Markov Chains: ## Modeling and Performance Evaluation with Computer Science ## Applications}, Wiley, 1998, Section 8.2.1, "Single Class Queueing ## Networks". ## ## @seealso{qncsmvald,qncscmva} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X G] = qncsmva( varargin ) if ( nargin < 3 || nargin > 5 ) print_usage(); endif [err N S V m Z] = qncschkparam( varargin{:} ); isempty(err) || error(err); K = length(S); # Number of servers U = R = Q = X = zeros( 1, K ); G = zeros(1,N+1); G(1) = 1; if ( N == 0 ) # Trivial case of empty population: just return all zeros return; endif i_single = find( m==1 ); i_multi = find( m>1 ); i_delay = find( m<1 ); ## Initialize results if ( length(i_multi)>0 ) p = zeros( K, max(m)+1 ); # p(i,j+1) is the probability that there are j jobs at server i p(:,1) = 1; endif X_s = 0; # System throughput ## Main MVA loop, iterates over the population size for n=1:N R(i_single) = S(i_single) .* (1 + Q(i_single)); for i=i_multi # I cannot easily vectorize this j=0:m(i)-2; R(i) = S(i) / m(i) * (1+Q(i)+dot( m(i)-j-1, p( i, 1+j ) ) ); endfor R(i_delay) = S(i_delay); R_s = dot( V, R ); # System response time X_s = n / ( Z + R_s ); # System Throughput Q = X_s * ( V .* R ); G(1+n) = G(n) / X_s; ## prepare for next iteration lambda_i = V * X_s; # lambda_i(i) is the node i throughput for i=i_multi j=1:m(i)-1; # range p(i, j+1) = lambda_i(i) .* S(i) ./ min( j,m(i) ) .* p(i,j); p(i,1) = 1 - 1/m(i) * ... (V(i)*S(i)*X_s + dot( m(i)-j, p(i,j+1)) ); endfor endfor X = X_s * V; # Service centers throughput U(i_single) = X(i_single) .* S(i_single); U(i_delay) = X(i_delay) .* S(i_delay); U(i_multi) = X(i_multi) .* S(i_multi) ./ m(i_multi); if ( any(U<0) || any(R<0) ) warning("qn:numerical-instability", "Numerical instability detected. Type 'help qncsmva' for details"); endif endfunction #{ ## This function is slightly faster (and more compact) than the above ## when all servers are single-server or delay centers. Improvements are ## quite small (10%-15% faster, depends on the network size), so at the ## moment it is commented out. function [U R Q X G] = __qncsmva_fast( N, S, V, m, Z ) U = R = Q = X = zeros( 1, length(S) ); X_s = 0; # System throughput G = zeros(1,N+1); G(1) = 1; ## Main MVA loop for n=1:N R = S .* (1+Q.*(m==1)); R_s = dot( V, R ); # System response time X_s = n / ( Z + R_s ); # System Throughput Q = X_s * ( V .* R ); G(1+n) = G(n) / X_s; endfor X = X_s * V; # Service centers throughput U = X .* S; endfunction #} %!test %! fail( "qncsmva()", "Invalid" ); %! fail( "qncsmva( 10, [1 2], [1 2 3] )", "incompatible size" ); %! fail( "qncsmva( 10, [-1 1], [1 1] )", "nonnegative" ); %! fail( "qncsmva( 10.3, [-1 1], [1 1] )", "integer" ); %! fail( "qncsmva( -0.3, [-1 1], [1 1] )", "nonnegative" ); ## Check if networks with only one type of server are handled correctly %!test %! qncsmva(1,1,1,1); %! qncsmva(1,1,1,-1); %! qncsmva(1,1,1,2); %! qncsmva(1,[1 1],[1 1],[-1 -1]); %! qncsmva(1,[1 1],[1 1],[1 1]); %! qncsmva(1,[1 1],[1 1],[2 2]); ## Check degenerate case of N==0 (LI case) %!test %! N = 0; %! S = [1 2 3 4]; %! V = [1 1 1 4]; %! [U R Q X] = qncsmva(N, S, V); %! assert( U, 0*S ); %! assert( R, 0*S ); %! assert( Q, 0*S ); %! assert( X, 0*S ); ## Check degenerate case of N==0 (LD case) %!test %! N = 0; %! S = [1 2 3 4]; %! V = [1 1 1 4]; %! m = [2 3 4 5]; %! [U R Q X] = qncsmva(N, S, V, m); %! assert( U, 0*S ); %! assert( R, 0*S ); %! assert( Q, 0*S ); %! assert( X, 0*S ); %!test %! # Exsample 3.42 p. 577 Jain %! S = [ 0.125 0.3 0.2 ]'; %! V = [ 16 10 5 ]; %! N = 20; %! m = ones(1,3)'; %! Z = 4; %! [U R Q X] = qncsmva(N,S,V,m,Z); %! assert( R, [ .373 4.854 .300 ], 1e-3 ); %! assert( Q, [ 1.991 16.177 0.500 ], 1e-3 ); %! assert( all( U>=0 ) ); %! assert( all( U<=1 ) ); %! assert( Q, R.*X, 1e-5 ); # Little's Law %!test %! # Exsample 3.42 p. 577 Jain %! S = [ 0.125 0.3 0.2 ]; %! V = [ 16 10 5 ]; %! N = 20; %! m = ones(1,3); %! Z = 4; %! [U R Q X] = qncsmva(N,S,V,m,Z); %! assert( R, [ .373 4.854 .300 ], 1e-3 ); %! assert( Q, [ 1.991 16.177 0.500 ], 1e-3 ); %! assert( all( U>=0 ) ); %! assert( all( U<=1 ) ); %! assert( Q, R.*X, 1e-5 ); # Little's Law %!test %! # Example 8.4 p. 333 Bolch et al. %! S = [ .5 .6 .8 1 ]; %! N = 3; %! m = [2 1 1 -1]; %! V = [ 1 .5 .5 1 ]; %! [U R Q X] = qncsmva(N,S,V,m); %! assert( Q, [ 0.624 0.473 0.686 1.217 ], 1e-3 ); %! assert( X, [ 1.218 0.609 0.609 1.218 ], 1e-3 ); %! assert( all(U >= 0 ) ); %! assert( all(U( m>0 ) <= 1 ) ); %! assert( Q, R.*X, 1e-5 ); # Little's Law %!test %! # Example 8.3 p. 331 Bolch et al. %! # This is a single-class network, which however nothing else than %! # a special case of multiclass network %! S = [ 0.02 0.2 0.4 0.6 ]; %! K = 6; %! V = [ 1 0.4 0.2 0.1 ]; %! [U R Q X] = qncsmva(K, S, V); %! assert( U, [ 0.198 0.794 0.794 0.595 ], 1e-3 ); %! assert( R, [ 0.025 0.570 1.140 1.244 ], 1e-3 ); %! assert( Q, [ 0.244 2.261 2.261 1.234 ], 1e-3 ); %! assert( X, [ 9.920 3.968 1.984 0.992 ], 1e-3 ); %!test %! # Check bound analysis %! N = 10; # max population %! for n=1:N %! S = [1 0.8 1.2 0.5]; %! V = [1 2 2 1]; %! [U R Q X] = qncsmva(n, S, V); %! Xs = X(1)/V(1); %! Rs = dot(R,V); %! # Compare with balanced system bounds %! [Xlbsb Xubsb Rlbsb Rubsb] = qncsbsb( n, S .* V ); %! assert( Xlbsb<=Xs ); %! assert( Xubsb>=Xs ); %! assert( Rlbsb<=Rs ); %! assert( Rubsb>=Rs ); %! # Compare with asymptotic bounds %! [Xlab Xuab Rlab Ruab] = qncsaba( n, S .* V ); %! assert( Xlab<=Xs ); %! assert( Xuab>=Xs ); %! assert( Rlab<=Rs ); %! assert( Ruab>=Rs ); %! endfor %!demo %! S = [ 0.125 0.3 0.2 ]; %! V = [ 16 10 5 ]; %! N = 20; %! m = ones(1,3); %! Z = 4; %! [U R Q X] = qncsmva(N,S,V,m,Z); %! X_s = X(1)/V(1); # System throughput %! R_s = dot(R,V); # System response time %! printf("\t Util Qlen RespT Tput\n"); %! printf("\t-------- -------- -------- --------\n"); %! for k=1:length(S) %! printf("Dev%d\t%8.4f %8.4f %8.4f %8.4f\n", k, U(k), Q(k), R(k), X(k) ); %! endfor %! printf("\nSystem\t %8.4f %8.4f %8.4f\n\n", N-X_s*Z, R_s, X_s ); %!demo %! SA = [300 40]; %! p = .9; P = [ 0 1; 1-p p ]; %! VA = qncsvisits(P); %! SB = [300 30]; %! p = .75; P = [ 0 1; 1-p p ]; %! VB = qncsvisits(P); %! Z = 1800; %! NN = 1:100; %! XA = XB = XA_mva = XB_mva = zeros(size(NN)); %! for n=NN %! [nc XA(n)] = qncsbsb(n, SA, VA, 1, Z); %! [U R Q X] = qncsmva(n, SA, VA, 1, Z); %! XA_mva(n) = X(1)/VA(1); %! [nc XB(n)] = qncsbsb(n, SB, VB, 1, Z); %! [U R Q X] = qncsmva(n, SB, VB, 1, Z); %! XB_mva(n) = X(1)/VB(1); %! endfor %! plot(NN, XA, ":k", "linewidth", 1, %! NN, XA_mva, "-b", "linewidth", 1, %! NN, XB, ":k", "linewidth", 1, %! NN, XB_mva, "-r", "linewidth", 1); %! idx = 40; %! displ = 2e-4; %! text( NN(idx), XA(idx)-displ, "A) Large cache of slow disks"); %! text( NN(idx), XB(idx)+displ, "B) Small cache of fast disks"); %! ax = axis(); %! ax(3) = 0; %! ax(4) = 1.2*max([XA XB]); %! axis(ax); %! xlabel("Number of jobs"); %! ylabel("System throughput (jobs/s)"); queueing/inst/qsmminf.m0000664000175000017500000001143214620404470015071 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2018, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qsmminf (@var{lambda}, @var{mu}) ## @deftypefnx {Function File} {@var{pk} =} qsmminf (@var{lambda}, @var{mu}, @var{k}) ## ## Compute utilization, response time, average number of requests and throughput for an infinite-server queue. ## ## The @math{M/M/\infty} system has an infinite number of identical ## servers. Such a system is always stable (i.e., the mean queue ## length is always finite) for any arrival and service rates. ## ## @cindex @math{M/M/}inf system ## ## @tex ## The steady-state probability @math{\pi_k} that there are @math{k} ## requests in the system, @math{k @geq{} 0}, can be computed as: ## ## $$ ## \pi_k = {1 \over k!} \left( \lambda \over \mu \right)^k e^{-\lambda / \mu} ## $$ ## @end tex ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate (@code{@var{lambda}>0}). ## ## @item @var{mu} ## Service rate (@code{@var{mu}>0}). ## ## @item @var{k} ## Number of requests in the system (@code{@var{k} @geq{} 0}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U} ## Traffic intensity (defined as @math{\lambda/\mu}). Note that this is ## different from the utilization, which in the case of @math{M/M/\infty} ## centers is always zero. ## ## @cindex traffic intensity ## ## @item @var{R} ## Service center response time. ## ## @item @var{Q} ## Average number of requests in the system (which is equal to the ## traffic intensity @math{\lambda/\mu}). ## ## @item @var{X} ## Throughput (which is always equal to @code{@var{X} = @var{lambda}}). ## ## @item @var{p0} ## Steady-state probability that there are no requests in the system ## ## @item @var{pk} ## Steady-state probability that there are @var{k} requests in the ## system (including the one being served). ## ## @end table ## ## If this function is called with less than three arguments, ## @var{lambda} and @var{mu} can be vectors of the same size. In this ## case, the results will be vectors as well. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks ## and Markov Chains: Modeling and Performance Evaluation with Computer ## Science Applications}, Wiley, 1998, Section 6.4 ## @end itemize ## ## @seealso{qsmm1,qsmmm,qsmmmk} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U_or_pk R Q X p0] = qsmminf( lambda, mu, k ) if ( nargin < 2 || nargin > 3 ) print_usage(); endif ( isvector(lambda) && isvector(mu) ) || ... error( "lambda and mu must be vectors" ); [ err lambda mu ] = common_size( lambda, mu ); if ( err ) error( "Parameters are of incompatible size" ); endif lambda = lambda(:)'; mu = mu(:)'; ( all( lambda>0 ) && all( mu>0 ) ) || ... error( "lambda and mu must be >0" ); if (nargin < 3) U_or_pk = Q = lambda ./ mu; # Traffic intensity. p0 = exp(-lambda./mu); # probability that there are 0 requests in the system R = 1 ./ mu; X = lambda; else (length(lambda) == 1) || error("lambda must be a scalar if this function is called with three arguments"); isvector(k) || error("k must be a vector"); all(k>=0 )|| error("k must be >= 0"); ## expn does not support array arguments, hence we must use arrayfun() U_or_pk = arrayfun(@(x) expn(lambda/mu, x) * exp(-lambda/mu), k); endif endfunction %!test %! fail( "qsmminf( [1 2], [1 2 3] )", "incompatible size"); %! fail( "qsmminf( [-1 -1], [1 1] )", ">0" ); %!demo %! ## Given a M/M/inf and M/M/m queue, compute the steady-state probability pk %! ## of having k requests in the systen. %! lambda = 5; %! mu = 1.1; %! m = 5; %! k = 0:20; %! pk_inf = qsmminf(lambda, mu, k); %! pk_m = qsmmm(lambda, mu, 5, k); %! plot(k, pk_inf, "-o;M/M/\\infty;", "linewidth", 2, ... %! k, pk_m, "-x;M/M/5;", "linewidth", 2); %! xlabel("N. of requests (k)"); %! ylabel("P_k"); %! title(sprintf("M/M/\\infty and M/M/%d systems, \\lambda = %g, \\mu = %g", m, lambda, mu)); queueing/inst/qsammm.m0000664000175000017500000000651214620404470014715 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qsammm (@var{lambda}, @var{mu}) ## ## @cindex asymmetric @math{M/M/m} system ## ## Compute @emph{approximate} utilization, response time, average ## number of requests in service and throughput for an asymmetric ## @math{M/M/m} queue. In this type of system there are @math{m} different ## servers connected to a single queue. Each server has its own ## (possibly different) service rate. If there is more than one server ## available, requests are routed to a randomly-chosen one. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate (@code{@var{lambda}>0}) ## ## @item @var{mu} ## @code{@var{mu}(i)} is the service rate of server ## @math{i}, @math{1 @leq{} i @leq{} m}. ## The system must be ergodic (@code{@var{lambda} < sum(@var{mu})}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U} ## Approximate service center utilization, ## @math{U = \lambda / ( \sum_{i=1}^m \mu_i )}. ## ## @item @var{R} ## Approximate service center response time ## ## @item @var{Q} ## Approximate number of requests in the system ## ## @item @var{X} ## Approximate system throughput. If the system is ergodic, ## @code{@var{X} = @var{lambda}} ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks ## and Markov Chains: Modeling and Performance Evaluation with Computer ## Science Applications}, Wiley, 1998 ## @end itemize ## ## @seealso{qsmmm} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X p0 pm] = qsammm( lambda, mu ) if ( nargin != 2 ) print_usage(); endif isscalar(lambda) || ... error( "lambda must be scalar" ); isvector(mu) || ... error( "mu must be a vector" ); m = length(mu); # number of servers all( lambda < sum(mu) ) || ... error( "Processing capacity exceeded" ); X = lambda; U = rho = lambda / sum(mu); Q = p0 = 0; #{ k=[0:m-1]; p0 = 1 / ( ... sum( (m*rho).^k ./ factorial(k)) + ... (m*rho)^m / (factorial(m)*(1-rho)) ... ); pm = (m*rho)^m/(factorial(m)*(1-rho))*p0; #} p0 = 1 / ( ... sumexpn( m*rho, m-1 ) + ... expn(m*rho, m) / (1-rho) ... ); pm = expn(m*rho, m)*p0/(1-rho); Q = m*rho+rho / (1-rho) * pm; R = Q / X; endfunction %!test %! [U R Q X] = qsammm( 73,[10,15,20,20,25] ); %! assert( U, 0.81, 1e-2 ); %! assert( Q, 6.5278, 1e-4 ); queueing/inst/qnom.m0000664000175000017500000002621014620404470014371 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnom (@var{lambda}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnom (@var{lambda}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnom (@var{lambda}, @var{S}, @var{P}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnom (@var{lambda}, @var{S}, @var{P}, @var{m}) ## ## @cindex open network, multiple classes ## @cindex multiclass network, open ## ## Exact analysis of open, multiple-class BCMP networks. The network can ## be made of @emph{single-server} queueing centers (FCFS, LCFS-PR or ## PS) or delay centers (IS). This function assumes a network with ## @math{K} service centers and @math{C} customer classes. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda}(c) ## If this function is invoked as @code{qnom(lambda, S, V, @dots{})}, ## then @code{@var{lambda}(c)} is the external arrival rate of class ## @math{c} customers (@code{@var{lambda}(c) @geq{} 0}). If this ## function is invoked as @code{qnom(lambda, S, P, @dots{})}, then ## @code{@var{lambda}(c,k)} is the external arrival rate of class ## @math{c} customers at center @math{k} (@code{@var{lambda}(c,k) ## @geq{} 0}). ## ## @item @var{S}(c,k) ## mean service time of class @math{c} customers on the service center ## @math{k} (@code{@var{S}(c,k)>0}). For FCFS nodes, mean service ## times must be class-independent. ## ## @item @var{V}(c,k) ## visit ratio of class @math{c} customers to service center @math{k} ## (@code{@var{V}(c,k) @geq{} 0 }). @strong{If you pass this argument, ## class switching is not allowed} ## ## @item @var{P}(r,i,s,j) ## probability that a class @math{r} job completing service at center ## @math{i} is routed to center @math{j} as a class @math{s} job. ## @strong{If you pass argument @var{P}, class switching is allowed}; ## however, all servers must be fixed-rate or infinite-server nodes ## (@code{@var{m}(k) @leq{} 1} for all @math{k}). ## ## @item @var{m}(k) ## number of servers at center @math{k}. If @code{@var{m}(k) < 1}, ## enter @math{k} is a delay center (IS); otherwise it is a regular ## queueing center with @code{@var{m}(k)} servers. Default is ## @code{@var{m}(k) = 1} for all @math{k}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(c,k) ## If @math{k} is a queueing center, then @code{@var{U}(c,k)} is the ## class @math{c} utilization of center @math{k}. If @math{k} is an IS ## node, then @code{@var{U}(c,k)} is the class @math{c} @emph{traffic ## intensity} defined as @code{@var{X}(c,k)*@var{S}(c,k)}. ## ## @item @var{R}(c,k) ## class @math{c} response time at center @math{k}. The system ## response time for class @math{c} requests can be computed as ## @code{dot(@var{R}, @var{V}, 2)}. ## ## @item @var{Q}(c,k) ## average number of class @math{c} requests at center @math{k}. The ## average number of class @math{c} requests in the system @var{Qc} ## can be computed as @code{Qc = sum(@var{Q}, 2)} ## ## @item @var{X}(c,k) ## class @math{c} throughput at center @math{k}. ## ## @end table ## ## @strong{NOTES} ## ## If the function call specifies the visit ratios @var{V}, ## class switching is @strong{not} allowed. If the function call ## specifies the routing probability matrix @var{P}, then class ## switching @strong{is} allowed; however, all nodes are ## restricted to be fixed rate servers or delay centers: ## multiple-server and general load-dependent centers are not ## supported. Note that the meaning of parameter @var{lambda} is ## different from one case to the other (see below). ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. ## Sevcik, @cite{Quantitative System Performance: Computer System ## Analysis Using Queueing Network Models}, Prentice Hall, ## 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In ## particular, see section 7.4.1 ("Open Model Solution Techniques"). ## @end itemize ## ## @seealso{qnopen,qnos,qnomvisits} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qnom( varargin ) if ( nargin < 2 || nargin > 4 ) print_usage(); endif if ( nargin == 2 || ndims(varargin{3}) == 2 ) [err lambda S V m] = qnomchkparam( varargin{:} ); else lambda = varargin{1}; ( ndims(lambda) == 2 && all( lambda(:) >= 0 ) ) || ... error( "lambda must be >= 0" ); [C,K] = size(lambda); S = varargin{2}; ( ndims(S) == 2 && size(S) == [C,K] ) || ... error( "S size mismatch (should be [%d,%d])", C, K ); P = varargin{3}; ( ndims(P) == 4 && size(P) == [C,K,C,K] ) || ... error( "P size mismatch (should be %dx%dx%dx%d)",C,K,C,K ); V = qnomvisits(P,lambda); if ( nargin < 4 ) m = ones(1,K); else m = varargin{4}; isvector(m) || ... error( "m must be a vector" ); m = m(:)'; # make m a row vector length(m) == K || ... error( "m size mismatch (should be %d, is %d)", K, length(m) ); all(m<=1) || ... error( "IF you use parameter P, m must be <= 1"); endif lambda = sum(lambda,2); # lambda(c) is the overall class c arrival rate endif [C K] = size(S); U = R = Q = X = zeros(C,K); ## NOTE; Zahorjan et al. define the class c throughput at center k as ## X(c,k) = lambda(c) * V(c,k). However, this assumes a definition of ## V(c,k) that is different from what is returned by the qnomvisits() ## function. The queueing package defines V(c,k) as the class c visit ## _ratio_ at center k (see the documentation of the queueing package ## to see the formal definition of V(c,k) as the solution of a linear ## system of equations), while Zahorjan et al. define V(c,k) as the ## _number of visits_ at center k. If you want to try the examples ## on Zahorjan with this function, you need to scale V(c,k) ## as lambda / lambda(c) * V(c,k). X = sum(lambda)*V; # X(c,k) = lambda*V(c,k); ## If there are M/M/k servers with k>=1, compute the maximum ## processing capacity m(m<1) = -1; # avoid division by zero in next line rho = X .* S * diag( 1 ./ m ); # rho(c,k) = X(c,k) * S(x,k) / m(k) [Umax kmax] = max( sum(rho,1) ); (Umax < 1) || ... error( "Processing capacity exceeded at center %d", kmax ); ## Compute utilizations (for IS nodes compute also response time and ## queue lenghts) for k=1:K for c=1:C if ( m(k) > 1 ) # M/M/m-FCFS [U(c,k)] = qsmmm( X(c,k), 1/S(c,k), m(k) ); elseif ( m(k) == 1 ) # M/M/1 or -/G/1-PS [U(c,k)] = qsmm1( X(c,k), 1/S(c,k) ); else # -/G/inf [U(c,k) R(c,k) Q(c,k)] = qsmminf( X(c,k), 1/S(c,k) ); endif endfor endfor assert( sum(U,1) < 1 ); # sanity check ## Adjust response times and queue lengths for FCFS queues k_fcfs = find(m>=1); for c=1:C Q(c,k_fcfs) = U(c,k_fcfs) ./ ( 1 - sum(U(:,k_fcfs),1) ); R(c,k_fcfs) = Q(c,k_fcfs) ./ X(c,k_fcfs); # Use Little's law endfor endfunction %!test %! fail( "qnom([1 1], [.9; 1.0])", "exceeded at center 1"); %! fail( "qnom([1 1], [0.9 .9; 0.9 1.0])", "exceeded at center 2"); %! #qnom([1 1], [.9; 1.0],[],2); # should not fail, M/M/2-FCFS %! #qnom([1 1], [.9; 1.0],[],-1); # should not fail, -/G/1-PS %! fail( "qnom(1./[2 3], [1.9 1.9 0.9; 2.9 3.0 2.9])", "exceeded at center 2"); %! #qnom(1./[2 3], [1 1.9 0.9; 0.3 3.0 1.5],[],[1 2 1]); # should not fail %!test %! V = [1 1; 1 1]; %! S = [1 3; 2 4]; %! lambda = [3/19 2/19]; %! [U R Q X] = qnom(lambda, S, diag( lambda / sum(lambda) ) * V ); %! assert( U(1,1), 3/19, 1e-6 ); %! assert( U(2,1), 4/19, 1e-6 ); %! assert( R(1,1), 19/12, 1e-6 ); %! assert( R(1,2), 57/2, 1e-6 ); %! assert( Q(1,1), .25, 1e-6 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law %!test %! # example p. 138 Zahorjan et al. %! V = [ 10 9; 5 4]; %! S = [ 1/10 1/3; 2/5 1]; %! lambda = [3/19 2/19]; %! [U R Q X] = qnom(lambda, S, diag( lambda / sum(lambda) ) * V ); %! assert( X(1,1), 1.58, 1e-2 ); %! assert( U(1,1), .158, 1e-3 ); %! assert( R(1,1), .158, 1e-3 ); # modified from the original example, as the reference above considers R as the residence time, not the response time %! assert( Q(1,1), .25, 1e-2 ); %! assert( Q, R.*X, 1e-5 ); # Little's Law %!test %! # example 7.7 p. 304 Bolch et al. Please note that the book uses the %! # notation P(i,r,j,s) (i,j are service centers, r,s are job %! # classes) while the queueing package uses P(r,i,s,j) %! P = zeros(2,3,2,3); %! lambda = S = zeros(2,3); %! P(1,1,1,2) = 0.4; %! P(1,1,1,3) = 0.3; %! P(1,2,1,1) = 0.6; %! P(1,2,1,3) = 0.4; %! P(1,3,1,1) = 0.5; %! P(1,3,1,2) = 0.5; %! P(2,1,2,2) = 0.3; %! P(2,1,2,3) = 0.6; %! P(2,2,2,1) = 0.7; %! P(2,2,2,3) = 0.3; %! P(2,3,2,1) = 0.4; %! P(2,3,2,2) = 0.6; %! S(1,1) = 1/8; %! S(1,2) = 1/12; %! S(1,3) = 1/16; %! S(2,1) = 1/24; %! S(2,2) = 1/32; %! S(2,3) = 1/36; %! lambda(1,1) = lambda(2,1) = 1; %! V = qnomvisits(P,lambda); %! assert( V, [ 3.333 2.292 1.917; 10 8.049 8.415] ./ 2, 1e-3); %! [U R Q X] = qnom(sum(lambda,2), S, V); %! assert( sum(U,1), [0.833 0.442 0.354], 1e-3 ); %! # Note: the value of K_22 (corresponding to Q(2,2)) reported in the book %! # is 0.5. However, hand computation using the exact same formulas %! # from the book produces a different value, 0.451 %! assert( Q, [2.5 0.342 0.186; 2.5 0.451 0.362], 1e-3 ); ## Check that the results of qnom_nocs and qnom_cs are the same ## for multiclass networks WITHOUT class switching. %!test %! P = zeros(2,2,2,2); %! P(1,1,1,2) = 0.8; P(1,2,1,1) = 1; %! P(2,1,2,2) = 0.9; P(2,2,2,1) = 1; %! S = zeros(2,2); %! S(1,1) = 1.5; S(1,2) = 1.2; %! S(2,1) = 0.8; S(2,2) = 2.5; %! lambda = zeros(2,2); %! lambda(1,1) = 1/20; %! lambda(2,1) = 1/30; %! [U1 R1 Q1 X1] = qnom(lambda, S, P); # qnom_cs %! [U2 R2 Q2 X2] = qnom(sum(lambda,2), S, qnomvisits(P,lambda)); # qnom_nocs %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 ); %! assert( Q1, Q2, 1e-5 ); %! assert( X1, X2, 1e-5 ); %!demo %! P = zeros(2,2,2,2); %! lambda = zeros(2,2); %! S = zeros(2,2); %! P(1,1,2,1) = P(1,2,2,1) = 0.2; %! P(1,1,2,2) = P(2,2,2,2) = 0.8; %! S(1,1) = S(1,2) = 0.1; %! S(2,1) = S(2,2) = 0.05; %! rr = 1:100; %! Xk = zeros(2,length(rr)); %! for r=rr %! lambda(1,1) = lambda(1,2) = 1/r; %! [U R Q X] = qnom(lambda,S,P); %! Xk(:,r) = sum(X,1)'; %! endfor %! plot(rr,Xk(1,:),";Server 1;","linewidth",2, ... %! rr,Xk(2,:),";Server 2;","linewidth",2); %! legend("boxoff"); %! xlabel("Class 1 interarrival time"); %! ylabel("Throughput"); queueing/inst/qncsmvaap.m0000664000175000017500000001757714620404470015430 0ustar morenomoreno## Copyright (C) 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncsmvaap (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}, @var{iter_max}) ## ## @cindex Mean Value Analysys (MVA), approximate ## @cindex MVA, approximate ## @cindex approximate MVA ## @cindex closed network, single class ## @cindex closed network, approximate analysis ## ## Analyze closed, single class queueing networks using the Approximate ## Mean Value Analysis (MVA) algorithm. This function is based on ## approximating the number of customers seen at center @math{k} when a ## new request arrives as @math{Q_k(N) \times (N-1)/N}. This function ## only handles single-server and delay centers; if your network ## contains general load-dependent service centers, use the function ## @code{qncsmvald} instead. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## Population size (number of requests in the system, @code{@var{N} > 0}). ## ## @item @var{S}(k) ## mean service time on server @math{k} ## (@code{@var{S}(k)>0}). ## ## @item @var{V}(k) ## average number of visits to service center ## @math{k} (@code{@var{V}(k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k} ## (if @var{m} is a scalar, all centers have that number of servers). If ## @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); if ## @code{@var{m}(k) == 1}, center @math{k} is a regular queueing ## center (FCFS, LCFS-PR or PS) with one server (default). This function ## does not support multiple server nodes (@code{@var{m}(k) > 1}). ## ## @item @var{Z} ## External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. ## ## @item @var{tol} ## Stopping tolerance. The algorithm stops when the maximum relative ## difference between the new and old value of the queue lengths ## @var{Q} becomes less than the tolerance. Default is @math{10^{-5}}. ## ## @item @var{iter_max} ## Maximum number of iterations (@code{@var{iter_max}>0}. ## The function aborts if convergenge is not reached within the maximum ## number of iterations. Default is 100. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(k) ## If @math{k} is a FCFS, LCFS-PR or PS node (@code{@var{m}(k) == 1}), ## then @code{@var{U}(k)} is the utilization of center @math{k}. If ## @math{k} is an IS node (@code{@var{m}(k) < 1}), then ## @code{@var{U}(k)} is the @emph{traffic intensity} defined as ## @code{@var{X}(k)*@var{S}(k)}. ## ## @item @var{R}(k) ## response time at center @math{k}. ## The system response time @var{Rsys} ## can be computed as @code{@var{Rsys} = @var{N}/@var{Xsys} - Z} ## ## @item @var{Q}(k) ## average number of requests at center @math{k}. The number of ## requests in the system can be computed either as ## @code{sum(@var{Q})}, or using the formula ## @code{@var{N}-@var{Xsys}*@var{Z}}. ## ## @item @var{X}(k) ## center @math{k} throughput. The system throughput @var{Xsys} can be ## computed as @code{@var{Xsys} = @var{X}(1) / @var{V}(1)} ## ## @end table ## ## @strong{REFERENCES} ## ## This implementation is based on Edward D. Lazowska, John Zahorjan, ## G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System ## Performance: Computer System Analysis Using Queueing Network Models}, ## Prentice Hall, ## 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In ## particular, see section 6.4.2.2 ("Approximate Solution Techniques"). ## ## @seealso{qncsmva,qncsmvald} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qncsmvaap( N, S, V, m, Z, tol, iter_max ) if ( nargin < 3 || nargin > 7 ) print_usage(); endif isscalar(N) && N >= 0 || ... error( "N must be >= 0" ); isvector(S) || ... error( "S must be a vector" ); isvector(V) || ... error( "V must be a vector" ); S = S(:)'; # make S a row vector V = V(:)'; # make V a row vector K = length(S); # Number of servers if ( nargin < 4 ) m = ones(1,K); else isvector(m) || ... error( "m must be a vector" ); m = m(:)'; # make m a row vector endif [err S V m] = common_size(S, V, m); (err == 0) || ... error( "S, V and m are of incompatible size" ); all(S>=0) || ... error( "S must be a vector >= 0" ); all(V>=0) || ... error( "V must be a vector >= 0" ); all(m<=1) || ... error( "Vector m must be <= 1 (this function supports IS and single-server nodes only)" ); if ( nargin < 5 ) Z = 0; else (isscalar(Z) && Z >= 0) || ... error( "Z must be >= 0" ); endif if ( nargin < 6 ) tol = 1e-5; else ( isscalar(tol) && tol>0 ) || ... error("tol must be a positive scalar"); endif if ( nargin < 7 ) iter_max = 100; else ( isscalar(iter_max) && iter_max > 0 ) || ... error("iter_max must be a positive integer"); endif U = R = Q = X = zeros( 1, K ); ## Trivial case of empty population: just return all zeros if ( N == 0 ) return; endif Q = N/K * ones(1,K); # initialize queue lengths iter = 0; do iter++; Qold = Q; A = (N-1)/N * Q; R = S.*(1+A.*(m==1)); Rs = dot(V,R); Xs = N/(Z+Rs); Q = Xs*(V.*R); err = norm((Q-Qold)./Qold, "inf"); until (err < tol || iter>iter_max); if ( iter > iter_max ) warning( "qncsmvaap(): Convergence not reached after %d iterations", iter_max ); endif X = Xs * V; U = X .* S; endfunction %!test %! fail( "qncsmvaap()", "Invalid" ); %! fail( "qncsmvaap( 10, [1 2], [1 2 3] )", "S, V and m" ); %! fail( "qncsmvaap( 10, [-1 1], [1 1] )", ">= 0" ); %! fail( "qncsmvaap( 10, [1 2], [1 2], [1 2] )", "supports"); %! fail( "qncsmvaap( 10, [1 2], [1 2], [1 1], 0, -1)", "tol"); %!test %! # Example p. 117 Lazowska et al. %! S = [0.605 2.1 1.35]; %! V = [1 1 1]; %! N = 3; %! Z = 15; %! m = 1; %! [U R Q X] = qncsmvaap(N, S, V, m, Z); %! Rs = dot(V,R); %! Xs = N/(Z+Rs); %! assert( Q, [0.0973 0.4021 0.2359], 1e-3 ); %! assert( Xs, 0.1510, 1e-3 ); %! assert( Rs, 4.87, 1e-3 ); %!demo %! S = [ 0.125 0.3 0.2 ]; %! V = [ 16 10 5 ]; %! N = 30; %! m = ones(1,3); %! Z = 4; %! Xmva = Xapp = Rmva = Rapp = zeros(1,N); %! for n=1:N %! [U R Q X] = qncsmva(n,S,V,m,Z); %! Xmva(n) = X(1)/V(1); %! Rmva(n) = dot(R,V); %! [U R Q X] = qncsmvaap(n,S,V,m,Z); %! Xapp(n) = X(1)/V(1); %! Rapp(n) = dot(R,V); %! endfor %! subplot(2,1,1); %! plot(1:N, Xmva, ";Exact;", "linewidth", 2, 1:N, Xapp, "x;Approximate;", "markersize", 7); %! legend("location","southeast"); legend("boxoff"); %! ylabel("Throughput X(n)"); %! subplot(2,1,2); %! plot(1:N, Rmva, ";Exact;", "linewidth", 2, 1:N, Rapp, "x;Approximate;", "markersize", 7); %! legend("location","southeast"); legend("boxoff"); %! ylabel("Response Time R(n)"); %! xlabel("Number of Requests n"); queueing/inst/ctmcchkQ.m0000664000175000017500000000464714620404470015166 0ustar morenomoreno## Copyright (C) 2012 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{result} @var{err}] =} ctmcchkQ (@var{Q}) ## ## @cindex Markov chain, continuous time ## ## If @var{Q} is a valid infinitesimal generator matrix, return ## the size (number of rows or columns) of @var{Q}. If @var{Q} is not ## an infinitesimal generator matrix, set @var{result} to zero, and ## @var{err} to an appropriate error string. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [result err] = ctmcchkQ( Q ) persistent epsilon = 100*eps; if ( nargin != 1 ) print_usage(); endif result = 0; err = ""; if ( !issquare(Q) ) err = "P is not a square matrix"; return; endif if (any(Q(~logical(eye(size(Q))))<0) || ... # there is any negative non-diagonal element norm( sum(Q,2), "inf" ) > epsilon ) err = "Q is not an infinitesimal generator matrix"; return; endif result = rows(Q); endfunction %!test %! Q = [0]; %! [result err] = ctmcchkQ(Q); %! assert( result, 1 ); %! assert( err, "" ); %!test %! N = 10; %! Q = ctmcbd(rand(1,N-1),rand(1,N-1)); %! [result err] = ctmcchkQ(Q); %! assert( result, N ); %! assert( err, "" ); %!test %! Q = [1 2 3; 4 5 6]; %! [result err] = ctmcchkQ(Q); %! assert( result, 0 ); %! assert( index(err, "square") > 0 ); %!test %! N = 10; %! Q = ctmcbd(rand(1,N-1),rand(1,N-1)); %! Q(2,1) = -1; %! [result err] = ctmcchkQ(Q); %! assert( result, 0 ); %! assert( index(err, "infinitesimal") > 0 ); %!test %! N = 10; %! Q = ctmcbd(linspace(1,N-1,N-1),linspace(1,N-1,N-1)); %! Q(1,1) += 7; %! [result err] = ctmcchkQ(Q); %! assert( result, 0 ); %! assert( index(err, "infinitesimal") > 0 ); queueing/inst/dtmcisir.m0000664000175000017500000000474114620404470015242 0ustar morenomoreno## Copyright (C) 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{r} @var{s}] =} dtmcisir (@var{P}) ## ## @cindex Markov chain, discrete time ## @cindex discrete time Markov chain ## @cindex DTMC ## @cindex irreducible Markov chain ## ## Check if @var{P} is irreducible, and identify Strongly Connected ## Components (SCC) in the transition graph of the DTMC with transition ## matrix @var{P}. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(i,j) ## transition probability from state @math{i} to state @math{j}. ## @var{P} must be an @math{N \times N} stochastic matrix. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{r} ## 1 if @var{P} is irreducible (i.e., the state transition graph is ## strongly connected), 0 otherwise (scalar) ## ## @item @var{s}(i) ## strongly connected component (SCC) that state @math{i} belongs to ## (vector of length @math{N}). SCCs are numbered @math{1, 2, @dots{}}. ## The number of SCCs is @code{max(s)}. If the graph is ## strongly connected, then there is a single SCC and the predicate ## @code{all(s == 1)} evaluates to true ## ## @end table ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [r s] = dtmcisir( P ) if ( nargin != 1 ) print_usage(); endif [N err] = dtmcchkP(P); if ( N == 0 ) error(err); endif s = scc(P); r = (max(s) == 1); endfunction %!test %! P = [0 .5 0; 0 0 0]; %! fail( "dtmcisir(P)" ); %!test %! P = [0 1 0; 0 .5 .5; 0 1 0]; %! [r s] = dtmcisir(P); %! assert( r == 0 ); %! assert( max(s), 2 ); %! assert( min(s), 1 ); %!test %! P = [.5 .5 0; .2 .3 .5; 0 .2 .8]; %! [r s] = dtmcisir(P); %! assert( r == 1 ); %! assert( max(s), 1 ); %! assert( min(s), 1 ); queueing/inst/qncmbsb.m0000664000175000017500000001335014620404470015045 0ustar morenomoreno## Copyright (C) 2012, 2016, 2020, 2022 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmbsb (@var{N}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncmbsb (@var{N}, @var{S}, @var{V}) ## ## @cindex bounds, balanced system ## @cindex balanced system bounds ## @cindex multiclass network, closed ## @cindex closed multiclass network ## ## Compute Balanced System Bounds for closed, multiclass networks ## with @math{K} service centers and @math{C} customer classes. ## Only single-server nodes are supported. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N}(c) ## number of class @math{c} requests in the system (vector of length ## @math{C}). ## ## @item @var{D}(c, k) ## class @math{c} service demand at center @math{k} (@math{C \times K} ## matrix, @code{@var{D}(c,k) @geq{} 0}). ## ## @item @var{S}(c, k) ## mean service time of class @math{c} ## requests at center @math{k} (@math{C \times K} matrix, @code{@var{S}(c,k) @geq{} 0}). ## ## @item @var{V}(c,k) ## average number of visits of class @math{c} ## requests to center @math{k} (@math{C \times K} matrix, @code{@var{V}(c,k) @geq{} 0}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl}(c) ## @itemx @var{Xu}(c) ## Lower and upper class @math{c} throughput bounds (vector of length @math{C}). ## ## @item @var{Rl}(c) ## @itemx @var{Ru}(c) ## Lower and upper class @math{c} response time bounds (vector of length @math{C}). ## ## @end table ## ## @seealso{qncsbsb} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [Xl Xu Rl Ru] = qncmbsb( varargin ) if ( nargin<2 || nargin>5 ) print_usage(); endif [err N S V m Z] = qncmchkparam( varargin{:} ); isempty(err) || error(err); all(m<=1) || ... error("Multiple-server nodes are not supported"); all(Z == 0 ) || ... error("This function only supports Z=0"); if ( sum(N) == 0 ) # handle trivial case of empty network Xl = Xu = Rl = Ru = zeros(size(S)); else D = S .* V; K = columns(S); ## Equations from T. Kerola, The Composite Bound Method (CBM) for ## Computing Throughput Bounds in Multiple Class Environments}, ## Technical Report CSD-TR-475, Department of Computer Sciences, ## Purdue University, mar 13 1984 (Revisted aug 27, 1984), available ## at http://docs.lib.purdue.edu/cstech/395/ Dc = sum(D,2)'; D_max = max(D,[],2)'; D_min = min(D,[],2)'; Xl = N ./ (Dc + (sum(N)-1) .* D_max); Xu = min( 1./D_max, N ./ ((K+sum(N)-1) .* D_min)); Rl = N ./ Xu; Ru = N ./ Xl; endif endfunction %!test %! fail("qncmbsb([],[])", "nonempty"); %! fail("qncmbsb([1 0], [1 2 3])", "2 rows"); %! fail("qncmbsb([1 0], [1 2 3; 4 5 -1])", "nonnegative"); %! fail("qncmbsb([1 2], [1 2 3; 4 5 6], [1 2 3])", "2 x 3"); %! fail("qncmbsb([1 2], [1 2 3; 4 5 6], [1 2 3; 4 5 -1])", "nonnegative"); %! fail("qncmbsb([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1])", "3 elements"); %! fail("qncmbsb([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1 2])", "not supported"); %! fail("qncmbsb([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1 -1],[1 2 3])", "2 elements"); %! fail("qncmbsb([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1 -1],[1 -2])", "nonnegative"); %! fail("qncmbsb([1 2], [1 2 3; 1 2 3], [1 2 3; 1 2 3], [1 1 -1],[1 0])", "only supports"); %!test %! [Xl Xu Rl Ru] = qncmbsb([0 0], [1 2 3; 1 2 3]); %! assert( all(Xl(:) == 0) ); %! assert( all(Xu(:) == 0) ); %! assert( all(Rl(:) == 0) ); %! assert( all(Ru(:) == 0) ); %!test %! S = [10 7 5 4; ... %! 5 2 4 6]; %! NN=20; %! Xl = Xu = Rl = Ru = Xmva = Rmva = zeros(NN,2); %! for n=1:NN %! N=[n,10]; %! [a b c d] = qncmbsb(N,S); %! Xl(n,:) = a; Xu(n,:) = b; Rl(n,:) = c; Ru(n,:) = d; %! [U R Q X] = qncmmva(N,S,ones(size(S))); %! Xmva(n,:) = X(:,1)'; Rmva(n,:) = sum(R,2)'; %! endfor %! assert( all(Xl <= Xmva) ); %! assert( all(Xu >= Xmva) ); %! assert( all(Rl <= Rmva) ); %! assert( all(Xu >= Xmva) ); %!demo %! S = [10 7 5 4; ... %! 5 2 4 6]; %! NN=20; %! Xl = Xu = Rl = Ru = Xmva = Rmva = zeros(NN,2); %! for n=1:NN %! N=[n,10]; %! [a b c d] = qncmbsb(N,S); %! Xl(n,:) = a; Xu(n,:) = b; Rl(n,:) = c; Ru(n,:) = d; %! [U R Q X] = qncmmva(N,S,ones(size(S))); %! Xmva(n,:) = X(:,1)'; Rmva(n,:) = sum(R,2)'; %! endfor %! subplot(2,2,1); %! plot(1:NN,Xl(:,1), 1:NN,Xu(:,1), 1:NN,Xmva(:,1),";MVA;", "linewidth", 2); %! ylim([0, 0.2]); %! title("Class 1 throughput"); legend("boxoff"); %! subplot(2,2,2); %! plot(1:NN,Xl(:,2), 1:NN,Xu(:,2), 1:NN,Xmva(:,2),";MVA;", "linewidth", 2); %! ylim([0, 0.2]); %! title("Class 2 throughput"); legend("boxoff"); %! subplot(2,2,3); %! plot(1:NN,Rl(:,1), 1:NN,Ru(:,1), 1:NN,Rmva(:,1),";MVA;", "linewidth", 2); %! ylim([0, 700]); %! title("Class 1 response time"); legend("location", "northwest"); legend("boxoff"); %! subplot(2,2,4); %! plot(1:NN,Rl(:,2), 1:NN,Ru(:,2), 1:NN,Rmva(:,2),";MVA;", "linewidth", 2); %! ylim([0, 700]); %! title("Class 2 response time"); legend("location", "northwest"); legend("boxoff"); queueing/inst/qnos.m0000664000175000017500000001446114620404470014404 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnos (@var{lambda}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnos (@var{lambda}, @var{S}, @var{V}, @var{m}) ## ## @cindex open network, single class ## @cindex BCMP network ## ## Analyze open, single class BCMP queueing networks with @math{K} service centers. ## ## This function works for a subset of BCMP single-class open networks ## satisfying the following properties: ## ## @itemize ## ## @item The allowed service disciplines at network nodes are: FCFS, ## PS, LCFS-PR, IS (infinite server); ## ## @item Service times are exponentially distributed and ## load-independent; ## ## @item Center @math{k} can consist of @code{@var{m}(k) @geq{} 1} ## identical servers. ## ## @item Routing is load-independent ## ## @end itemize ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Overall external arrival rate (@code{@var{lambda}>0}). ## ## @item @var{S}(k) ## average service time at center @math{k} (@code{@var{S}(k)>0}). ## ## @item @var{V}(k) ## average number of visits to center @math{k} (@code{@var{V}(k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{i}. If @code{@var{m}(k) < 1}, ## enter @math{k} is a delay center (IS); otherwise it is a regular ## queueing center with @code{@var{m}(k)} servers. Default is ## @code{@var{m}(k) = 1} for all @math{k}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U}(k) ## If @math{k} is a queueing center, ## @code{@var{U}(k)} is the utilization of center @math{k}. ## If @math{k} is an IS node, then @code{@var{U}(k)} is the ## @emph{traffic intensity} defined as @code{@var{X}(k)*@var{S}(k)}. ## ## @item @var{R}(k) ## center @math{k} average response time. ## ## @item @var{Q}(k) ## average number of requests at center @math{k}. ## ## @item @var{X}(k) ## center @math{k} throughput. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks ## and Markov Chains: Modeling and Performance Evaluation with Computer ## Science Applications}, Wiley, 1998 ## @end itemize ## ## @seealso{qnopen,qnclosed,qnosvisits} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U R Q X] = qnos( varargin ) if ( nargin < 3 || nargin > 4 ) print_usage(); endif [err lambda S V m] = qnoschkparam( varargin {:} ); isempty(err) || error(err); all(S>0) || ... error( "S must be positive" ); ## If there are M/M/k servers with k>=1, compute the maximum ## processing capacity m(m<1) = -1; # avoids division by zero in next line [Umax kmax] = max( lambda * S .* V ./ m ); (Umax < 1) || ... error( "Processing capacity exceeded at center %d", kmax ); l = lambda*V; # arrival rates i = find( m == 1 ); # single station queueing centers if numel(i) [U(i) R(i) Q(i) X(i)] = qsmm1( l(i), 1./S(i) ); endif i = find( m<1 ); # delay centers if numel(i) [U(i) R(i) Q(i) X(i)] = qsmminf( l(i), 1./S(i) ); endif i = find( m>1 ); # multiple stations queueing centers if numel(i) [U(i) R(i) Q(i) X(i)] = qsmmm( l(i), 1./S(i), m(i) ); endif endfunction %!test %! lambda = 0; %! S = [1 1 1]; %! V = [1 1 1]; %! fail( "qnos(lambda,S,V)","lambda must be"); %! lambda = 1; %! S = [1 0 1]; %! fail( "qnos(lambda,S,V)","S must be"); %! S = [1 1 1]; %! m = [1 1]; %! fail( "qnos(lambda,S,V,m)","incompatible size"); %! V = [1 1 1 1]; %! fail( "qnos(lambda,S,V)","incompatible size"); %! fail( "qnos(1.0, [0.9 1.2], [1 1])", "exceeded at center 2"); %! fail( "qnos(1.0, [0.9 2.0], [1 1], [1 2])", "exceeded at center 2"); %! qnos(1.0, [0.9 1.9], [1 1], [1 2]); # should not fail %! qnos(1.0, [0.9 1.9], [1 1], [1 0]); # should not fail %! qnos(1.0, [1.9 1.9], [1 1], [0 0]); # should not fail %! qnos(1.0, [1.9 1.9], [1 1], [2 2]); # should not fail %!test %! # Example 34.1 p. 572 Bolch et al. %! lambda = 3; %! V = [16 7 8]; %! S = [0.01 0.02 0.03]; %! [U R Q X] = qnos( lambda, S, V ); %! assert( R, [0.0192 0.0345 0.107], 1e-2 ); %! assert( U, [0.48 0.42 0.72], 1e-2 ); %! assert( Q, R.*X, 1e-5 ); # check Little's Law %!test %! # Example p. 113, Lazowska et al. %! V = [121 70 50]; %! S = [0.005 0.03 0.027]; %! lambda=0.3; %! [U R Q X] = qnos( lambda, S, V ); %! assert( U(1), 0.182, 1e-3 ); %! assert( X(1), 36.3, 1e-2 ); %! assert( Q(1), 0.222, 1e-3 ); %! assert( Q, R.*X, 1e-5 ); # check Little's Law %!test %! lambda=[1]; %! P=[0]; %! V=qnosvisits(P,lambda); %! S=[0.25]; %! [U1 R1 Q1 X1]=qnos(sum(lambda),S,V); %! [U2 R2 Q2 X2]=qsmm1(lambda(1),1/S(1)); %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 ); %! assert( Q1, Q2, 1e-5 ); %! assert( X1, X2, 1e-5 ); ## Check if processing capacity is properly accounted for %!test %! lambda = 1.1; %! V = 1; %! m = [2]; %! S = [1]; %! [U1 R1 Q1 X1] = qnos(lambda,S,V,m); %! m = [-1]; %! lambda = 90.0; %! [U1 R1 Q1 X1] = qnos(lambda,S,V,m); %!demo %! lambda = 3; %! V = [16 7 8]; %! S = [0.01 0.02 0.03]; %! [U R Q X] = qnos( lambda, S, V ); %! R_s = dot(R,V) # System response time %! N = sum(Q) # Average number in system %!test %! # Example 7.4 p. 287 Bolch et al. %! S = [ 0.04 0.03 0.06 0.05 ]; %! P = [ 0 0.5 0.5 0; 1 0 0 0; 0.6 0 0 0; 1 0 0 0 ]; %! lambda = [0 0 0 4]; %! V=qnosvisits(P,lambda); %! k = [ 3 2 4 1 ]; %! [U R Q X] = qnos( sum(lambda), S, V ); %! assert( X, [20 10 10 4], 1e-4 ); %! assert( U, [0.8 0.3 0.6 0.2], 1e-2 ); %! assert( R, [0.2 0.043 0.15 0.0625], 1e-3 ); %! assert( Q, [4, 0.429 1.5 0.25], 1e-3 ); queueing/inst/qncsbsb.m0000664000175000017500000001057514620404470015061 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsbsb (@var{N}, @var{D}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsbsb (@var{N}, @var{S}, @var{V}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsbsb (@var{N}, @var{S}, @var{V}, @var{m}) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncsbsb (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) ## ## @cindex bounds, balanced system ## @cindex closed network, single class ## @cindex balanced system bounds ## ## Compute Balanced System Bounds on system throughput and response time for closed, single-class networks with @math{K} service centers. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{N} ## number of requests in the system (scalar, @code{@var{N} @geq{} 0}). ## ## @item @var{D}(k) ## service demand at center @math{k} (@code{@var{D}(k) @geq{} 0}). ## ## @item @var{S}(k) ## mean service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). ## ## @item @var{V}(k) ## average number of visits to center @math{k} (@code{@var{V}(k) ## @geq{} 0}). Default is 1. ## ## @item @var{m}(k) ## number of servers at center @math{k}. This function supports ## @code{@var{m}(k) = 1} only (single-eserver FCFS nodes); this ## parameter is only for compatibility with @code{qncsaba}. Default is ## 1. ## ## @item @var{Z} ## External delay (@code{@var{Z} @geq{} 0}). Default is 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl} ## @itemx @var{Xu} ## Lower and upper bound on the system throughput. ## ## @item @var{Rl} ## @itemx @var{Ru} ## Lower and upper bound on the system response time. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth ## C. Sevcik, @cite{Quantitative System Performance: Computer System ## Analysis Using Queueing Network Models}, Prentice Hall, ## 1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In ## particular, see section 5.4 ("Balanced Systems Bounds"). ## @end itemize ## ## @seealso{qncmbsb} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [Xl Xu Rl Ru] = qncsbsb( varargin ) if (nargin<2 || nargin>5) print_usage(); endif [err N S V m Z] = qncschkparam( varargin{:} ); isempty(err) || error(err); all(m==1) || ... error( "this function supports M/M/1 servers only" ); D = S .* V; D_max = max(D); D_tot = sum(D); D_ave = mean(D); Xl = N/(D_tot+Z+( (N-1)*D_max )/( 1+Z/(N*D_tot) ) ); Xu = min( 1/D_max, N/( D_tot+Z+( (N-1)*D_ave )/(1+Z/D_tot) ) ); Rl = max( N*D_max-Z, D_tot+( (N-1)*D_ave )/( 1+Z/D_tot) ); Ru = D_tot + ( (N-1)*D_max )/( 1+Z/(N*D_tot) ); endfunction %!test %! fail("qncsbsb(-1,0)", "N must be"); %! fail("qncsbsb(1,[])", "nonempty"); %! fail("qncsbsb(1,[-1 2])", "nonnegative"); %! fail("qncsbsb(1,[1 2],[1 2 3])", "incompatible size"); %! fail("qncsbsb(1,[1 2 3],[1 2 3],[1 2])", "incompatible size"); %! fail("qncsbsb(1,[1 2 3],[1 2 3],[1 2 1])", "M/M/1 servers"); %! fail("qncsbsb(1,[1 2 3],[1 2 3],[1 1 1],-1)", "nonnegative"); %! fail("qncsbsb(1,[1 2 3],[1 2 3],[1 1 1],[0 0])", "scalar"); %!test %! S = [1 0.8 1.2 0.5]; %! V = [1 2 2 1]; %! D = S .* V; %! N = 50; %! tol = 1e-7; # compensate for numerical inaccuracies %! for n=1:N %! [U R Q X] = qncsmva(n, S, V); %! Xs = X(1)/V(1); %! Rs = dot(R,V); %! [Xl Xu Rl Ru] = qncsbsb( n, D ); %! assert( Xl <= Xs+tol ); %! assert( Xu >= Xs-tol ); %! assert( Rl <= Rs+tol ); %! assert( Ru >= Rs-tol ); %! endfor queueing/inst/qncspb.m0000664000175000017500000001247414620404470014714 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncspb (@var{N}, @var{D} ) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncspb (@var{N}, @var{S}, @var{V} ) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncspb (@var{N}, @var{S}, @var{V}, @var{m} ) ## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qncspb (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z} ) ## ## @cindex bounds, PB ## @cindex PB bounds ## @cindex closed network, single class ## ## Compute PB Bounds (C. H. Hsieh and S. Lam, 1987) for single-class, ## closed networks with @math{K} service centers. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{} ## number of requests in the system (scalar, @code{@var{N} > 0}). ## ## @item @var{D}(k) ## service demand of service center @math{k} (@code{@var{D}(k) @geq{} 0}). ## ## @item @var{S}(k) ## mean service time at center @math{k} (@code{@var{S}(k) @geq{} 0}). ## ## @item @var{V}(k) ## visit ratio to center @math{k} (@code{@var{V}(k) @geq{} 0}). ## ## @item @var{m}(k) ## number of servers at center @math{k}. This function only supports ## @math{M/M/1} queues, therefore @var{m} must be ## @code{ones(size(S))}. ## ## @item @var{Z} ## external delay (think time, @code{@var{Z} @geq{} 0}). Default 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{Xl} ## @itemx @var{Xu} ## Lower and upper bounds on the system throughput. ## ## @item @var{Rl} ## @itemx @var{Ru} ## Lower and upper bounds on the system response time. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item ## C. H. Hsieh and S. Lam, @cite{Two classes of performance bounds for ## closed queueing networks}, Performance Evaluation, Vol. 7 Issue 1, ## pp. 3--30, February 1987, DOI ## @uref{http://dx.doi.org/10.1016/0166-5316(87)90054-X, ## 10.1016/0166-5316(87)90054-X}. Also available as ## @uref{ftp://ftp.cs.utexas.edu/pub/techreports/tr85-09.pdf, Technical ## Report TR-85-09}, Department of Computer Science, University of Texas ## at Austin, June 1985 ## @end itemize ## ## This function implements the non-iterative variant described in G. ## Casale, R. R. Muntz, G. Serazzi, @cite{Geometric Bounds: a ## Non-Iterative Analysis Technique for Closed Queueing Networks}, IEEE ## Transactions on Computers, 57(6):780-794, June 2008. ## ## @seealso{qncsaba, qbcsbsb, qncsgb} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [X_lower X_upper R_lower R_upper] = qncspb( varargin ) if ( nargin < 2 || nargin > 5 ) print_usage(); endif [err N S V m Z] = qncschkparam( varargin{:} ); isempty(err) || error(err); ( N>0 ) || ... error("N must be positive"); all(m==1) || ... error("qncspb only supports single server nodes"); D = S .* V; D_tot = sum(D); X_max = 1/max(D); X_min = 0; X_lower = N/( Z + D_tot + ... ( sum( D .^ N * (N-1-Z*X_min) ) / sum( D .^ (N-1) ) ) ); X_upper = N/( Z + D_tot + ... ( sum( D .^ 2 * (N-1-Z*X_max) ) / sum( D ) ) ); X_upper = min( X_upper, X_max ); # cap X upper bound to 1/max(D) R_lower = N/X_upper-Z; R_upper = N/X_lower-Z; endfunction %!test %! fail( "qncspb( 1, [] )", "vector" ); %! fail( "qncspb( 1, [0 -1])", "nonnegative" ); %! fail( "qncspb( 0, [1 2] )", "positive" ); %! fail( "qncspb( -1, [1 2])", "nonnegative" ); %! fail( "qncspb( 1, [1 2], [1,1], [2, 2])", "single server" ); %! fail( "qncspb( 1, [1 2], [1,1], [1, 1], -1)", "nonnegative" ); %!# shared test function %!function test_pb( D, expected, Z=0 ) %! for i=1:rows(expected) %! N = expected(i,1); %! [X_lower X_upper] = qncspb(N,D,ones(size(D)),ones(size(D)),Z); %! X_exp_lower = expected(i,2); %! X_exp_upper = expected(i,3); %! assert( [N X_lower X_upper], [N X_exp_lower X_exp_upper], 1e-4 ) %! endfor %!test %! # table IV %! D = [ 0.1 0.1 0.09 0.08 ]; %! # N X_lower X_upper %! expected = [ 2 4.3174 4.3174; ... %! 5 6.6600 6.7297; ... %! 10 8.0219 8.2700; ... %! 20 8.8672 9.3387; ... %! 80 9.6736 10.000 ]; %! test_pb(D, expected); %!test %! S = [1 0.8 1.2 0.5]; %! V = [1 2 2 1]; %! D = S .* V; %! N = 50; %! tol = 1e-7; # compensate for numerical inaccuracies %! for n=1:N %! [U R Q X] = qncsmva(n, S, V); %! Xs = X(1)/V(1); %! Rs = dot(R,V); %! [Xl Xu Rl Ru] = qncspb( n, D ); %! assert( Xl <= Xs+tol ); %! assert( Xu >= Xs-tol ); %! assert( Rl <= Rs+tol ); %! assert( Ru >= Rs-tol ); %! endfor queueing/inst/ctmcisir.m0000664000175000017500000000471414620404470015241 0ustar morenomoreno## Copyright (C) 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{r} @var{s}] =} ctmcisir (@var{P}) ## ## @cindex Markov chain, continuous time ## @cindex continuous time Markov chain ## @cindex CTMC ## @cindex irreducible Markov chain ## ## Check if @var{Q} is irreducible, and identify Strongly Connected ## Components (SCC) in the transition graph of the DTMC with infinitesimal ## generator matrix @var{Q}. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{Q}(i,j) ## Infinitesimal generator matrix. @var{Q} is a @math{N \times N} square ## matrix where @code{@var{Q}(i,j)} is the transition rate from state ## @math{i} to state @math{j}, for @math{1 @leq{} i, j @leq{} N}, ## @math{i \neq j}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{r} ## 1 if @var{Q} is irreducible, 0 otherwise. ## ## @item @var{s}(i) ## strongly connected component (SCC) that state @math{i} belongs to. ## SCCs are numbered @math{1, 2, @dots{}}. If the graph is strongly ## connected, then there is a single SCC and the predicate @code{all(s == 1)} ## evaluates to true. ## ## @end table ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [r s] = ctmcisir( Q ) if ( nargin != 1 ) print_usage(); endif [N err] = ctmcchkQ(Q); ( N > 0 ) || ... error(err); s = scc(Q); r = (max(s) == 1); endfunction %!test %! Q = [-.5 .5 0; 1 0 0]; %! fail( "ctmcisir(Q)" ); %!test %! Q = [-1 1 0; .5 -.5 0; 0 0 0]; %! [r s] = ctmcisir(Q); %! assert( r == 0 ); %! assert( max(s), 2 ); %! assert( min(s), 1 ); %!test %! Q = [-.5 .5 0; .2 -.7 .5; .2 0 -.2]; %! [r s] = ctmcisir(Q); %! assert( r == 1 ); %! assert( max(s), 1 ); %! assert( min(s), 1 ); queueing/inst/ctmcexps.m0000664000175000017500000001264114620404470015250 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{L} =} ctmcexps (@var{Q}, @var{t}, @var{p} ) ## @deftypefnx {Function File} {@var{L} =} ctmcexps (@var{Q}, @var{p}) ## ## @cindex Markov chain, continuous time ## @cindex continuous time Markov chain ## @cindex expected sojourn time, CTMC ## @cindex CTMC ## ## With three arguments, compute the expected times @code{@var{L}(i)} ## spent in each state @math{i} during the time interval @math{[0,t]}, ## assuming that the initial occupancy vector is @var{p}. With two ## arguments, compute the expected time @code{@var{L}(i)} spent in each ## transient state @math{i} until absorption. ## ## @strong{Note:} In its current implementation, this function ## requires that an absorbing state is reachable from any ## non-absorbing state of @math{Q}. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{Q}(i,j) ## @math{N \times N} infinitesimal generator matrix. @code{@var{Q}(i,j)} ## is the transition rate from state @math{i} to state @math{j}, ## @math{1 @leq{} i, j @leq{} N}, @math{i \neq j}. ## The matrix @var{Q} must also satisfy the ## condition @math{\sum_{j=1}^N Q_{i,j} = 0} for every @math{i=1, @dots{}, N}. ## ## @item @var{t} ## If given, compute the expected sojourn times in @math{[0,t]} ## ## @item @var{p}(i) ## Initial occupancy probability vector; @code{@var{p}(i)} is the ## probability the system is in state @math{i} at time 0, @math{i = 1, ## @dots{}, N} ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{L}(i) ## If this function is called with three arguments, @code{@var{L}(i)} is ## the expected time spent in state @math{i} during the interval ## @math{[0,t]}. If this function is called with two arguments ## @code{@var{L}(i)} is the expected time spent in transient state ## @math{i} until absorption; if state @math{i} is absorbing, ## @code{@var{L}(i)} is zero. ## ## @end table ## ## @seealso{dtmcexps} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function L = ctmcexps( Q, varargin ) persistent epsilon = 10*eps; if ( nargin < 2 || nargin > 3 ) print_usage(); endif [N err] = ctmcchkQ(Q); (N>0) || ... error(err); if ( nargin == 2 ) p = varargin{1}; else t = varargin{1}; p = varargin{2}; endif ( isvector(p) && length(p) == size(Q,1) && all(p>=0) && abs(sum(p)-1.0)= 0 ) || ... error( "t must be >= 0" ); ## F(x) are the transient state occupancy probabilities at time x ## F(x) = p*expm(Q*x) (see function ctmc()). F = @(x) (p*expm(Q*x)); L = quadv(F,0,t); else ( isvector(t) && abs(t(1)) < epsilon ) || ... error( "t must be a vector, and t(1) must be 0.0" ); t = t(:)'; # make t a row vector ff = @(x,t) (x(:)'*Q+p); fj = @(x,t) (Q); L = lsode( {ff, fj}, zeros(size(p)), t ); endif else # absorbing case ## Identify absorbing states. If there are no absorbing states, ## raise an error. N = rows(Q); tr = find( any( abs(Q) > epsilon, 2 ) ); # non-absorbing states if ( length( tr ) == N ) error( "There are no absorbing states" ); endif QN = Q(tr,tr); pN = p(tr); LN = -pN*inv(QN); L = zeros(1,N); L(tr) = LN; endif endfunction %!test %! Q = [-1 1; 1 -1]; %! L = ctmcexps(Q,10,[1 0]); %! L = ctmcexps(Q,linspace(0,10,100),[1 0]); %!test %! Q = ctmcbd( [1 2 3], [3 2 1] ); %! p0 = [1 0 0 0]; %! t = linspace(0,10,10); %! L1 = L2 = zeros(length(t),4); %! # compute L using the differential equation formulation %! ff = @(x,t) (x(:)'*Q+p0); %! fj = @(x,t) (Q); %! L1 = lsode( {ff, fj}, zeros(size(p0)), t ); %! # compute L using ctmcexps (integral formulation) %! for i=1:length(t) %! L2(i,:) = ctmcexps(Q,t(i),p0); %! endfor %! assert( L1, L2, 1e-5); %!demo %! lambda = 0.5; %! N = 4; %! b = lambda*[1:N-1]; %! d = zeros(size(b)); %! Q = ctmcbd(b,d); %! t = linspace(0,10,100); %! p0 = zeros(1,N); p0(1)=1; %! L = zeros(length(t),N); %! for i=1:length(t) %! L(i,:) = ctmcexps(Q,t(i),p0); %! endfor %! plot( t, L(:,1), ";State 1;", "linewidth", 2, ... %! t, L(:,2), ";State 2;", "linewidth", 2, ... %! t, L(:,3), ";State 3;", "linewidth", 2, ... %! t, L(:,4), ";State 4;", "linewidth", 2 ); %! legend("location","northwest"); legend("boxoff"); %! xlabel("Time"); %! ylabel("Expected sojourn time"); %!demo %! lambda = 0.5; %! N = 4; %! b = lambda*[1:N-1]; %! d = zeros(size(b)); %! Q = ctmcbd(b,d); %! p0 = zeros(1,N); p0(1)=1; %! L = ctmcexps(Q,p0); %! disp(L); queueing/inst/ctmc.m0000664000175000017500000002321614620404470014350 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2016, 2018, 2020, 2024 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{p} =} ctmc (@var{Q}) ## @deftypefnx {Function File} {@var{p} =} ctmc (@var{Q}, @var{t}, @var{p0}) ## ## @cindex Markov chain, continuous time ## @cindex continuous time Markov chain ## @cindex Markov chain, state occupancy probabilities ## @cindex stationary probabilities ## @cindex CTMC ## ## Compute stationary or transient state occupancy probabilities for a continuous-time Markov chain. ## ## With a single argument, compute the stationary state occupancy ## probabilities @math{@var{p}(1), @dots{}, @var{p}(N)} for a ## continuous-time Markov chain with finite state space @math{@{1, @dots{}, ## N@}} and @math{N \times N} infinitesimal generator matrix @var{Q}. ## With three arguments, compute the state occupancy probabilities ## @math{@var{p}(1), @dots{}, @var{p}(N)} that the system is in state @math{i} ## at time @var{t}, given initial state occupancy probabilities ## @math{@var{p0}(1), @dots{}, @var{p0}(N)} at time 0. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{Q}(i,j) ## Infinitesimal generator matrix. @var{Q} is a @math{N \times N} square ## matrix where @code{@var{Q}(i,j)} is the transition rate from state ## @math{i} to state @math{j}, for @math{1 @leq{} i \neq j @leq{} N}. ## @var{Q} must satisfy the property that @math{\sum_{j=1}^N Q_{i, j} = ## 0} ## ## @item @var{t} ## Time at which to compute the transient probability (@math{t @geq{} ## 0}). If omitted, the function computes the steady state occupancy ## probability vector. ## ## @item @var{p0}(i) ## probability that the system is in state @math{i} at time 0. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{p}(i) ## If this function is invoked with a single argument, @code{@var{p}(i)} ## is the steady-state probability that the system is in state @math{i}, ## @math{i = 1, @dots{}, N}. If this function is invoked with three ## arguments, @code{@var{p}(i)} is the probability that the system is in ## state @math{i} at time @var{t}, given the initial occupancy ## probabilities @var{p0}(1), @dots{}, @var{p0}(N). ## ## @end table ## ## @seealso{dtmc} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function q = ctmc( Q, t, p0 ) persistent epsilon = 10*eps; if ( nargin != 1 && nargin != 3 ) print_usage(); endif [N err] = ctmcchkQ(Q); ( N>0 ) || ... error(err); if ( nargin == 1 ) # steady-state analysis ## non zero columns nonzero=find( any(abs(Q)>epsilon,1 ) ); if ( length(nonzero) == 0 ) error( "Q is the zero matrix" ); endif normcol = nonzero(1); # normalization condition column ## force probability of unvisited states to zero for i=find( all(abs(Q)=0 ) || ... error("t must be a scalar >= 0"); ( isvector(p0) && length(p0) == N && all(p0>=0) && abs(sum(p0)-1.0). ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{Q} =} ctmcbd (@var{b}, @var{d}) ## ## @cindex Markov chain, continuous time ## @cindex continuous time Markov chain ## @cindex CTMC ## @cindex birth-death process, CTMC ## ## Returns the infinitesimal generator matrix @math{Q} for a ## continuous birth-death process over the finite state space ## @math{@{1, @dots{}, N@}}. For each @math{i=1, @dots{}, (N-1)}, ## @code{@var{b}(i)} is the transition rate from state @math{i} to ## state @math{(i+1)}, and @code{@var{d}(i)} is the transition rate from state ## @math{(i+1)} to state @math{i}. ## ## Matrix @math{\bf Q} is therefore defined as: ## ## @tex ## $$ \pmatrix{ -\lambda_1 & \lambda_1 & & & & \cr ## \mu_1 & -(\mu_1 + \lambda_2) & \lambda_2 & & \cr ## & \mu_2 & -(\mu_2 + \lambda_3) & \lambda_3 & & \cr ## \cr ## & & \ddots & \ddots & \ddots & & \cr ## \cr ## & & & \mu_{N-2} & -(\mu_{N-2}+\lambda_{N-1}) & \lambda_{N-1} \cr ## & & & & \mu_{N-1} & -\mu_{N-1} } ## $$ ## @end tex ## @ifnottex ## ## @example ## @group ## / \ ## | -b(1) b(1) | ## | d(1) -(d(1)+b(2)) b(2) | ## | d(2) -(d(2)+b(3)) b(3) | ## | | ## | ... ... ... | ## | | ## | d(N-2) -(d(N-2)+b(N-1)) b(N-1) | ## | d(N-1) -d(N-1) | ## \ / ## @end group ## @end example ## @end ifnottex ## ## @noindent where @math{\lambda_i} and @math{\mu_i} are the birth and ## death rates, respectively. ## ## @seealso{dtmcbd} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function Q = ctmcbd( birth, death ) if ( nargin != 2 ) print_usage(); endif ( isvector( birth ) && isvector( death ) ) || ... error( "birth and death must be vectors" ); birth = birth(:); # make birth a column vector death = death(:); # make death a column vector size_equal( birth, death ) || ... error( "birth and death rates must have the same length" ); all( birth >= 0 ) || ... error( "birth rates must be >= 0" ); all( death >= 0 ) || ... error( "death rates must be >= 0" ); ## builds the infinitesimal generator matrix Q = diag( birth, 1 ) + diag( death, -1 ); Q -= diag( sum(Q,2) ); endfunction %!test %! birth = [ 1 1 1 ]; %! death = [ 2 2 2 ]; %! Q = ctmcbd( birth, death ); %! assert( ctmc(Q), [ 8/15 4/15 2/15 1/15 ], 1e-5 ); queueing/inst/dtmcfpt.m0000664000175000017500000001021514620404470015056 0ustar morenomoreno## Copyright (C) 2011, 2012, 2016, 2018 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{M} =} dtmcfpt (@var{P}) ## ## @cindex first passage times ## @cindex mean recurrence times ## @cindex discrete time Markov chain ## @cindex Markov chain, discrete time ## @cindex DTMC ## ## Compute mean first passage times and mean recurrence times ## for an irreducible discrete-time Markov chain over the state space ## @math{@{1, @dots{}, N@}}. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(i,j) ## transition probability from state @math{i} to state @math{j}. ## @var{P} must be an irreducible stochastic matrix, which means that ## the sum of each row must be 1 (@math{\sum_{j=1}^N P_{i j} = 1}), ## and the rank of @var{P} must be @math{N}. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{M}(i,j) ## For all @math{1 @leq{} i, j @leq{} N}, @math{i \neq j}, @code{@var{M}(i,j)} is ## the average number of transitions before state @var{j} is entered ## for the first time, starting from state @var{i}. ## @code{@var{M}(i,i)} is the @emph{mean recurrence time} of state ## @math{i}, and represents the average time needed to return to state ## @var{i}. ## ## @end table ## ## @strong{REFERENCES} ## ## @itemize ## @item Grinstead, Charles M.; Snell, J. Laurie (July ## 1997). @cite{Introduction to Probability}, Ch. 11: Markov ## Chains. American Mathematical Society. ISBN 978-0821807491. ## @end itemize ## ## @seealso{ctmcfpt} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function result = dtmcfpt( P ) if ( nargin != 1 ) print_usage(); endif [N err] = dtmcchkP(P); ( N>0 ) || ... error(err); if ( any(diag(P) == 1) ) error("Cannot compute first passage times for absorbing chains"); endif w = dtmc(P); # steady state probability vector W = repmat(w,N,1); ## Z = (I - P + W)^-1 where W is the matrix where each row is the ## steady-state probability vector for P Z = inv(eye(N)-P+W); ## m_ij = (z_jj - z_ij) / w_j result = (repmat(diag(Z)',N,1) - Z) ./ repmat(w,N,1) + diag(1./w); endfunction %!test %! P = [1 1 1; 1 1 1]; %! fail( "dtmcfpt(P)" ); %!test %! P = dtmcbd([1 1 1], [0 0 0] ); %! fail( "dtmcfpt(P)", "absorbing" ); %!test %! P = [ 0.0 0.9 0.1; ... %! 0.1 0.0 0.9; ... %! 0.9 0.1 0.0 ]; %! p = dtmc(P); %! M = dtmcfpt(P); %! assert( diag(M)', 1./p, 1e-8 ); ## Example on p. 461 of [GrSn97] %!test %! P = [ 0 1 0 0 0; ... %! .25 .0 .75 0 0; ... %! 0 .5 0 .5 0; ... %! 0 0 .75 0 .25; ... %! 0 0 0 1 0 ]; %! M = dtmcfpt(P); %! assert( M, [16 1 2.6667 6.3333 21.3333; ... %! 15 4 1.6667 5.3333 20.3333; ... %! 18.6667 3.6667 2.6667 3.6667 18.6667; ... %! 20.3333 5.3333 1.6667 4 15; ... %! 21.3333 6.3333 2.6667 1 16 ], 1e-4 ); %!test %! sz = 10; %! P = reshape( 1:sz^2, sz, sz ); %! normP = repmat(sum(P,2),1,columns(P)); %! P = P./normP; %! M = dtmcfpt(P); %! for i=1:rows(P) %! for j=1:columns(P) %! assert( M(i,j), 1 + dot(P(i,:), M(:,j)) - P(i,j)*M(j,j), 1e-8); %! endfor %! endfor ## "Rat maze" problem (p. 453 of [GrSn97]); %!test %! P = zeros(9,9); %! P(1,[2 4]) = .5; %! P(2,[1 5 3]) = 1/3; %! P(3,[2 6]) = .5; %! P(4,[1 5 7]) = 1/3; %! P(5,[2 4 6 8]) = 1/4; %! P(6,[3 5 9]) = 1/3; %! P(7,[4 8]) = .5; %! P(8,[7 5 9]) = 1/3; %! P(9,[6 8]) = .5; %! M = dtmcfpt(P); %! assert( M(1:9 != 5,5)', [6 5 6 5 5 6 5 6], 100*eps ); queueing/inst/qsmg1.m0000664000175000017500000000531414620404470014451 0ustar morenomoreno## Copyright (C) 2009 Dmitry Kolesnikov ## Copyright (C) 2012, 2016, 2022 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qsmg1 (@var{lambda}, @var{xavg}, @var{x2nd}) ## ## @cindex @math{M/G/1} system ## ## Compute utilization, response time, average number of requests and ## throughput for a @math{M/G/1} system. The service time distribution ## is described by its mean @var{xavg}, and by its second moment ## @var{x2nd}. The computations are based on results from L. Kleinrock, ## @cite{Queuing Systems}, Wiley, Vol 2, and Pollaczek-Khinchine formula. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate ## ## @item @var{xavg} ## Average service time ## ## @item @var{x2nd} ## Second moment of service time distribution ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U} ## Service center utilization ## ## @item @var{R} ## Service center response time ## ## @item @var{Q} ## Average number of requests in the system ## ## @item @var{X} ## Service center throughput ## ## @item @var{p0} ## Probability that there is not any request at system ## ## @end table ## ## @var{lambda}, @var{xavg}, @var{t2nd} can be vectors of the ## same size. In this case, the results will be vectors as well. ## ## @seealso{qsmh1} ## ## @end deftypefn ## Author: Dmitry Kolesnikov function [U R Q X p0] = qsmg1(lambda, xavg, x2nd) if ( nargin != 3 ) print_usage(); endif ## bring the parameters to a common size [ err lambda xavg x2nd ] = common_size( lambda, xavg, x2nd ); if ( err ) error( "parameters are of incompatible size" ); endif mu = 1 ./ xavg; rho = lambda ./ mu; #coefficient of variation Cx = (x2nd - xavg .* xavg) ./ (xavg .* xavg); #PK mean formula(s) Q = rho + rho .* rho .* (1 + Cx) ./ (2 .* (1 - rho)); R = xavg + xavg .* rho .* (1 + Cx) ./ (2 .* (1 - rho)); p0 = exp(-rho); #General Results #utilization U = rho; X = lambda; endfunction queueing/inst/erlangb.m0000664000175000017500000000741014620404470015032 0ustar morenomoreno## Copyright (C) 2014, 2016, 2018, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{B} =} erlangb (@var{A}, @var{m}) ## ## @cindex Erlang-B formula ## ## Compute the steady-state blocking probability in the Erlang loss model. ## ## The Erlang-B formula @math{E_B(A, m)} gives the probability that an ## open system with @math{m} identical servers, arrival rate ## @math{\lambda}, individual service rate @math{\mu} and offered load ## @math{A = \lambda / \mu} has all servers busy. This corresponds to ## the rejection probability of an @math{M/M/m/0} system with @math{m} ## servers and no queue. ## ## @tex ## @math{E_B(A, m)} is defined as: ## ## $$ ## E_B(A, m) = \displaystyle{{A^m \over m!} \left( \sum_{k=0}^m {A^k \over k!} \right) ^{-1}} ## $$ ## @end tex ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{A} ## Offered load, defined as @math{A = \lambda / \mu} where ## @math{\lambda} is the mean arrival rate and @math{\mu} the mean ## service rate of each individual server (real, @math{A > 0}). ## ## @item @var{m} ## Number of identical servers (integer, @math{m @geq{} 1}). Default @math{m = 1} ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{B} ## The value @math{E_B(A, m)} ## ## @end table ## ## @var{A} or @var{m} can be vectors, and in this case, the results will ## be vectors as well. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Zeng, @cite{Two common properties of the Erlang-B function, Erlang-C function, and Engset blocking function}, Mathematical and Computer Modelling, Volume 37, Issues 12-13, June 2003, Pages 1287-1296 ## @end itemize ## ## @seealso{erlangc,engset,qsmmm} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function B = erlangb(A, m) if ( nargin < 1 || nargin > 2 ) print_usage(); endif ( isnumeric(A) && all( A(:) > 0 ) ) || error("A must be positive"); if ( nargin == 1 ) m = 1; else ( isnumeric(m) && all( fix(m(:)) == m(:)) && all( m(:) > 0 ) ) || error("m must be a positive integer"); endif [err A m] = common_size(A, m); if ( err ) error("parameters are not of common size"); endif B = arrayfun( @__erlangb_compute, A, m); endfunction ## Compute E_B(A,m) recursively, as described in: ## ## Guoping Zeng, Two common properties of the erlang-B function, ## erlang-C function, and Engset blocking function, Mathematical and ## Computer Modelling Volume 37, Issues 12–13, June 2003, Pages ## 1287–1296 http://dx.doi.org/10.1016/S0895-7177(03)90040-9 ## ## To improve numerical stability, the recursion is based on the inverse ## 1 / E_B rather than E_B itself. function B = __erlangb_compute(A, m) Binv = 1.0; for k=1:m Binv = 1.0 + k/A*Binv; endfor B = 1.0 / Binv; endfunction %!test %! fail("erlangb(1, -1)", "positive"); %! fail("erlangb(-1, 1)", "positive"); %! fail("erlangb(1, 0)", "positive"); %! fail("erlangb(0, 1)", "positive"); %! fail("erlangb('foo',1)", "positive"); %! fail("erlangb(1,'bar')", "positive"); %! fail("erlangb([1 1],[1 1 1])","common size"); queueing/inst/private/0000775000175000017500000000000014620417652014720 5ustar morenomorenoqueueing/inst/private/expn.m0000664000175000017500000000223614620404470016045 0ustar morenomoreno## Copyright (C) 2012, 2018, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{r} =} expn (@var{a}, @var{n}) ## ## Compute @code{r = a^n / n!}, with @math{a>0} and @math{n @geq{} 0}. ## ## @end deftypefn function r = expn( a, n ) (isscalar(n) && (n>=0)) || error("n must be nonnegative"); (isscalar(a) && (a>0)) || error("a must be positive"); r = prod( a./(1:n) ); # for n=0, prod([]) returns 1 which is correct endfunction queueing/inst/private/scc.m0000664000175000017500000000402014620404470015634 0ustar morenomoreno## Copyright (C) 2018, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{s} =} scc (@var{G}) ## ## Compute the Strongly Connected Components (SCC) of a graph with ## adjacency matrix @var{G}. Any positive value in @var{G} denotes ## an edge; zero or negative values denote the absence of an edge. ## ## @end deftypefn function s = scc( G ) ## It might be possible to use a different algorithm for SCC (e.g., ## http://pmtksupport.googlecode.com/svn/trunk/gaimc1.0-graphAlgo/scomponents.m assert(issquare(G)); N = rows(G); GF = (G>0); GB = (G'>0); s = zeros(N,1); c=1; for n=1:N if (s(n) == 0) fw = __dfs(GF,n); bw = __dfs(GB,n); r = (fw & bw); s(r) = c++; endif endfor endfunction ## This is essentially the same code from qncmvisits.m function v = __dfs(G, s) assert( issquare(G) ); N = rows(G); v = stack = zeros(1,N); ## v(i) == 1 iff node i has been visited q = 1; # first empty slot in queue stack(q++) = s; v(s) = 1; while( q>1 ) n = stack(--q); ## explore neighbors of n: all f in G(n,:) such that v(f) == 0 ## The following instruction is equivalent to: ## for f=find(G(n,:)) ## if ( v(f) == 0 ) for f = find ( G(n,:) & (v==0) ) stack(q++) = f; v(f) = 1; endfor endwhile endfunction queueing/inst/private/qncschkparam.m0000664000175000017500000000501514620404470017544 0ustar morenomoreno## Copyright (C) 2012, 2013, 2014 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{err} @var{Nout} @var{Sout} @var{Vout} @var{mout} @var{Zout}] = } qncschkparam( N, S, V, m, Z ) ## ## Validate input parameters for closed, single class networks. ## @var{err} is the empty string on success, or a suitable error message ## string on failure. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [err Nout Sout Vout mout Zout] = qncschkparam( N, S, V, m, Z ) err = ""; [Nout Sout Vout mout Zout] = deal(0); if ( nargin < 2 || nargin > 5) err = "Wrong number of parameters (min 2, max 5)"; return; endif if ! ( isscalar(N) && N>=0 && N == fix(N) ) err = "N must be a nonnegative integer"; return; endif Nout = N; if ! ( isnumeric(S) && isvector(S) && length(S)>0 ) err = "S must be a nonempty vector"; return; endif if ( any(S<0) ) err = "S must contain nonnegative values"; return; endif Sout = S(:)'; if ( nargin < 3 ) Vout = ones(size(Sout)); else if ! ( isnumeric(V) && isvector(V) ) err = "V must be a vector"; return; endif if ( any(V<0) ) err = "V must contain nonnegative values"; return; endif Vout = V(:)'; endif if ( nargin < 4 ) mout = ones(size(Sout)); else if ! ( isnumeric(V) && isvector(m) ) err = "m must be a vector"; return; endif mout = m(:)'; endif [er Sout Vout mout] = common_size(Sout, Vout, mout); if (er != 0 ) err = "S, V and m are of incompatible size"; return; endif if ( nargin < 5 ) Zout = 0; else if ! ( isscalar(Z) && Z >= 0 ) err = "Z must be a nonnegative scalar"; return; endif Zout = Z; endif endfunction queueing/inst/private/qncmchkparam.m0000664000175000017500000000634214620404470017542 0ustar morenomoreno## Copyright (C) 2012, 2013 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{err} @var{Nout} @var{Sout} @var{Vout} @var{mout} @var{Zout}] = } qncmchkparam( N, S ) ## @deftypefnx {Function File} {[@var{err} @var{Nout} @var{Sout} @var{Vout} @var{mout} @var{Zout}] = } qncmchkparam( N, S, V ) ## @deftypefnx {Function File} {[@var{err} @var{Nout} @var{Sout} @var{Vout} @var{mout} @var{Zout}] = } qncmchkparam( N, S, V, m ) ## @deftypefnx {Function File} {[@var{err} @var{Nout} @var{Sout} @var{Vout} @var{mout} @var{Zout}] = } qncmchkparam( N, S, V, m, Z ) ## ## Validate input parameters for closed, multiclass network. ## @var{err} is the empty string on success, or a suitable error message ## string on failure. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [err Nout Sout Vout mout Zout] = qncmchkparam( N, S, V, m, Z ) err = ""; [Nout Sout Vout mout Zout] = deal(0); if ( nargin < 2 || nargin > 5 ) err = "Wrong number of parameters (min 2, max 5)"; return; endif if ! ( isnumeric(N) && isvector(N) && length(N)>0 ) err = "N must be a nonempty vector"; return; endif if ! ( all(N>=0) && all( fix(N) == N ) ) err = "N must contain nonnegative integers"; return; endif Nout = N(:)'; C = length(Nout); ## Number of classes if ! ( isnumeric(S) && ismatrix(S) && ndims(S) == 2 && rows(S) == C ) err = sprintf("S must be a 2-dimensional matrix with %d rows",C); return; endif if ( any(S(:)<0) ) err = "S must contain nonnegative values"; return; endif Sout = S; K = columns(Sout); if ( nargin < 3 ) Vout = ones(size(Sout)); else if ! ( isnumeric(V) && ismatrix(V) && ndims(V) == 2 && rows(V) == C && columns(V) == K ) err = sprintf("V must be a %d x %d matrix", C, K ); return; endif if ( any(V(:)<0) ) err = "V must contain nonnegative values"; return; endif Vout = V; endif if ( nargin < 4 ) mout = ones(1,K); else if ! ( isnumeric(m) && isvector(m) && length(m) == K ) err = sprintf("m must be a vector with %d elements", K ); return; endif mout = m(:)'; endif if ( nargin < 5 ) Zout = zeros(1,C); else if ! ( isnumeric(Z) && isvector(Z) && length(Z) == C ) err = sprintf("Z must be a vector with %d elements", C); return; endif if ( any(Z<0) ) err = "Z must contain nonnegative values"; return; endif Zout = Z(:)'; endif endfunction queueing/inst/private/sumexpn.m0000664000175000017500000000505014620404470016567 0ustar morenomoreno## Copyright (C) 2012, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {@var{r} =} sumexpn (@var{a}, @var{n}) ## ## Compute the sum: ## ## @iftex ## @tex ## $$ S(a,n) = \sum_{k=0}^n {a^k \over k!} $$ ## @end tex ## @end iftex ## @ifnottex ## @example ## n ## __ ## \ a^k ## S(a,n) = > ----- ## /__ k! ## k=0 ## @end example ## @end ifnottex ## ## with @math{a>0} and @math{n @geq{} 0}. ## ## @end deftypefn function r = sumexpn( a, n ) n>=0 || ... error("n must be nonnegative"); a>0 || ... error("a must be positive"); #{ A direct calculation of the summation yields the expression: r = sum(cumprod([1 a./(1:n)])); However, we can apply an approach similar to Horner's rule and rewrite a^0 a^1 a^2 a^n --- + --- + --- + ... + --- 0! 1! 2! n! as a / a / a / / a \ \\\ 1 + - | 1 + - | 1 + - | 1 + ... | 1 + - | ... ||| 1 \ 2 \ 3 \ \ n / /// from which we can use the following iterative code that is numerically more stable: #} r = 1; for k=n:-1:1 r = (1+(a/k)*r); endfor endfunction %!test %! a = 0.8; %! n = 0; %! assert( sumexpn(a,n), sum(a.^(0:n) ./ factorial(0:n)), 1e-6 ); %!test %! a = 1.2; %! n = 6; %! assert( sumexpn(a,n), sum(a.^(0:n) ./ factorial(0:n)), 1e-6 ); %!test %! a = 18; %! assert( sumexpn(a,0), 1, 1e-6 ); %!test %! a = 18; %! assert( sumexpn(a,1), 1 + a, 1e-6 ); %!test %! a = 1.75; %! assert( sumexpn(a, 2), 1 + a + (a^2)/2, 1e-6 ); %!demo %! function r = sumexpn_direct(a, n) %! r = sum(cumprod([1 a./(1:n)])); %! endfunction %! %! a = 0.1:0.05:30; %! n = 20; %! d = zeros(size(a)); %! for idx=1:length(a) %! d(idx) = sumexpn_direct(a(idx),n) - sumexpn(a(idx),n); %! endfor %! plot(a,d, ";sumexpn_direct - sumexpn;"); queueing/inst/private/qnomchkparam.m0000664000175000017500000000474114620404470017557 0ustar morenomoreno## Copyright (C) 2012, 2013, 2014 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{err} @var{lambda} @var{S} @var{V} @var{m} @var{Z}] = } qnomchkparam( lambda, S, ... ) ## ## Validate input parameters for open, multiclass network. ## @var{err} is the empty string on success, or a suitable error message ## string on failure. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [err lambda S V m] = qnomchkparam( varargin ) err = ""; assert( nargin >= 2 ); lambda = varargin{1}; S = varargin{2}; [V m] = deal(0); if ! ( isnumeric(lambda) && isvector(lambda) && length(lambda)>0 ) err = "lambda must be a nonempty vector"; return; endif if ( any(lambda<0) ) err = "lambda must contain nonnegative values"; return; endif lambda = lambda(:)'; C = length(lambda); ## Number of classes if ! ( isnumeric(S) && ismatrix(S) && ndims(S) == 2 && rows(S) == C ) err = sprintf("S must be a 2-dimensional matrix with %d rows",C); return; endif if ( any(S(:)<0) ) err = "S must contain nonnegative values"; return; endif K = columns(S); if ( nargin < 3 ) V = ones(size(S)); else V = varargin{3}; if ! ( isnumeric(V) && ismatrix(V) & ndims(V) == 2 & rows(V) == C & columns(V) == K ) err = sprintf("V must be a %d x %d matrix", C, K ); return; endif if ( any(V(:)<0) ) err = "V must contain nonnegative values"; return; endif endif if ( nargin < 4 ) m = ones(1,K); else m = varargin{4}; if ! ( isnumeric(m) && isvector(m) && length(m) == K ) err = sprintf("m must be a vector with %d elements", K ); return; endif m = m(:)'; endif endfunction queueing/inst/private/qnoschkparam.m0000664000175000017500000000437514620404470017570 0ustar morenomoreno## Copyright (C) 2012, 2013, 2014 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{err} @var{lambda} @var{S} @var{V} @var{m}] = } qnoschkparam( lambda, S, V, m ) ## ## Validate input parameters for open, single class networks. ## @var{err} is the empty string on success, or a suitable error message ## string on failure. ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [err lambda S V m] = qnoschkparam( varargin ) err = ""; assert( nargin >= 2 ); lambda = varargin{1}; S = varargin{2}; [V m] = deal(0); if ! ( isscalar(lambda) && lambda > 0 ) err = "lambda must be a positive scalar"; return; endif if ! ( isnumeric(S) && isvector(S) && length(S)>0 ) err = "S must be a nonempty vector"; return; endif if ( any(S<0) ) err = "S must contain nonnegative values"; return; endif S = S(:)'; if ( nargin < 3 ) V = ones(size(S)); else V = varargin{3}; if ! ( isnumeric(V) && isvector(V) ) err = "V must be a vector"; return; endif if ( any(V<0) ) err = "V must contain nonnegative values"; return; endif V = V(:)'; endif if ( nargin < 4 ) m = ones(size(S)); else m = varargin{4}; if ! ( isnumeric(m) && isvector(m) ) err = "m must be a vector"; return; endif m = m(:)'; endif [er S V m] = common_size(S, V, m); if (er != 0 ) err = "S, V and m are of incompatible size"; return; endif endfunction queueing/inst/qsmmm.m0000664000175000017500000001700414620404470014552 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016, 2018, 2019, 2020, 2022 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pm}] =} qsmmm (@var{lambda}, @var{mu}) ## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pm}] =} qsmmm (@var{lambda}, @var{mu}, @var{m}) ## @deftypefnx {Function File} {@var{pk} =} qsmmm (@var{lambda}, @var{mu}, @var{m}, @var{k}) ## ## @cindex @math{M/M/m} system ## ## Compute utilization, response time, average number of requests in ## service and throughput for a @math{M/M/m} queue, a queueing system ## with @math{m} identical servers connected to a single FCFS ## queue. ## ## @tex ## The steady-state probability @math{\pi_k} that there are @math{k} ## requests in the system, @math{k \geq 0}, can be computed as: ## ## $$ ## \pi_k = \cases{ \displaystyle{\pi_0 { ( m\rho )^k \over k!}} & $0 \leq k \leq m$;\cr\cr ## \displaystyle{\pi_0 { \rho^k m^m \over m!}} & $k>m$.\cr ## } ## $$ ## ## where @math{\rho = \lambda/(m\mu)} is the individual server utilization. ## The steady-state probability @math{\pi_0} that there are no jobs in the ## system is: ## ## $$ ## \pi_0 = \left[ \sum_{k=0}^{m-1} { (m\rho)^k \over k! } + { (m\rho)^m \over m!} {1 \over 1-\rho} \right]^{-1} ## $$ ## ## @end tex ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate (@code{@var{lambda}>0}). ## ## @item @var{mu} ## Service rate (@code{@var{mu}>@var{lambda}}). ## ## @item @var{m} ## Number of servers (@code{@var{m} @geq{} 1}). ## Default is @code{@var{m}=1}. ## ## @item @var{k} ## Number of requests in the system (@code{@var{k} @geq{} 0}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U} ## Service center utilization, @math{U = \lambda / (m \mu)}. ## ## @item @var{R} ## Service center mean response time ## ## @item @var{Q} ## Average number of requests in the system ## ## @item @var{X} ## Service center throughput. If the system is ergodic, ## we will always have @code{@var{X} = @var{lambda}} ## ## @item @var{p0} ## Steady-state probability that there are 0 requests in the system ## ## @item @var{pm} ## Steady-state probability that an arriving request has to wait in the ## queue ## ## @item @var{pk} ## Steady-state probability that there are @var{k} requests in the ## system (including the one being served). ## ## @end table ## ## If this function is called with less than four parameters, ## @var{lambda}, @var{mu} and @var{m} can be vectors of the same size. In this ## case, the results will be vectors as well. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks ## and Markov Chains: Modeling and Performance Evaluation with Computer ## Science Applications}, Wiley, 1998, Section 6.5 ## @end itemize ## ## @seealso{erlangc,qsmm1,qsmminf,qsmmmk} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U_or_pk R Q X p0 pm] = qsmmm( lambda, mu, m, k ) if ( nargin < 2 || nargin > 4 ) print_usage(); endif if ( nargin == 2 ) m = 1; else ( isnumeric(lambda) && isnumeric(mu) && isnumeric(m) ) || ... error( "the parameters must be numeric vectors" ); endif [err lambda mu m] = common_size( lambda, mu, m ); if ( err ) error( "parameters are not of common size" ); endif lambda = lambda(:)'; mu = mu(:)'; m = m(:)'; all( m>0 ) || error( "m must be >0" ); all( lambda>0 ) || error( "lambda must be >0" ); rho = lambda ./ (m .* mu ); all( rho < 1 ) || error( "Processing capacity exceeded" ); for i=1:length(lambda) p0(i) = 1 / ( ... sumexpn( m(i)*rho(i), m(i)-1 ) + ... expn(m(i)*rho(i), m(i))/(1-rho(i)) ... ); endfor if (nargin < 4) X = lambda; U_or_pk = rho; pm = erlangc(lambda ./ mu, m); Q = m .* rho + rho ./ (1-rho) .* pm; R = Q ./ X; else (length(lambda) == 1) || error("lambda must be a scalar if this function is called with four arguments"); isvector(k) || error("k must be a vector"); all(k>=0) || error("k must be >= 0"); U_or_pk = 0*k; for idx=1:length(k) if (k(idx) <= m) U_or_pk(idx) = p0 * expn(m * rho, k(idx)); else U_or_pk(idx) = p0 * expn(m * rho, m) * (rho ^ (k(idx)-m)); endif endfor endif endfunction %!demo %! # This is figure 6.4 on p. 220 Bolch et al. %! rho = 0.9; %! ntics = 21; %! lambda = 0.9; %! m = linspace(1,ntics,ntics); %! mu = lambda./(rho .* m); %! [U R Q X] = qsmmm(lambda, mu, m); %! qlen = X.*(R-1./mu); %! plot(m,Q,"o",qlen,"*"); %! axis([0,ntics,0,25]); %! legend("Jobs in the system","Queue Length","location","northwest"); %! legend("boxoff"); %! xlabel("Number of servers (m)"); %! title("M/M/m system, \\lambda = 0.9, \\mu = 0.9"); %!demo %! ## Given a M/M/m queue, compute the steady-state probability pk of %! ## having k jobs in the systen. %! lambda = 0.5; %! mu = 0.15; %! m = 5; %! k = 0:10; %! pk = qsmmm(lambda, mu, m, k); %! plot(k, pk, "-o", "linewidth", 2); %! xlabel("N. of jobs (k)"); %! ylabel("P_k"); %! title(sprintf("M/M/%d system, \\lambda = %g, \\mu = %g", m, lambda, mu)); %!test %! # source: https://www.systems.ethz.ch/sites/default/files/file/asl2017/slides/slides-mmx-queues.pdf %! lambda = 9; %! m = 2; %! mu = 5; %! [U R Q X] = qsmmm(lambda, mu, m); %! W = R - 1/mu; # waiting time %! NW = lambda * W; # number of waiting customers %! assert( NW, 7.674, 1e-3 ); %! assert( R, 1.053, 1e-3 ); %!test %! # source: https://www.systems.ethz.ch/sites/default/files/file/asl2017/slides/slides-mmx-queues.pdf %! lambda = 9; %! m = 4; %! mu = 5; %! [U R Q X] = qsmmm(lambda, mu, m); %! W = R - 1/mu; # waiting time %! NW = lambda * W; # number of waiting customers %! assert( NW, 0.105, 1e-3 ); %! assert( R, 0.212, 1e-3 ); %!test %! # compare with qsmm1 in the special case m=1 %! lambda = 4; %! mu = 5; %! m = 1; # this is actually a M/M/1 system %! [U1 R1 Q1 X1] = qsmmm(lambda, mu, m); %! [U2 R2 Q2 X2] = qsmm1(lambda, mu); %! assert(U1, U2, 1e-5); %! assert(R1, R2, 1e-5); %! assert(Q1, Q2, 1e-5); %! assert(X1, X2, 1e-5); %!demo %! ## This code produces Fig. 4 from the paper: M. Marzolla, "A GNU %! ## Octave package for Queueing Networks and Markov Chains analysis", %! ## submitted to the ACM Transactions on Mathematical Software. %! %! lambda = 4; mu = 1.2; %! k = 0:20; %! pk_inf = qsmminf(lambda, mu, k); %! pk_4 = qsmmm(lambda, mu, 4, k); %! pk_5 = qsmmm(lambda, mu, 5, k); %! %! plot(k, pk_inf, "-ok;M/M/\\infty;", "linewidth", 1.5, ... %! k, pk_5, "--+k;M/M/5;", "linewidth", 1.5, ... %! k, pk_4, "--xk;M/M/4;", "linewidth", 1.5 ... %! ); %! xlabel("N. of requests (k)"); %! ylabel("\\pi_k"); %! legend("boxoff"); %! title(sprintf("PMF of M/M/\\infty and M/M/m systems, \\lambda = %g, \\mu = %g", lambda, mu)); queueing/inst/qsmmmk.m0000664000175000017500000001746314620404470014736 0ustar morenomoreno## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2016, 2018, 2019 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pK}] =} qsmmmk (@var{lambda}, @var{mu}, @var{m}, @var{K}) ## @deftypefnx {Function File} {@var{pn} =} qsmmmk (@var{lambda}, @var{mu}, @var{m}, @var{K}, @var{n}) ## ## @cindex @math{M/M/m/K} system ## ## Compute utilization, response time, average number of requests and ## throughput for a @math{M/M/m/K} finite capacity system. In a ## @math{M/M/m/K} system there are @math{m \geq 1} identical service centers ## sharing a fixed-capacity queue. At any time, at most @math{K @geq{} m} requests can be in the system, including those being served. The maximum queue length ## is @math{K-m}. This function generates and ## solves the underlying CTMC. ## ## @tex ## ## The steady-state probability @math{\pi_n} that there are @math{n} ## jobs in the system, @math{0 @leq{} n @leq{} K}, is: ## ## $$ ## \pi_n = \cases{ \displaystyle{{\rho^n \over n!} \pi_0} & if $0 \leq n \leq m$;\cr\cr ## \displaystyle{{\rho^m \over m!} \left( \rho \over m \right)^{n-m} \pi_0} & if $m < n \leq K$\cr} ## $$ ## ## where @math{\rho = \lambda/\mu} is the offered load. The probability ## @math{\pi_0} that the system is empty can be computed by considering ## that all probabilities must sum to one: @math{\sum_{k=0}^K \pi_k = 1}, ## that gives: ## ## $$ ## \pi_0 = \left[ \sum_{k=0}^m {\rho^k \over k!} + {\rho^m \over m!} \sum_{k=m+1}^K \left( {\rho \over m}\right)^{k-m} \right]^{-1} ## $$ ## ## @end tex ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{lambda} ## Arrival rate (@code{@var{lambda}>0}) ## ## @item @var{mu} ## Service rate (@code{@var{mu}>0}) ## ## @item @var{m} ## Number of servers (@code{@var{m} @geq{} 1}) ## ## @item @var{K} ## Maximum number of requests allowed in the system, ## including those being served (@code{@var{K} @geq{} @var{m}}) ## ## @item @var{n} ## Number of requests in the (@code{0 @leq{} @var{n} @leq{} K}). ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{U} ## Service center utilization ## ## @item @var{R} ## Service center response time ## ## @item @var{Q} ## Average number of requests in the system ## ## @item @var{X} ## Service center throughput ## ## @item @var{p0} ## Steady-state probability that there are no requests in the system. ## ## @item @var{pK} ## Steady-state probability that there are @var{K} requests in the system ## (i.e., probability that the system is full). ## ## @item @var{pn} ## Steady-state probability that there are @var{n} requests in the system ## (including those being served). ## ## @end table ## ## If this function is called with less than five arguments, ## @var{lambda}, @var{mu}, @var{m} and @var{K} can be either scalars, or ## vectors of the same size. In this case, the results will be vectors ## as well. ## ## @strong{REFERENCES} ## ## @itemize ## @item ## G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks ## and Markov Chains: Modeling and Performance Evaluation with Computer ## Science Applications}, Wiley, 1998, Section 6.6 ## @end itemize ## ## @seealso{qsmm1,qsmminf,qsmmm} ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [U_or_pn R Q X p0 pK] = qsmmmk( lambda, mu, m, K, n ) if ( nargin < 4 || nargin > 5 ) print_usage(); endif ( isvector(lambda) && isvector(mu) && isvector(m) && isvector(K) ) || ... error( "lambda, mu, m, K must be vectors" ); lambda = lambda(:)'; # make lambda a row vector mu = mu(:)'; # make mu a row vector m = m(:)'; # make m a row vector K = K(:)'; # make K a row vector [err lambda mu m K] = common_size( lambda, mu, m, K ); if ( err ) error( "Parameters are not of common size" ); endif all( K>0 ) || ... error( "k must be strictly positive" ); all( m>0 ) && all( m <= K ) || ... error( "m must be in the range 1:k" ); all( lambda>0 ) && all( mu>0 ) || ... error( "lambda and mu must be >0" ); if (nargin < 5) U_or_pn = R = Q = X = p0 = pK = 0*lambda; for i=1:length(lambda) ## Build and solve the birth-death process describing the M/M/m/k system birth_rate = lambda(i)*ones(1,K(i)); death_rate = [ linspace(1,m(i),m(i))*mu(i) ones(1,K(i)-m(i))*m(i)*mu(i) ]; p = ctmc(ctmcbd(birth_rate, death_rate)); p0(i) = p(1); pK(i) = p(1+K(i)); j = [1:K(i)]; Q(i) = dot( p(1+j),j ); endfor ## Compute other performance measures X = lambda.*(1-pK); U_or_pn = X ./ (m .* mu ); R = Q ./ X; else (length(lambda) == 1) || error("lambda must be a scalar if this function is called with five arguments"); isvector(n) || error("n must be a vector"); (all(n >= 0) && all(n <= K)) || error("n must be >= 0 and <= K"); n = n(:)'; birth_rate = lambda*ones(1,K); death_rate = [ linspace(1,m,m)*mu ones(1,K-m)*m*mu ]; p = ctmc(ctmcbd(birth_rate, death_rate)); U_or_pn = p(1+n); endif endfunction %!test %! lambda = mu = m = 1; %! k = 10; %! [U R Q X p0] = qsmmmk(lambda,mu,m,k); %! assert( Q, k/2, 1e-7 ); %! assert( U, 1-p0, 1e-7 ); %!test %! lambda = [1 0.8 2 9.2 0.01]; %! mu = lambda + 0.17; %! k = 12; %! [U1 R1 Q1 X1] = qsmm1k(lambda,mu,k); %! [U2 R2 Q2 X2] = qsmmmk(lambda,mu,1,k); %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 ); %! assert( Q1, Q2, 1e-5 ); %! assert( X1, X2, 1e-5 ); %! #assert( [U1 R1 Q1 X1], [U2 R2 Q2 X2], 1e-5 ); %!test %! lambda = 0.9; %! mu = 0.75; %! k = 10; %! [U1 R1 Q1 X1 p01] = qsmmmk(lambda,mu,1,k); %! [U2 R2 Q2 X2 p02] = qsmm1k(lambda,mu,k); %! assert( [U1 R1 Q1 X1 p01], [U2 R2 Q2 X2 p02], 1e-5 ); %!test %! lambda = 0.8; %! mu = 0.85; %! m = 3; %! k = 5; %! [U1 R1 Q1 X1 p0] = qsmmmk( lambda, mu, m, k ); %! birth = lambda*ones(1,k); %! death = [ mu*linspace(1,m,m) mu*m*ones(1,k-m) ]; %! q = ctmc(ctmcbd( birth, death )); %! U2 = dot( q, min( 0:k, m )/m ); %! assert( U1, U2, 1e-4 ); %! Q2 = dot( [0:k], q ); %! assert( Q1, Q2, 1e-4 ); %! assert( p0, q(1), 1e-4 ); %!test %! # This test comes from an example I found on the web %! lambda = 40; %! mu = 30; %! m = 3; %! k = 7; %! [U R Q X p0] = qsmmmk( lambda, mu, m, k ); %! assert( p0, 0.255037, 1e-6 ); %! assert( R, 0.036517, 1e-6 ); %!test %! # This test comes from an example I found on the web %! lambda = 50; %! mu = 10; %! m = 4; %! k = 6; %! [U R Q X p0 pk] = qsmmmk( lambda, mu, m, k ); %! assert( pk, 0.293543, 1e-6 ); %!test %! # This test comes from an example I found on the web %! lambda = 3; %! mu = 2; %! m = 2; %! k = 5; %! [U R Q X p0 pk] = qsmmmk( lambda, mu, m, k ); %! assert( p0, 0.179334, 1e-6 ); %! assert( pk, 0.085113, 1e-6 ); %! assert( Q, 2.00595, 1e-5 ); %! assert( R-1/mu, 0.230857, 1e-6 ); # waiting time in the queue %!demo %! ## Given a M/M/m/K queue, compute the steady-state probability pn %! ## of having n jobs in the systen. %! lambda = 0.2; %! mu = 0.25; %! m = 5; %! K = 20; %! n = 0:10; %! pn = qsmmmk(lambda, mu, m, K, n); %! plot(n, pn, "-o", "linewidth", 2); %! xlabel("N. of jobs (n)"); %! ylabel("P_n"); %! title(sprintf("M/M/%d/%d system, \\lambda = %g, \\mu = %g", m, K, lambda, mu)); queueing/inst/qncmvisits.m0000664000175000017500000002221614620404470015621 0ustar morenomoreno## Copyright (C) 2012, 2016, 2020 Moreno Marzolla ## ## This file is part of the queueing toolbox. ## ## The queueing toolbox is free software: you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation, either version 3 of the ## License, or (at your option) any later version. ## ## The queueing toolbox is distributed in the hope that it will be ## useful, but WITHOUT ANY WARRANTY; without even the implied warranty ## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with the queueing toolbox. If not, see . ## -*- texinfo -*- ## ## @deftypefn {Function File} {[@var{V} @var{ch}] =} qncmvisits (@var{P}) ## @deftypefnx {Function File} {[@var{V} @var{ch}] =} qncmvisits (@var{P}, @var{r}) ## ## Compute the average number of visits for the nodes of a closed multiclass network with @math{K} service centers and @math{C} customer classes. ## ## @strong{INPUTS} ## ## @table @code ## ## @item @var{P}(r,i,s,j) ## probability that a ## class @math{r} request which completed service at center @math{i} is ## routed to center @math{j} as a class @math{s} request. Class switching ## is allowed. ## ## @item @var{r}(c) ## index of class @math{c} reference station, ## @math{r(c) \in @{1, @dots{}, K@}}, @math{1 @leq{} c @leq{} C}. ## The class @math{c} visit count to server @code{@var{r}(c)} ## (@code{@var{V}(c,r(c))}) is conventionally set to 1. The reference ## station serves two purposes: (i) its throughput is assumed to be the ## system throughput, and (ii) a job returning to the reference station ## is assumed to have completed one cycle. Default is to consider ## station 1 as the reference station for all classes. ## ## @end table ## ## @strong{OUTPUTS} ## ## @table @code ## ## @item @var{V}(c,i) ## number of visits of class @math{c} requests at center @math{i}. ## ## @item @var{ch}(c) ## chain number that class @math{c} belongs ## to. Different classes can belong to the same chain. Chains are ## numbered sequentially starting from 1 (@math{1, 2, @dots{}}). The ## total number of chains is @code{max(@var{ch})}. ## ## @end table ## ## @end deftypefn ## Author: Moreno Marzolla ## Web: http://www.moreno.marzolla.name/ function [V chains] = qncmvisits( P, r ) if ( nargin < 1 || nargin > 2 ) print_usage(); endif ndims(P) == 4 || ... error("P must be a 4-dimensional matrix"); [C, K, C2, K2] = size( P ); (K == K2 && C == C2) || ... error( "P must be a C*K*C*K matrix"); if ( nargin < 2) r = ones(1,C); else isvector(r) && length(r) == C || ... error("r must be a vector with %d elements",C); all( r>=1 && r<=K ) || ... error("elements in r must be in the range [1, %d]",K); r = r(:)'; endif ## solve the traffic equations: V(s,j) = sum_r sum_i V(r,i) * ## P(r,i,s,j), for all s,j V(s,r(s)) = 1 for all s. A = reshape(P,[K*C K*C])-eye(K*C); b = zeros(1,K*C); CH = __scc(reshape(P,[C*K C*K])>0); nCH = max(CH); # number of chains CH = reshape(CH,C,K); # CH(c,k) is the chain that class c at center k belongs to chains = zeros(1,C); for k=1:K for c=1:C if ( chains(c) == 0 ) chains(c) = CH(c,k); else ( CH(c,k) == 0 || chains(c) == CH(c,k) ) || ... error("Class %d belongs to different chains",c); endif endfor endfor constraints = zeros(1,nCH); # constraint(cc) = 1 iff we set a constraint for a class belonging to chain cc; we only set one constraint per chain for c=1:C cc = CH(c,r(c)); if ( cc == 0 || constraints(cc) == 0 ) ii = sub2ind([C K],c,r(c)); A(:,ii) = 0; A(ii,ii) = 1; if ( cc > 0 ) ## if r(c) is not an isolated node constraints(cc) = 1; b(ii) = 1; endif endif endfor V = reshape(b/A, C, K); ## Make sure that no negative values appear (sometimes, numerical ## errors produce tiny negative values instead of zeros) V = max(0,V); endfunction %!test %! %! ## Closed, multiclass network %! %! C = 2; K = 3; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = 1; %! P(1,2,1,1) = 1; %! P(2,1,2,3) = 1; %! P(2,3,2,1) = 1; %! V = qncmvisits(P); %! for c=1:C %! for k=1:K %! assert(V(c,k), sum(sum(V .* P(:,:,c,k))), 1e-5); %! endfor %! endfor %!test %! %! ## Test multiclass network. Example from Schwetman (figure 7, page 9 of %! ## http://docs.lib.purdue.edu/cstech/259/ %! ## "Testing network-of-queues software, technical report CSD-TR 330, %! ## Purdue University). %! %! C = 2; K = 4; %! P = zeros(C,K,C,K); %! # class 1 routing %! P(1,1,1,1) = .05; %! P(1,1,1,2) = .45; %! P(1,1,1,3) = .5; %! P(1,2,1,1) = 1; %! P(1,3,1,1) = 1; %! # class 2 routing %! P(2,1,2,1) = .01; %! P(2,1,2,3) = .5; %! P(2,1,2,4) = .49; %! P(2,3,2,1) = 1; %! P(2,4,2,1) = 1; %! V = qncmvisits(P); %! for c=1:C %! for i=1:K %! assert(V(c,i), sum(sum(V .* P(:,:,c,i))), 1e-5); %! endfor %! endfor %!test %! %! ## Network with class switching. %! ## This is the example in figure 9 of %! ## Schwetman, "Implementing the Mean Value Analysis %! ## Algorithm fort the solution of Queueing Network Models", Technical %! ## Report CSD-TR-355, Department of Computer Science, Purdue Univrsity, %! ## Feb 15, 1982, http://docs.lib.purdue.edu/cstech/286/ %! %! C = 2; K = 3; %! S = [.01 .07 .10; ... %! .05 0.7 .10 ]; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = .7; %! P(1,1,1,3) = .2; %! P(1,1,2,1) = .1; %! P(2,1,2,2) = .3; %! P(2,1,2,3) = .5; %! P(2,1,1,1) = .2; %! P(1,2,1,1) = P(1,3,1,1) = 1; %! P(2,2,2,1) = P(2,3,2,1) = 1; %! N = [3 0]; %! V = qncmvisits(P); %! VV = [10 7 2; 5 1.5 2.5]; # result given in Schwetman; our function computes something different, but that's ok since visit counts are actually ratios %! assert( V ./ repmat(V(:,1),1,K), VV ./ repmat(VV(:,1),1,K), 1e-5 ); %!test %! %! ## two disjoint classes: must produce two disjoing chains %! %! C = 2; K = 3; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = 1; %! P(1,2,1,1) = 1; %! P(2,1,2,3) = 1; %! P(2,3,2,1) = 1; %! [nc r] = qncmvisits(P); %! assert( r(1) != r(2) ); %!test %! %! ## two classes, one chain %! %! C = 2; K = 3; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = .5; %! P(1,2,2,1) = 1; %! P(2,1,2,3) = .5; %! P(2,3,1,1) = 1; %! [nc r] = qncmvisits(P); %! assert( r(1) == r(2) ); %!test %! %! ## a "Moebius strip". Note that this configuration is invalid, and %! ## therefore our algorithm must raise an error. This is because this %! ## network has two chains, but both chains contain both classes %! %! C = 2; K = 2; %! P = zeros(C,K,C,K); %! P(1,1,2,2) = 1; %! P(2,2,1,1) = 1; %! P(2,1,1,2) = 1; %! P(1,2,2,1) = 1; %! fail( "qncmvisits(P)", "different"); %!test %! %! ## Network with two classes representing independent chains. %! ## This is example in figure 8 of %! ## Schwetman, "Implementing the Mean Value Analysis %! ## Algorithm fort the solution of Queueing Network Models", Technical %! ## Report CSD-TR-355, Department of Computer Science, Purdue Univrsity, %! ## Feb 15, 1982, http://docs.lib.purdue.edu/cstech/286/ %! %! C = 2; K = 2; %! P = zeros(C,K,C,K); %! P(1,1,1,3) = P(1,3,1,1) = 1; %! P(2,2,2,3) = P(2,3,2,2) = 1; %! V = qncmvisits(P,[1,2]); %! assert( V, [1 0 1; 0 1 1], 1e-5 ); %!test %! C = 2; %! K = 3; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = 1; %! P(1,2,1,3) = 1; %! P(1,3,2,2) = 1; %! P(2,2,1,1) = 1; %! [V ch] = qncmvisits(P); %! assert( ch, [1 1] ); ## The following transition probability matrix is not well formed: note ## that there is an outgoing transition from center 1, class 1 but not ## incoming transition. %!test %! C = 2; %! K = 3; %! P = zeros(C,K,C,K); %! P(1,1,1,2) = 1; %! P(1,2,1,3) = 1; %! P(1,3,2,2) = 1; %! P(2,2,2,1) = 1; %! P(2,1,1,2) = 1; %! [V ch] = qncmvisits(P); %! assert( ch, [1 1] ); ## compute strongly connected components using Kosaraju's algorithm, ## which requires two DFS visits. A better solution would be to use ## Tarjan's algorithm. ## ## In this implementation, an isolated node without self loops will NOT ## belong to any SCC. Although this is not formally correct from the ## graph theoretic point of view, it is necessary to compute chains ## correctly. function s = __scc(G) assert(issquare(G)); N = rows(G); GF = (G>0); GB = (G'>0); s = zeros(N,1); c=1; for n=1:N if (s(n) == 0) fw = __dfs(GF,n); bw = __dfs(GB,n); r = (fw & bw); if (any(r)) s(r) = c++; endif endif endfor endfunction ## Executes a dfs visit on graph G, starting from source node s function v = __dfs(G, s) assert( issquare(G) ); N = rows(G); v = stack = zeros(1,N); ## v(i) == 1 iff node i has been visited q = 1; # first empty slot in queue stack(q++) = s; ## Note: node s is NOT marked as visited; it will be marked as visited ## only if we visit it again. This is necessary to ensure that ## isolated nodes without self loops will not belong to any SCC. while( q>1 ) n = stack(--q); ## explore neighbors of n: all f in G(n,:) such that v(f) == 0 ## The following instruction is equivalent to: ## for f=find(G(n,:)) ## if ( v(f) == 0 ) for f = find ( G(n,:) & (v==0) ) stack(q++) = f; v(f) = 1; endfor endwhile endfunction queueing/README.md0000664000175000017500000000530014620410450013533 0ustar morenomoreno# The Octave queueing toolbox Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2018, 2020, 2024 Moreno Marzolla ## Description The _queueing toolbox_ ("queueing", in short) is a collection of GNU Octave scripts for numerical evaluation of queueing network models. Open, closed and mixed networks are supported, with single or multiple classes of customers. The queueing toolbox also provides functions for steady-state and transient analysis of Markov chains, as well as for single station queueing systems. This package requires GNU Octave version 4.0.0 or later. GNU Octave is free software and is available at https://www.gnu.org/software/octave/ ## Download and install The Web pages of the queueing toolbox are https://gnu-octave.github.io/packages/queueing/ https://www.moreno.marzolla.name/software/queueing/ where the latest version can be downloaded. See the installation instructions there. ## Citation To cite the Octave queueing package use: > Moreno Marzolla, The qnetworks Toolbox: A Software Package for > Queueing Networks Analysis. Khalid Al-Begain, Dieter Fiems and > William J. Knottenbelt, Editors, Proceedings 17th International > Conference on Analytical and Stochastic Modeling Techniques and > Applications (ASMTA 2010) Cardiff, UK, June 14--16, 2010, volume > 6148 of Lecture Notes in Computer Science, Springer, pp. 102--116, > ISBN 978-3-642-13567-5, DOI 10.1007/978-3-642-13568-2_8 A BibTeX entry for LaTeX users is: ``` @inproceedings{queueing, author = {Moreno Marzolla}, title = {The qnetworks Toolbox: A Software Package for Queueing Networks Analysis}, booktitle = {Analytical and Stochastic Modeling Techniques and Applications, 17th International Conference, ASMTA 2010, Cardiff, UK, June 14--16, 2010. Proceedings}, editor = {Khalid Al-Begain and Dieter Fiems and William J. Knottenbelt}, year = {2010}, publisher = {Springer}, series = {Lecture Notes in Computer Science}, volume = {6148}, pages = {102--116}, ee = {http://dx.doi.org/10.1007/978-3-642-13568-2_8}, doi = {10.1007/978-3-642-13568-2_8}, isbn = {978-3-642-13567-5} } ``` ## Documentation The queueing toolbox comes with extensive documentation; here is the user manual in [pdf](https://www.moreno.marzolla.name/software/queueing/queueing.pdf) and [html](https://www.moreno.marzolla.name/software/queueing/queueing.html) format. Usage help for all functions is available through the `help` built-in command at the GNU Octave prompt. See the manual for details. The Octave queueing toolbox is distributed under the terms of the GNU General Public License, version 3 or later. See the file for details. queueing/NEWS0000664000175000017500000001240214620415500012755 0ustar morenomorenoSummary of important user-visible changes for queueing-1.2.8 ------------------------------------------------------------------------------ ** queueing-1.2.8 contains minor changes ** New demo blocks for qsmmm(), ctmc() and qmcmmvabs() ** Removed deprecated operators .- and .+ ** Fixed a few syntax errors ** Fixed automatic generation of PDF documentation ** Fixed documentation ** Migrated source repository to GitHub Summary of important user-visible changes for queueing-1.2.7 ------------------------------------------------------------------------------ ** queueing-1.2.7 contains new features ** Added computation of state occupancy probabilities to functions qsmm1(), qsmm1k(), qsmminf(), qsmmm(), qsmmmk() ** Function qncmmvaap() has been deprecated and renamed to qncmmvabs() ** The following deprecated functions have been removed: qnvisits(), qnopensingle(), qnopenmulti(), qnopenbsb(), qnopenab(), qnmvapop(), qnmvablo(), qnjackson(), qnconvolution(), qnconvolutionld(), qncmva(), qnclosedsinglemva(), qnclosedsinglemvald(), qnclosedpb(), qnclosedmultimva(), qnclosedab(), qnclosedbsb(), qnclosedgb(), qnclosedmultimvaapprox(), qnclosedsinglemvaapprox(), qnmg1(), qnmh1(), qnmm1(), qnmminf(), qnmmmk(), qnmmm(), qnmm1k(), qnammm(), ctmc_bd(), ctmc_exps(), ctmc_fpt(), ctmc_mtta(), ctmc_taexps(), dtmc_bd(), dtmc_exps(), dtmc_fpt(), dtmc_mtta(), dtmc_taexps(), population_mix(), dtmc_is_irreducible(), ctmc_check_Q(), dtmc_check_P() Summary of important user-visible changes for queueing-1.2.6 ------------------------------------------------------------------------------ ** queueing-1.2.6 contains new features ** New functions dtmcisir() and ctmcisir() ** General documentation cleanup Summary of important user-visible changes for queueing-1.2.5 ------------------------------------------------------------------------------ ** queueing-1.2.5 is a bug fix release ** Fix for bug in qncmmva ** General documentation cleanup Summary of important user-visible changes for queueing-1.2.4 ------------------------------------------------------------------------------ ** queueing-1.2.4 is a bug fix release ** Fixes for bugs #48958, #48959 and #48960 Summary of important user-visible changes for queueing-1.2.3 ------------------------------------------------------------------------------ ** queueing-1.2.3 contains new features ** Added new functions erlangb (Erlang-B formula), erlangc (Erlang-C formula) and engset Summary of important user-visible changes for queueing-1.2.2 ------------------------------------------------------------------------------ ** queueing-1.2.2 is a bug fix release ** Fixed bug in qncmmva: utilization for M/M/m centers was not correctly scaled to [0,1] when m>1 ** Added warning to qncsmva and qncmmva to detect and report numerical instability problems Summary of important user-visible changes for queueing-1.2.1 ------------------------------------------------------------------------------ ** queueing-1.2.1 contains new features ** Function qnvisits() has been deprecated, and is replaced by qncsvisits(), qnosvisits() (for single-class networks) and qncmvisits(), qnomvisits() (for multiple-class networks). The new functions allow the user to specify the reference station. Summary of important user-visible changes for queueing-1.2.0 ------------------------------------------------------------------------------ ** queueing-1.2.0 includes many bug fixes and new features ** The documentation has been restructured, hopefully improving readability and overall organization ** Added functions to compute various kinds of performance bounds on multiclass networks; balanced system, asymptotic and composite bounds are supported. ** Added function qnom for analyzing open, multiclass product-form networks. ** Adopted a new scheme for naming functions; old names are still available for compatibility with existing scripts, but will be removed in future releases. ** Fixed bugs in qncscmva, qncsconv, qncsconvld, qnopensingle, qnopenmulti and qncmmva Summary of important user-visible changes for queueing-1.1.1 ------------------------------------------------------------------------------ ** queueing-1.1.1 is a bug fix release ** Increased tolerance in tests for dtmc_fpt and dtmc_mtta to avoid spurious failures on some platforms ** Set "Autoload: no" in the DESCRIPTION file. This means that this package is no longer automatically loaded on Octave startup. To use the queueing package you need to issue the command "pkg load queueing" at the Octave prompt. Summary of important user-visible changes for queueing-1.1.0 ------------------------------------------------------------------------------ ** Function ctmc_exps() can now compute the expected sojourn time until absorption for absorbing CTMC ** Functions ctmc_exps() and ctmc_taexps() now accept a scalar as the second argument (time). ** Function ctmc_bd() now returns the infinitesimal generator matrix Q of the birth-death process with given rates, not the steady-state solution. ** The following new functions have been added: dtmc_bd(), dtmc_mtta(), ctmc_check_Q(), dtmc_exps(), dtmc_taexps() ** The following deprecated functions have been removed: ctmc_bd_solve(), ctmc_solve(), dtmc_solve() queueing/COPYING0000664000175000017500000010451314620404470013322 0ustar morenomoreno GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . queueing/DESCRIPTION0000664000175000017500000000170714620415614014000 0ustar morenomorenoName: queueing Version: 1.2.8 Date: 2024-05-13 Author: Moreno Marzolla Maintainer: Moreno Marzolla Title: Octave package for Queueing Networks and Markov chains analysis Description: The queueing package provides functions for queueing networks and Markov chains analysis. This package can be used to compute steady-state performance measures for open, closed and mixed networks with single or multiple job classes. Mean Value Analysis (MVA), convolution, and various bounding techniques are implemented. Furthermore, several transient and steady-state performance measures for Markov chains can be computed, such as state occupancy probabilities, mean time to absorption, time-averaged sojourn times and so forth. Discrete- and continuous-time Markov chains are supported. Categories: Misc Depends: octave (>= 4.0.0) Autoload: no License: GPLv3+ Url: https://www.moreno.marzolla.name/software/queueing/ queueing/INSTALL0000664000175000017500000001021314620415630013311 0ustar morenomorenoThis file documents the installation procedure of the Octave 'queueing' package. 'queueing' is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 3 or later, as published by the Free Software Foundation. Note: This file ('INSTALL') is automatically generated from 'doc/installation.txi' in the 'queueing' source tree. Do not modify this document directly, as changes will be lost. Modify 'doc/installation.txi' instead. 1 Installation and Getting Started ********************************** 1.1 Installation through Octave package management system ========================================================= The most recent version of 'queueing' is 1.2.8 and can be downloaded from Additional information can be found at To install 'queueing', follow these steps: 1. If you have a recent version of GNU Octave and a network connection, you can install 'queueing' from Octave command prompt using this command: octave:1> pkg install pkg install "https://github.com/mmarzolla/queueing/releases/download/1.2.8/queueing-1.2.8.tar.gz" The command above will download and install the latest version of the 'queueing' package from the source repository, and install it on your machine. If you do not have root access, you can perform a local install with: octave:1> pkg install -local "https://github.com/mmarzolla/queueing/releases/download/1.2.8/queueing-1.2.8.tar.gz" This will install 'queueing' in your home directory, and the package will be available to the current user only. 2. Alternatively, you can first download the 'queueing' tarball; to install the package in the system-wide location issue this command at the Octave prompt: octave:1> pkg install _queueing-1.2.8.tar.gz_ (you may need to start Octave as root in order to allow the installation to copy the files to the target locations). After this, all functions will be available each time Octave starts, without the need to tweak the search path. If you do not have root access, you can do a local install using: octave:1> pkg install -local queueing-1.2.8.tar.gz 3. Use the 'pkg list' command at the Octave prompt to check that the 'queueing' package has been succesfully installed; you should see something like: octave:1>pkg list queueing Package Name | Version | Installation directory --------------+---------+----------------------- queueing | 1.2.8 | /home/moreno/octave/queueing-1.2.8 4. Starting from version 1.1.1, 'queueing' is no longer automatically loaded on Octave start. To make the functions available for use, you need to issue the command octave:1>pkg load queueing at the Octave prompt. To automatically load 'queueing' each time Octave starts, you can add the command above to the startup script (usually, '~/.octaverc' on Unix systems). 5. To completely remove 'queueing' from your system, use the 'pkg uninstall' command: octave:1> pkg uninstall queueing 1.2 Manual installation ======================= If you want to manually install 'queueing' in a custom location, you can download the tarball and unpack it somewhere: tar xvfz queueing-1.2.8.tar.gz cd queueing-1.2.8/ Copy all '.m' files from the 'inst/' directory to some target location. Then, start Octave with the '-p' option to add the target location to the search path, so that Octave will find all 'queueing' functions automatically: octave -p _/path/to/queueing_ For example, if all 'queueing' m-files are in '/usr/local/queueing', you can start Octave as follows: octave -p _/usr/local/queueing_ If you want, you can add the following line to '~/.octaverc': addpath("_/path/to/queueing_"); so that the path '/path/to/queueing' is automatically added to the search path each time Octave is started, and you no longer need to specify the '-p' option on the command line. queueing/CITATION0000664000175000017500000000234114620404470013420 0ustar morenomorenoTo cite the Octave queueing package use: Moreno Marzolla, The qnetworks Toolbox: A Software Package for Queueing Networks Analysis. Khalid Al-Begain, Dieter Fiems and William J. Knottenbelt, Editors, Proceedings 17th International Conference on Analytical and Stochastic Modeling Techniques and Applications (ASMTA 2010) Cardiff, UK, June 14--16, 2010, volume 6148 of Lecture Notes in Computer Science, Springer, pp. 102--116, ISBN 978-3-642-13567-5, DOI 10.1007/978-3-642-13568-2_8 A BibTeX entry for LaTeX users is: @inproceedings{queueing, author = {Moreno Marzolla}, title = {The qnetworks Toolbox: A Software Package for Queueing Networks Analysis}, booktitle = {Analytical and Stochastic Modeling Techniques and Applications, 17th International Conference, ASMTA 2010, Cardiff, UK, June 14--16, 2010. Proceedings}, editor = {Khalid Al-Begain and Dieter Fiems and William J. Knottenbelt}, year = {2010}, publisher = {Springer}, series = {Lecture Notes in Computer Science}, volume = {6148}, pages = {102--116}, ee = {http://dx.doi.org/10.1007/978-3-642-13568-2_8}, doi = {10.1007/978-3-642-13568-2_8}, isbn = {978-3-642-13567-5} }