# HG changeset patch
# User mmarzolla
# Date 1389190722 0
# Node ID 80053b69b1a5241e06f2b5f9be726c368ad37cd3
# Parent 480c265afea42a08f174db61f8ea971261e31724
New functions added
diff -r 480c265afea4 -r 80053b69b1a5 main/queueing/doc/references.txi
--- a/main/queueing/doc/references.txi Tue Jan 07 21:23:53 2014 +0000
+++ b/main/queueing/doc/references.txi Wed Jan 08 14:18:42 2014 +0000
@@ -129,7 +129,11 @@
@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
+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
diff -r 480c265afea4 -r 80053b69b1a5 main/queueing/doc/singlestation.txi
--- a/main/queueing/doc/singlestation.txi Tue Jan 07 21:23:53 2014 +0000
+++ b/main/queueing/doc/singlestation.txi Wed Jan 08 14:18:42 2014 +0000
@@ -114,6 +114,10 @@
@GETHELP{qsmmm}
+@GETHELP{erlangb}
+
+@GETHELP{erlangc}
+
@noindent @strong{REFERENCES}
@noindent G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks
@@ -125,6 +129,10 @@
@auindex de Meer, H.
@auindex Trivedi, K.
+@noindent 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
+
+@auindex Zeng, G.
+
@c
@c M/M/inf
@c
@@ -156,11 +164,12 @@
@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 can be at most
-@math{k} jobs at any time. If a new request tries to join the system
-when there are already @math{K} other requests, the arriving 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
+In a @math{M/M/1/K} finite capacity system there is a single server
+and there can be at most @math{k \geq 1} jobs at any time (including
+the job currently in service). If a new request tries to join the
+system when there are already @math{K} other requests, the arriving
+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
@math{\lambda} and @math{\mu}.
@GETHELP{qsmm1k}
diff -r 480c265afea4 -r 80053b69b1a5 main/queueing/inst/erlangb.m
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main/queueing/inst/erlangb.m Wed Jan 08 14:18:42 2014 +0000
@@ -0,0 +1,116 @@
+## Copyright (C) 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{B} =} erlangb (@var{A}, @var{m})
+##
+## @cindex Erlang-B formula
+##
+## Compute the value of the Erlang-B formula @math{E_B(A, m)} giving the
+## probability that a request arriving to a pool of @math{m} identical
+## servers is rejected.
+##
+## @iftex
+##
+## @math{E_B(A, m)} is defined as:
+##
+## @tex
+## $$
+## E_B(A, m) = \displaystyle{{A^m \over m!} \left( \sum_{k=0}^m {A^k \over k!} \right) ^{-1}}
+## $$
+## @end tex
+##
+## @end iftex
+##
+## @strong{INPUTS}
+##
+## @table @var
+##
+## @item 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 m
+## Number of identical servers (integer, @math{m @geq{} 1}). Default @math{m = 1}
+##
+## @end table
+##
+## @strong{OUTPUTS}
+##
+## @table @var
+##
+## @item 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.
+##
+## @seealso{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 (June
+## 2003), Two common properties of the erlang-B function, erlang-C
+## function, and Engset blocking function, Elsevier Science, retrieved
+## 2011-02-03
+##
+## To improve numerical stability, the recursion is based on the inverse
+## of 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");
+
diff -r 480c265afea4 -r 80053b69b1a5 main/queueing/inst/erlangc.m
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main/queueing/inst/erlangc.m Wed Jan 08 14:18:42 2014 +0000
@@ -0,0 +1,102 @@
+## Copyright (C) 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{C} =} erlangc (@var{A}, @var{m})
+##
+## @cindex Erlang-C formula
+##
+## Compute the steady-state probability that a request finds all
+## @math{m} servers musy in a @math{M/M/m/\infty} queueing system with
+## @math{m} identical servers and infinite queue. This quantity is
+## also called Erlang-C formula @math{E_C(A, m)}.
+##
+## @iftex
+##
+## @math{E_C(A, m)} is defined as:
+##
+## @tex
+## $$
+## 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}}
+## $$
+## @end tex
+##
+## where @math{\rho = A / m = \lambda / (m \mu)}.
+##
+## @end iftex
+##
+## @strong{INPUTS}
+##
+## @table @var
+##
+## @item 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{0 < A < m}).
+##
+## @item m
+## Number of identical servers (integer, @math{m @geq{} 1}). Default @math{m = 1}
+##
+## @end table
+##
+## @strong{OUTPUTS}
+##
+## @table @var
+##
+## @item 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.
+##
+## @seealso{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");
diff -r 480c265afea4 -r 80053b69b1a5 main/queueing/inst/qnjackson.m
--- a/main/queueing/inst/qnjackson.m Tue Jan 07 21:23:53 2014 +0000
+++ b/main/queueing/inst/qnjackson.m Wed Jan 08 14:18:42 2014 +0000
@@ -21,89 +21,9 @@
## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnjackson (@var{lambda}, @var{S}, @var{P}, @var{m} )
## @deftypefnx {Function File} {@var{pr} =} qnjackson (@var{lambda}, @var{S}, @var{P}, @var{m}, @var{k})
##
-## @cindex open network, single class
-## @cindex Jackson network
-##
-## This function is deprecated. Please use @code{qnopensingle} instead.
-##
-## With three or four arguments, this function computes the steady-state
-## occupancy probabilities for a Jackson network. With five arguments,
-## this function computes the steady-state probability
-## @code{@var{pi}(j)} that there are @code{@var{k}(j)} requests at
-## service center @math{j}.
-##
-## This function solves a subset of Jackson networks, with the
-## following constraints:
-##
-## @itemize
-##
-## @item External arrival rates are load-independent.
-##
-## @item Service center @math{i} consists either of @code{@var{m}(i) @geq{}
-## 1} identical servers with individual average service time
-## @code{@var{S}(i)}, or of an Infinite Server (IS) node.
-##
-## @end itemize
-##
-## @strong{INPUTS}
-##
-## @table @var
-##
-## @item lambda
-## @code{@var{lambda}(i)} is
-## the external arrival rate to service center @math{i}. @var{lambda}
-## must be a vector of length @math{N}, @code{@var{lambda}(i) @geq{} 0}.
-##
-## @item S
-## @code{@var{S}(i)} is the average service time on service center @math{i}
-## @var{S} must be a vector of length @math{N}, @code{@var{S}(i)>0}.
+## This function is deprecated. Please use @code{qnos} instead.
##
-## @item P
-## @code{@var{P}(i,j)} is the probability
-## that a job which completes service at service center @math{i} proceeds
-## to service center @math{j}. @var{P} must be a matrix of size
-## @math{N \times N}.
-##
-## @item m
-## @code{@var{m}(i)} is the number of servers at center
-## @math{i}. If @code{@var{m}(i) < 1}, center @math{i} is an
-## infinite-server node. Otherwise, it is a regular FCFS queueing center with
-## @code{@var{m}(i)} servers. Default is 1.
-##
-## @item k
-## Compute the steady-state probability that there are @code{@var{k}(i)}
-## requests at service center @math{i}. @var{k} must have the same length
-## as @var{lambda}, with @code{@var{k}(i) @geq{} 0}.
-##
-## @end table
-##
-## @strong{OUTPUT}
-##
-## @table @var
-##
-## @item U
-## If @math{i} is a FCFS node, then
-## @code{@var{U}(i)} is the utilization of service center @math{i}.
-## If @math{i} is an IS node, then @code{@var{U}(i)} is the
-## @emph{traffic intensity} defined as @code{@var{X}(i)*@var{S}(i)}.
-##
-## @item R
-## @code{@var{R}(i)} is the average response time of service center @math{i}.
-##
-## @item Q
-## @code{@var{Q}(i)} is the average number of customers in service center
-## @math{i}.
-##
-## @item X
-## @code{@var{X}(i)} is the throughput of service center @math{i}.
-##
-## @item pr
-## @code{@var{pr}(i)} is the steady state probability
-## that there are @code{@var{k}(i)} requests at service center @math{i}.
-##
-## @end table
-##
-## @seealso{qnopen}
+## @seealso{qnos}
##
## @end deftypefn
@@ -115,7 +35,7 @@
if (!warned)
warned = true;
warning("qn:deprecated-function",
- "qnjackson is deprecated. Please use qnopensingle insgead");
+ "qnjackson is deprecated. Please use qnos insgead");
endif
if ( nargin < 3 || nargin > 5 )
print_usage();
@@ -194,35 +114,3 @@
endif
endfunction
-%!test
-%! # Test various error conditions
-%! fail( "qnjackson( [0.5 0.5], [0 1], [0 0; 0 0], [1 1])", "S must be" );
-%! fail( "qnjackson( [-1 1], [1 1], [0 0; 0 0], [1 1])", "lambda must be" );
-%! fail( "qnjackson( [0.5 0.5], [1 1], [1 1; 0 0], [1 1])", "P is not" );
-%! fail( "qnjackson( [0.5 0.5], [1 1], [1 0; -1 0], [1 1])", "P is not" );
-%! fail( "qnjackson( [0.5 0.5], [1 1 1], [0 0; 0 0], [1 1])", "lambda and S" );
-%! fail( "qnjackson( [0.5 0.5], [1 1], [0 0; 0 0], [1 1 1])", "m and lambda" );
-%! fail( "qnjackson( [0.5 0.5], [1 1], [0 0; 0 0], [1 1], [1 1 1])", "k must be" );
-%! fail( "qnjackson( [0.5 0.5], [1 1], [0 0; 0 0], [1 1], [1 -1])", "k must be" );
-%! fail( "qnjackson( [0 1], [2 2], [0 0.9; 0 0] )", "not ergodic" );
-
-%!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];
-%! k = [ 3 2 4 1 ];
-%! [U R Q X] = qnjackson( lambda, S, P, 1 );
-%! 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
-%! # 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];
-%! k = [ 3 2 4 1 ];
-%! p_i = qnjackson( lambda, S, P, 1, k );
-%! assert( p_i, [0.1024, 0.063, 0.0518, 0.16], 1e-4 );
diff -r 480c265afea4 -r 80053b69b1a5 main/queueing/inst/qsmmm.m
--- a/main/queueing/inst/qsmmm.m Tue Jan 07 21:23:53 2014 +0000
+++ b/main/queueing/inst/qsmmm.m Wed Jan 08 14:18:42 2014 +0000
@@ -1,4 +1,4 @@
-## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 Moreno Marzolla
+## Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Moreno Marzolla
##
## This file is part of the queueing toolbox.
##
@@ -22,7 +22,10 @@
##
## @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 service centers connected to a single FCFS queue.
+## 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 service centers connected to a single FCFS
+## queue.
##
## @iftex
## The steady-state probability @math{\pi_k} that there are @math{k}
@@ -93,7 +96,7 @@
## @var{lambda}, @var{mu} and @var{m} can be vectors of the same size. In this
## case, the results will be vectors as well.
##
-## @seealso{qsmm1,qsmminf,qsmmmk}
+## @seealso{erlangc,qsmm1,qsmminf,qsmmmk}
##
## @end deftypefn
@@ -106,38 +109,33 @@
endif
if ( nargin == 2 )
m = 1;
+ else
+ ( isnumeric(lambda) && isnumeric(mu) && isnumeric(m) ) || ...
+ error( "the parameters must be numeric vectors" );
endif
- ( isvector(lambda) && isvector(mu) && isvector(m) ) || ...
- error( "the parameters must be vectors" );
[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" );
- all( lambda < m .* mu ) || ...
- error( "Processing capacity exceeded" );
X = lambda;
U = rho = lambda ./ (m .* mu );
+ all( U < 1 ) || ...
+ error( "Processing capacity exceeded" );
Q = p0 = pm = 0*lambda;
for i=1:length(lambda)
-#{
- k=[0:m(i)-1];
- p0(i) = 1 / ( ...
- sum( (m(i)*rho(i)).^ k ./ factorial(k)) + ...
- (m(i)*rho(i))^m(i) / (factorial(m(i))*(1-rho(i))) ...
- );
-#}
p0(i) = 1 / ( ...
sumexpn( m(i)*rho(i), m(i)-1 ) + ...
expn(m(i)*rho(i), m(i))/(1-rho(i)) ...
);
- pm(i) = expn(m(i)*rho(i),m(i))*p0(i)/(1-rho(i));
endfor
+ pm = erlangc(lambda ./ mu, m);
Q = m .* rho .+ rho ./ (1-rho) .* pm;
R = Q ./ X;
endfunction