Mercurial > forge
changeset 11293:467b5626e121 octave-forge
Deprecating qnvisits
author | mmarzolla |
---|---|
date | Thu, 06 Dec 2012 13:06:43 +0000 |
parents | effd46c38bfe |
children | bd5d51e5d5ce |
files | main/queueing/doc/queueingnetworks.txi main/queueing/inst/dtmcisir.m main/queueing/inst/qnclosed.m main/queueing/inst/qnclosedgb.m main/queueing/inst/qncmmva.m main/queueing/inst/qncmvisits.m main/queueing/inst/qncsgb.m main/queueing/inst/qncsmvablo.m main/queueing/inst/qncsvisits.m main/queueing/inst/qnjackson.m main/queueing/inst/qnmarkov.m main/queueing/inst/qnmvablo.m main/queueing/inst/qnom.m main/queueing/inst/qnomvisits.m main/queueing/inst/qnopensingle.m main/queueing/inst/qnos.m main/queueing/inst/qnosvisits.m main/queueing/inst/qnsolve.m main/queueing/inst/qnvisits.m |
diffstat | 19 files changed, 793 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/main/queueing/doc/queueingnetworks.txi Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/doc/queueingnetworks.txi Thu Dec 06 13:06:43 2012 +0000 @@ -235,7 +235,7 @@ @iftex @tex $$\left\{\eqalign{V_j & = \sum_{i=1}^K V_i P_{i, j} \quad j=1, \ldots, K \cr - V_1 & = 1}\right. $$ + V_r & = 1 \quad \hbox{for a selected reference station $r$}}\right. $$ @end tex @end iftex @ifnottex @@ -248,16 +248,33 @@ | /___ | i=1 | -| V_1 = 1 +| V_r = 1 for a selected reference station r \ @end example @end ifnottex -@GETHELP{qnvisits} +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 need an additional constraint @math{V_r = +1}. This is equivalent to define station @math{r} as the +@emph{reference station} (the default is @math{r=1}, +@xref{doc-qncsvisits}). The choice of the reference station for closed +networks is extremely important, since it determines the performance +results of the whole network. First, the network throughput is set to +the throughput of the reference station. Second, when a job returns to +the reference station, it is assumed that the job completed its +activity cycle, and enters a new activity cycle. Therefore, the system +response time is also measured with respect to the reference station. +@GETHELP{qncsvisits} + +@GETHELP{qnosvisits} + +@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} @@ -292,10 +309,11 @@ @end example @end ifnottex -The visit ratios @math{V} can be computed with: +The visit ratios @math{V} using station 1 as the reference +station can be computed with: @example -@GETDEMO{qnvisits,1} +@GETDEMO{qncsvisits,1} @result{} V = 1.00000 0.30000 0.70000 @end example @@ -337,12 +355,12 @@ @math{V} as follows: @example -@GETDEMO{qnvisits,2} +@GETDEMO{qnosvisits,1} @result{} V = 5.0000 1.5000 2.5000 @end example -Function @command{qnvisits} expects a vector with @math{K} elements as a -second parameter, for open networks only. The vector contains the +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]}. @@ -829,17 +847,25 @@ @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, K, j=1, \ldots, K \cr - V_{s, 1} & = 1 \quad s=1, \ldots, K}\right. $$ +$$\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,...,K, j=1,...,K +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 while for open networks: +@noindent where @math{r_s} is the index of 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 referenc station per +class and set their visit ratios to 1. When multiple classes belong to +the same chain, then only a single constraint per chain must be given. + +For open networks the traffic equations are as follows: @iftex @tex @@ -859,6 +885,10 @@ \sum_s \sum_j \lambda_{s, j}} is the overall external arrival rate to the whole system, then @math{P_{0, s, j} = \lambda_{s, j} / \lambda}. +@GETHELP{qncmvisits} + +@GETHELP{qnomvisits} + @c @c Open Networks @c @@ -1269,8 +1299,8 @@ @end table We can compute @math{V_k} from the routing probability matrix -@math{P_{i, j}} using the @command{qnvisits} function -@pxref{doc-qnvisits}. We can analyze the network for a given +@math{P_{i, j}} using the @command{qncsvisits} function +@pxref{doc-qncsvisits}. We can analyze the network for a given population size @math{N} (for example, @math{N=10}) as follows: @example @@ -1278,7 +1308,7 @@ @kbd{N = 10;} @kbd{S = [1 2 0.8];} @kbd{P = [0 0.3 0.7; 1 0 0; 1 0 0];} -@kbd{V = qnvisits(P);} +@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 @@ -1361,14 +1391,14 @@ arrivals at centers 2 and 3. Similarly to closed networks, we first need to compute the visit -counts @math{V_k} to center @math{k}. Again, we use the -@command{qnvisits} function as follows: +counts @math{V_k} to center @math{k}. 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 = qnvisits(P, lambda)} +@kbd{V = qnosvisits(P, lambda)} @result{} V = 5.00000 1.50000 2.50000 @end group @end example
--- a/main/queueing/inst/dtmcisir.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/dtmcisir.m Thu Dec 06 13:06:43 2012 +0000 @@ -91,7 +91,7 @@ %! assert( max(s), 1 ); %! assert( min(s), 1 ); -## FIXME: (mosty) copied from qnvisits.m; use a better algorithm for SCC +## FIXME: (mosty) copied from qncmvisits.m; use a better algorithm for SCC ## (e.g., ## http://pmtksupport.googlecode.com/svn/trunk/gaimc1.0-graphAlgo/scomponents.m function s = __scc(G) @@ -111,7 +111,7 @@ endfor endfunction -## FIXME: (mosty) copied from qnvisits.m +## FIXME: (mosty) copied from qncmvisits.m function v = __dfs(G, s) assert( issquare(G) ); N = rows(G);
--- a/main/queueing/inst/qnclosed.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnclosed.m Thu Dec 06 13:06:43 2012 +0000 @@ -77,7 +77,7 @@ %! m = ones(size(S)); # All centers are single-server %! Z = 2; # External delay %! N = 15; # Maximum population to consider -%! V = qnvisits(P); # Compute number of visits from P +%! 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);
--- a/main/queueing/inst/qnclosedgb.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnclosedgb.m Thu Dec 06 13:06:43 2012 +0000 @@ -85,7 +85,7 @@ %! P = [0 0.3 0.7; 1 0 0; 1 0 0]; %! S = [1 0.6 0.2]; %! m = ones(1,3); -%! V = qnvisits(P); +%! V = qncsvisits(P); %! Nmax = 20; %! tol = 1e-5; # compensate for numerical errors %! ## Test case with Z>0 @@ -103,7 +103,7 @@ %! P = [0 0.3 0.7; 1 0 0; 1 0 0]; %! S = [1 0.6 0.2]; %! m = ones(1,3); -%! V = qnvisits(P); +%! V = qncsvisits(P); %! Nmax = 20; %! tol = 1e-5; # compensate for numerical errors %!
--- a/main/queueing/inst/qncmmva.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qncmmva.m Thu Dec 06 13:06:43 2012 +0000 @@ -99,7 +99,8 @@ ## @item P ## @code{@var{P}(r,i,s,j)} is the 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 this argument, +## as a class @math{s} job; the reference station for all jobs +## is considered station 1. @strong{If you pass argument @var{P}, ## class switching is allowed}, but you can not specify any external delay ## (i.e., @var{Z} must be zero). ## @@ -228,7 +229,7 @@ U = R = Q = X = zeros(C,K); ## 1. Compute visit counts - [V ch] = qnvisits(P); + [V ch] = qncmvisits(P); ## 2. Identify chains nch = max(ch); @@ -634,7 +635,7 @@ %! N = [40 4]; %! S = [ 5.0 .010 .035 .035 .035 .035; \ %! 10.0 .100 .035 .035 .035 .035 ]; -%! V = qnvisits(P); +%! V = qncmvisits(P); %! [U R Q X] = qncmmva(N, S, V, [-1 1 1 1 1 1]); %! # FIXME: The results below were computed with JMVA; the numbers %! # in the paper are different (wrong?!?)!! @@ -680,7 +681,7 @@ %! %! # Compute visits %! -%! V = qnvisits(P); +%! V = qncmvisits(P); %! %! # Define population and service times %! @@ -735,7 +736,6 @@ %! 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]; -%! V = qnvisits(P); %! [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 );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qncmvisits.m Thu Dec 06 13:06:43 2012 +0000 @@ -0,0 +1,349 @@ +## 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 <http://www.gnu.org/licenses/>. + +## -*- 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 to the service centers of a closed multiclass network. +## +## @strong{INPUTS} +## +## @table @var +## +## @item P +## @code{@var{P}(r,i,s,j)} is the 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 r +## @code{@var{r}(c)} is the index of class @math{c} reference station. +## The class @math{c} visit count to server @code{@var{r}(c)} is +## conventionally set to 1. The reference station serves two purposes: +## its throughput is assumed to be the system throughput, and a job +## returning to the reference station is assumed to have completed one +## cycle. Default is station 1 for all classes. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item V +## @code{@var{V}(c,i)} is the number of visits of class @math{c} +## requests at center @math{i}. Note that @code{@var{V}(c,@var{r}(c)) = +## 1}. +## +## @item ch +## @code{@var{ch}(c)} is the 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 <marzolla(at)cs.unibo.it> +## 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 of r are out of 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/cgi/viewcontent.cgi?article=1258&context=cstech +%! ## "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 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/cgi/viewcontent.cgi?article=1285&context=cstech +%! +%! 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/cgi/viewcontent.cgi?article=1285&context=cstech +%! +%! 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] ); + +%!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 = qncmvisits(P,lambda); +%! S = [2 1 2 1.8]; +%! m = [3 1 1 2]; +%! [U R Q X] = qnos( sum(lambda), S, V, m ); + +## 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 me 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 +
--- a/main/queueing/inst/qncsgb.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qncsgb.m Thu Dec 06 13:06:43 2012 +0000 @@ -230,7 +230,7 @@ %! P = [0 0.3 0.7; 1 0 0; 1 0 0]; %! S = [1 0.6 0.2]; %! m = ones(1,3); -%! V = qnvisits(P); +%! V = qncsvisits(P); %! Z = 2; %! Nmax = 20; %! tol = 1e-5; # compensate for numerical errors @@ -248,7 +248,7 @@ %!test %! P = [0 0.3 0.7; 1 0 0; 1 0 0]; %! S = [1 0.6 0.2]; -%! V = qnvisits(P); +%! V = qncsvisits(P); %! Nmax = 20; %! tol = 1e-5; # compensate for numerical errors %!
--- a/main/queueing/inst/qncsmvablo.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qncsmvablo.m Thu Dec 06 13:06:43 2012 +0000 @@ -125,7 +125,7 @@ z = ones(1,N); lambda = 0; ## Computation of the visit counts - v = qnvisits(P); + v = qncsvisits(P); D = S .* v; # Service demand ## Main loop for k=1:K @@ -193,7 +193,7 @@ %! P = [0 0.7 0.3; 1 0 0; 1 0 0]; %! K = 40; %! [U1 R1 Q1] = qncsmvablo( K, S, M, P ); -%! V = qnvisits(P); +%! V = qncsvisits(P); %! [U2 R2 Q2] = qncsmva( K, S, V ); %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qncsvisits.m Thu Dec 06 13:06:43 2012 +0000 @@ -0,0 +1,131 @@ +## 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 <http://www.gnu.org/licenses/>. + +## -*- 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. +## +## @strong{INPUTS} +## +## @table @var +## +## @item P +## Routing probability matrix. +## @code{@var{P}(i,j)} is the probability that a request which completed +## service at center @math{i} is routed to center @math{j}. For closed +## networks it must hold that @code{sum(@var{P},2)==1}. The routing +## graph myst be strongly connected, meaning that it must be possible to +## eventually reach each node starting from each node. +## +## @item r +## Index of the reference station; if omitted, it is assumed +## @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 @var +## +## @item V +## @code{@var{V}(i)} is the average number of visits to service center +## @math{i}, assuming center @math{r} as the reference station. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function V = qncsvisits( P, r ) + + if ( nargin < 1 || nargin > 2 ) + print_usage(); + endif + + ndims(P) == 2 && issquare(P) || \ + error("P must be a 2-dimensional square matrix"); + + [res err] = dtmcchkP(P); + (res>0) || \ + error( "P is not a transition probability matrix for closed networks" ); + + N = rows(P); + + if ( nargin < 2 ) + r = 1; + else + issclarar(r) || \ + error("r must be a scalar"); + + (r>=1 && r<=N) || \ + error("r must be an integer in [%d,%d]",1,N); + endif + + V = zeros(size(P)); + A = P-eye(N); + b = zeros(1,N); + 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)", "not a transition probability" ); +%! P = [1 0; 0.5 0]; +%! fail( "qncsvisits(P)", "not a transition probability" ); + +%!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) +
--- a/main/queueing/inst/qnjackson.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnjackson.m Thu Dec 06 13:06:43 2012 +0000 @@ -145,7 +145,7 @@ endif ## Compute the arrival rates using the traffic equation: - l = sum(lambda)*qnvisits( P, lambda ); + l = sum(lambda)*qnosvisits( P, lambda ); ## Check ergodicity for i=1:N if ( m(i)>0 && l(i)>=m(i)/S(i) )
--- a/main/queueing/inst/qnmarkov.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnmarkov.m Thu Dec 06 13:06:43 2012 +0000 @@ -328,7 +328,7 @@ %! C = [6 6 6]; %! S = [1 0.8 1.8]; %! N = 6; -%! [U1 R1 Q1 X1] = qnclosed( N, S, qnvisits(P) ); +%! [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 );
--- a/main/queueing/inst/qnmvablo.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnmvablo.m Thu Dec 06 13:06:43 2012 +0000 @@ -82,7 +82,7 @@ %! P = [0 0.7 0.3; 1 0 0; 1 0 0]; %! K = 40; %! [U1 R1 Q1] = qnmvablo( K, S, M, P ); -%! V = qnvisits(P); +%! V = qncsvisits(P); %! [U2 R2 Q2] = qnclosedsinglemva( K, S, V ); %! assert( U1, U2, 1e-5 ); %! assert( R1, R2, 1e-5 );
--- a/main/queueing/inst/qnom.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnom.m Thu Dec 06 13:06:43 2012 +0000 @@ -79,7 +79,7 @@ ## ## @end table ## -## @seealso{qnopen,qnos,qnvisits} +## @seealso{qnopen,qnos,qnomvisits} ## ## @end deftypefn
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnomvisits.m Thu Dec 06 13:06:43 2012 +0000 @@ -0,0 +1,112 @@ +## 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 <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{V} =} qnomvisits (@var{P}, @var{lambda}) +## +## Compute the average number of visits to the service centers of an open multiclass network. +## +## @strong{INPUTS} +## +## @table @var +## +## @item P +## @code{@var{P}(r,i,s,j)} is the 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 lambda +## @code{@var{lambda}(r,i)} is the arrival rate of class @math{r} +## requests to center @math{i}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item V +## @code{@var{V}(r,i)} is the number of visits of class @math{r} +## requests at center @math{i}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## 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 [C,K,C,K] matrix"); + + [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 +
--- a/main/queueing/inst/qnopensingle.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnopensingle.m Thu Dec 06 13:06:43 2012 +0000 @@ -82,7 +82,7 @@ %!test %! lambda=[1]; %! P=[0]; -%! V=qnvisits(P,lambda); +%! V=qnosvisits(P,lambda); %! S=[0.25]; %! [U1 R1 Q1 X1]=qnopensingle(sum(lambda),S,V); %! [U2 R2 Q2 X2]=qnmm1(lambda(1),1/S(1));
--- a/main/queueing/inst/qnos.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnos.m Thu Dec 06 13:06:43 2012 +0000 @@ -88,7 +88,7 @@ ## ## @end table ## -## @seealso{qnopen,qnclosed,qnvisits} +## @seealso{qnopen,qnclosed,qnosvisits} ## ## @end deftypefn @@ -189,7 +189,7 @@ %!test %! lambda=[1]; %! P=[0]; -%! V=qnvisits(P,lambda); +%! 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));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnosvisits.m Thu Dec 06 13:06:43 2012 +0000 @@ -0,0 +1,117 @@ +## 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 <http://www.gnu.org/licenses/>. + +## -*- 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{N} service centers. +## +## @strong{INPUTS} +## +## @table @var +## +## @item P +## @code{@var{P}(i,j)} is the probability that a request which completed +## service at center @math{i} is routed to center @math{j}. +## +## @item lambda +## @code{@var{lambda}(i)} is the external arrival rate to +## center @math{i}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item V +## @code{@var{V}(i)} is the average number of +## visits to server @math{i}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function V = qnosvisits( P, lambda ) + + if ( nargin != 2 ) + print_usage(); + endif + + ndims(P) == 2 && issquare(P) || \ + error("P must be a square matrix"); + + N = size(P,1); + V = zeros(N,N); + + ## + ## Open network + ## + all(P(:)>=0) && all( sum(P,2)<=1+1e-5 ) || \ + error( "P is not a transition probability matrix for open networks" ); + + ( isvector(lambda) && length(lambda) == N ) || \ + error( "lambda must be a vector with %d elements", N ); + all( lambda>= 0 ) || \ + error( "lambda contains negative values" ); + + lambda = lambda(:)'; + + A = eye(N)-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 +%! P = [1 0; 0 1]; lambda=[0 -1]; +%! fail( "qnosvisits(P,lambda)", "contains negative" ); + +%!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 ); +
--- a/main/queueing/inst/qnsolve.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnsolve.m Thu Dec 06 13:06:43 2012 +0000 @@ -754,7 +754,7 @@ %! 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, qnvisits(P,lambda) ); +%! [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 );
--- a/main/queueing/inst/qnvisits.m Wed Dec 05 22:49:14 2012 +0000 +++ b/main/queueing/inst/qnvisits.m Thu Dec 06 13:06:43 2012 +0000 @@ -43,8 +43,8 @@ ## networks, @code{@var{lambda}(i)} is the external arrival rate to ## center @math{i}. For multiple class networks, ## @code{@var{lambda}(r,i)} is the arrival rate of class @math{r} -## requests to center @math{i}. If this parameter is omitted, the -## network is assumed to be closed. +## requests to center @math{i}. If this function is called with a single +## argument, the network is assumed to be closed. ## ## @end table ## @@ -54,9 +54,10 @@ ## ## @item V ## For single class networks, @code{@var{V}(i)} is the average number of -## visits to server @math{i}. For multiple class networks, -## @code{@var{V}(r,i)} is the class @math{r} visit ratio at center -## @math{i}. +## visits to server @math{i}, assuming center 1 as the reference station +## (i.e., @code{@var{V}(1) = 1}). For multiple class networks, +## @code{@var{V}(r,i)} is the number of visits of class @math{r} +## requests at center @math{i}. ## ## @item ch ## (For closed networks only). @code{@var{ch}(c)} is the chain number @@ -74,6 +75,13 @@ function [V ch] = qnvisits( P, varargin ) + persistent warned = false; + if (!warned) + warned = true; + warning("qn:deprecated-function", + "qnvisits is deprecated. Please use one of qncsvisits, qnosvisits, qncmvisits, qnomvisits instead"); + endif + if ( nargin < 1 || nargin > 2 ) print_usage(); endif