Diff of the two buildlogs: -- --- b1/build.log 2024-10-06 10:02:53.466433333 +0000 +++ b2/build.log 2024-10-06 10:04:45.309667126 +0000 @@ -1,6 +1,6 @@ I: pbuilder: network access will be disabled during build -I: Current time: Sat Oct 5 21:59:59 -12 2024 -I: pbuilder-time-stamp: 1728208799 +I: Current time: Sun Nov 9 06:25:54 +14 2025 +I: pbuilder-time-stamp: 1762619154 I: Building the build Environment I: extracting base tarball [/var/cache/pbuilder/trixie-reproducible-base.tgz] I: copying local configuration @@ -31,53 +31,85 @@ dpkg-source: info: applying texinfo-absolute-path.patch I: Not using root during the build. I: Installing the build-deps -I: user script /srv/workspace/pbuilder/8936/tmp/hooks/D02_print_environment starting +I: user script /srv/workspace/pbuilder/2824/tmp/hooks/D01_modify_environment starting +debug: Running on infom08-i386. +I: Changing host+domainname to test build reproducibility +I: Adding a custom variable just for the fun of it... +I: Changing /bin/sh to bash +'/bin/sh' -> '/bin/bash' +lrwxrwxrwx 1 root root 9 Nov 8 16:26 /bin/sh -> /bin/bash +I: Setting pbuilder2's login shell to /bin/bash +I: Setting pbuilder2's GECOS to second user,second room,second work-phone,second home-phone,second other +I: user script /srv/workspace/pbuilder/2824/tmp/hooks/D01_modify_environment finished +I: user script /srv/workspace/pbuilder/2824/tmp/hooks/D02_print_environment starting I: set - BUILDDIR='/build/reproducible-path' - BUILDUSERGECOS='first user,first room,first work-phone,first home-phone,first other' - BUILDUSERNAME='pbuilder1' - BUILD_ARCH='i386' - DEBIAN_FRONTEND='noninteractive' - DEB_BUILD_OPTIONS='buildinfo=+all reproducible=+all parallel=6 ' - DISTRIBUTION='trixie' - HOME='/root' - HOST_ARCH='i386' + BASH=/bin/sh + BASHOPTS=checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath + BASH_ALIASES=() + BASH_ARGC=() + BASH_ARGV=() + BASH_CMDS=() + BASH_LINENO=([0]="12" [1]="0") + BASH_LOADABLES_PATH=/usr/local/lib/bash:/usr/lib/bash:/opt/local/lib/bash:/usr/pkg/lib/bash:/opt/pkg/lib/bash:. + BASH_SOURCE=([0]="/tmp/hooks/D02_print_environment" [1]="/tmp/hooks/D02_print_environment") + BASH_VERSINFO=([0]="5" [1]="2" [2]="32" [3]="1" [4]="release" [5]="i686-pc-linux-gnu") + BASH_VERSION='5.2.32(1)-release' + BUILDDIR=/build/reproducible-path + BUILDUSERGECOS='second user,second room,second work-phone,second home-phone,second other' + BUILDUSERNAME=pbuilder2 + BUILD_ARCH=i386 + DEBIAN_FRONTEND=noninteractive + DEB_BUILD_OPTIONS='buildinfo=+all reproducible=+all parallel=5 ' + DIRSTACK=() + DISTRIBUTION=trixie + EUID=0 + FUNCNAME=([0]="Echo" [1]="main") + GROUPS=() + HOME=/root + HOSTNAME=i-capture-the-hostname + HOSTTYPE=i686 + HOST_ARCH=i386 IFS=' ' - INVOCATION_ID='9eccf78273644622840180ca716593ca' - LANG='C' - LANGUAGE='en_US:en' - LC_ALL='C' - LD_LIBRARY_PATH='/usr/lib/libeatmydata' - LD_PRELOAD='libeatmydata.so' - MAIL='/var/mail/root' - OPTIND='1' - PATH='/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' - PBCURRENTCOMMANDLINEOPERATION='build' - PBUILDER_OPERATION='build' - PBUILDER_PKGDATADIR='/usr/share/pbuilder' - PBUILDER_PKGLIBDIR='/usr/lib/pbuilder' - PBUILDER_SYSCONFDIR='/etc' - PPID='8936' - PS1='# ' - PS2='> ' + INVOCATION_ID=e81f92fdfcc4456db5188ad0d5dbfadb + LANG=C + LANGUAGE=de_CH:de + LC_ALL=C + LD_LIBRARY_PATH=/usr/lib/libeatmydata + LD_PRELOAD=libeatmydata.so + MACHTYPE=i686-pc-linux-gnu + MAIL=/var/mail/root + OPTERR=1 + OPTIND=1 + OSTYPE=linux-gnu + PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path + PBCURRENTCOMMANDLINEOPERATION=build + PBUILDER_OPERATION=build + PBUILDER_PKGDATADIR=/usr/share/pbuilder + PBUILDER_PKGLIBDIR=/usr/lib/pbuilder + PBUILDER_SYSCONFDIR=/etc + PIPESTATUS=([0]="0") + POSIXLY_CORRECT=y + PPID=2824 PS4='+ ' - PWD='/' - SHELL='/bin/bash' - SHLVL='2' - SUDO_COMMAND='/usr/bin/timeout -k 18.1h 18h /usr/bin/ionice -c 3 /usr/bin/nice /usr/sbin/pbuilder --build --configfile /srv/reproducible-results/rbuild-debian/r-b-build.8Pg3iuZk/pbuilderrc_o5SO --distribution trixie --hookdir /etc/pbuilder/first-build-hooks --debbuildopts -b --basetgz /var/cache/pbuilder/trixie-reproducible-base.tgz --buildresult /srv/reproducible-results/rbuild-debian/r-b-build.8Pg3iuZk/b1 --logfile b1/build.log octave-queueing_1.2.8-1.dsc' - SUDO_GID='111' - SUDO_UID='104' - SUDO_USER='jenkins' - TERM='unknown' - TZ='/usr/share/zoneinfo/Etc/GMT+12' - USER='root' - _='/usr/bin/systemd-run' + PWD=/ + SHELL=/bin/bash + SHELLOPTS=braceexpand:errexit:hashall:interactive-comments:posix + SHLVL=3 + SUDO_COMMAND='/usr/bin/timeout -k 24.1h 24h /usr/bin/ionice -c 3 /usr/bin/nice -n 11 /usr/bin/unshare --uts -- /usr/sbin/pbuilder --build --configfile /srv/reproducible-results/rbuild-debian/r-b-build.8Pg3iuZk/pbuilderrc_67MY --distribution trixie --hookdir /etc/pbuilder/rebuild-hooks --debbuildopts -b --basetgz /var/cache/pbuilder/trixie-reproducible-base.tgz --buildresult /srv/reproducible-results/rbuild-debian/r-b-build.8Pg3iuZk/b2 --logfile b2/build.log octave-queueing_1.2.8-1.dsc' + SUDO_GID=111 + SUDO_UID=104 + SUDO_USER=jenkins + TERM=unknown + TZ=/usr/share/zoneinfo/Etc/GMT-14 + UID=0 + USER=root + _='I: set' I: uname -a - Linux infom07-i386 6.1.0-26-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.112-1 (2024-09-30) x86_64 GNU/Linux + Linux i-capture-the-hostname 6.10.6+bpo-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.10.6-1~bpo12+1 (2024-08-26) x86_64 GNU/Linux I: ls -l /bin - lrwxrwxrwx 1 root root 7 Aug 4 21:30 /bin -> usr/bin -I: user script /srv/workspace/pbuilder/8936/tmp/hooks/D02_print_environment finished + lrwxrwxrwx 1 root root 7 Aug 4 2024 /bin -> usr/bin +I: user script /srv/workspace/pbuilder/2824/tmp/hooks/D02_print_environment finished -> Attempting to satisfy build-dependencies -> Creating pbuilder-satisfydepends-dummy package Package: pbuilder-satisfydepends-dummy @@ -701,7 +733,7 @@ Get: 576 http://deb.debian.org/debian trixie/main i386 texlive-base all 2024.20240829-2 [22.7 MB] Get: 577 http://deb.debian.org/debian trixie/main i386 texlive-font-utils all 2024.20240829-1 [6982 kB] Get: 578 http://deb.debian.org/debian trixie/main i386 texlive-plain-generic all 2024.20240829-1 [28.6 MB] -Fetched 313 MB in 8s (38.3 MB/s) +Fetched 313 MB in 4s (81.0 MB/s) debconf: delaying package configuration, since apt-utils is not installed Selecting previously unselected package readline-common. (Reading database ... (Reading database ... 5% (Reading database ... 10% (Reading database ... 15% (Reading database ... 20% (Reading database ... 25% (Reading database ... 30% (Reading database ... 35% (Reading database ... 40% (Reading database ... 45% (Reading database ... 50% (Reading database ... 55% (Reading database ... 60% (Reading database ... 65% (Reading database ... 70% (Reading database ... 75% (Reading database ... 80% (Reading database ... 85% (Reading database ... 90% (Reading database ... 95% (Reading database ... 100% (Reading database ... 19774 files and directories currently installed.) @@ -3086,7 +3118,11 @@ Building tag database... -> Finished parsing the build-deps I: Building the package -I: Running cd /build/reproducible-path/octave-queueing-1.2.8/ && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games" HOME="/nonexistent/first-build" dpkg-buildpackage -us -uc -b && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games" HOME="/nonexistent/first-build" dpkg-genchanges -S > ../octave-queueing_1.2.8-1_source.changes +I: user script /srv/workspace/pbuilder/2824/tmp/hooks/A99_set_merged_usr starting +Not re-configuring usrmerge for trixie +I: user script /srv/workspace/pbuilder/2824/tmp/hooks/A99_set_merged_usr finished +hostname: Name or service not known +I: Running cd /build/reproducible-path/octave-queueing-1.2.8/ && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path" HOME="/nonexistent/second-build" dpkg-buildpackage -us -uc -b && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path" HOME="/nonexistent/second-build" dpkg-genchanges -S > ../octave-queueing_1.2.8-1_source.changes dpkg-buildpackage: info: source package octave-queueing dpkg-buildpackage: info: source version 1.2.8-1 dpkg-buildpackage: info: source distribution unstable @@ -3487,6 +3523,132 @@ Checking package... Run the unit tests... Checking m files ... +[inst/ctmcfpt.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcfpt.m +***** 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) ); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/qncsbsb.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsbsb.m +***** 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 +2 tests, 2 passed, 0 known failure, 0 skipped +[inst/qncsvisits.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsvisits.m +***** 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) +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/dtmcchkP.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcchkP.m +***** 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 ); +5 tests, 5 passed, 0 known failure, 0 skipped +[inst/qnopen.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnopen.m +***** 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 ); +2 tests, 2 passed, 0 known failure, 0 skipped [inst/qnosvisits.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnosvisits.m ***** test @@ -3516,168 +3678,312 @@ m = [3 1 1 2]; [U R Q X] = qnos( sum(lambda), S, V, m ) 2 tests, 2 passed, 0 known failure, 0 skipped -[inst/qncmmva.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmmva.m +[inst/qncspb.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncspb.m ***** test - S = [1 1 2; 1 1 1]; - V = [1 1 1; 1 1 1]; - N = [1 1]; - m = [1 1 2]; - fail( "qncmmva(N)" ); - fail( "qncmmva(N,S,V,m)", "independent" ); - S = [0 0 0; 1 1 1]; - fail( "qncmmva(N,S,V,m)", "must contain at least" ); - S = [1 2 3; 1 2 3]; - N = [1 1]; - V = zeros(3,2,3); - fail( "qncmmva(N,S,V)", "size mismatch" ); - fail( "qncmmva([0.3 1], [1 2; 3 4])", "integer"); - fail( "qncmmva([-1 0], [1 2; 3 4])", "nonnegative"); + 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 - S = [1 1 1; 1 1 1]; - N = [0 0]; - [U R Q X] = qncmmva(N, S); - assert( U, 0*S ); - assert( R, 0*S ); - assert( Q, 0*S ); - assert( X, 0*S ); + # 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 1 1; 1 1 1]; - V = [1 1 1; 1 1 1]; - N = [0 0]; - m = [2 2 2]; - [U R Q X] = qncmmva(N, S, V, m); - assert( U, 0*S ); - assert( R, 0*S ); - assert( Q, 0*S ); - assert( X, 0*S ); + 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 +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/qnos.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnos.m ***** test - S = [ 1/10 1/3; 2/5 1 ]; - V = [ 10 9; 5 4 ]; - N = [ 1 1 ]; - [U R Q X] = qncmmva(N,S,V); - assert( Q, [ 4/19 15/19; 5/19 14/19 ], 1e-3 ); - assert( R .* V, [ 4/3 5; 5/2 7 ], 1e-3 ); - assert( diag( X ./ V )', [ 3/19 2/19 ], 1e-3 ); - assert( all(U(:)<=1) ); - assert( Q, R.*X, 1e-5 ); # Little's Law + 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 - S = [0.02 0.2 0.4 0.6]; - V = [1 0.4 0.2 0.1]; - N = [6]; - [U R Q X] = qncmmva( N, S, V ); - assert( Q, [0.244 2.261 2.261 1.234], 1e-3 ); - assert( R, [0.025 0.570 1.140 1.244], 1e-3 ); - assert( X, [9.920 3.968 1.984 0.992], 1e-3 ); - assert( U, [0.198 0.794 0.794 0.595], 1e-3 ); + # 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 - S = [1 0 .025; 0 15 .5]; - V = [1 0 1; 0 1 1]; - N = [2 1]; - m = [-1 -1 1]; - [U R Q X] = qncmmva(N,S,V,m); - assert( R(1,1), 1, 1e-3 ); - assert( R(2,2), 15, 1e-3 ); - assert( R(1,3), .027, 1e-3 ); - assert( R(2,3), .525, 1e-3 ); - assert( X(1,1)+X(1,2), 1.949, 1e-3 ); - assert( X(2,1)+X(2,2), 0.064, 1e-3 ); - assert( sum(Q,1), [1.949, .966, .085], 1e-3 ); - assert( all(U(:,3)<=1) ); - assert( Q, R.*X, 1e-5 ); # Little's Law + # 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 - 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); - # I replaced 14.3->14.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 ); + 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 ); +***** 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 ); +6 tests, 6 passed, 0 known failure, 0 skipped +[inst/qsmm1k.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmm1k.m +***** 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)); +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/engset.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/engset.m +***** 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"); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/qnom.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnom.m +***** 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 - 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) ); + # 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 - 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 ); + # 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 ); ***** 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 + 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"); +5 tests, 5 passed, 0 known failure, 0 skipped +[inst/qncmvisits.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmvisits.m ***** test - C = 2; - K = 6; + + ## Closed, multiclass network + + C = 2; K = 3; 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 ]; + 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); - [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 + for c=1:C + for k=1:K + assert(V(c,k), sum(sum(V .* P(:,:,c,k))), 1e-5); + endfor + endfor ***** test - C = 2; # two classes - K = 4; # four servers - C = 2; K = 4; - P = zeros(C,K,C,K); - S = zeros(C,K); - # Routing + ## 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; @@ -3690,53 +3996,24 @@ P(2,1,2,4) = .49; P(2,3,2,1) = 1; P(2,4,2,1) = 1; - - # Compute visits - 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 - # Define population and service times + ## 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/ - 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 ); -***** 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 ); -***** 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 -***** test C = 2; K = 3; S = [.01 .07 .10; ... - .05 .07 .10 ]; + .05 0.7 .10 ]; P = zeros(C,K,C,K); P(1,1,1,2) = .7; P(1,1,1,3) = .2; @@ -3744,132 +4021,287 @@ 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; + 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]; - [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 ); + 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 - 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 ); + + ## 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 - 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 ); -***** 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); + + ## 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,[3 3]); # reference station is station 3 - N = [15 5]; - m = [-1 -1 1]; - [U R Q X] = qncmmva(N,S,V,m) -***** demo - C = 2; K = 3; - S = [.01 .07 .10; ... - .05 .07 .10 ]; + 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) = .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)'; + 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] ); +***** 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] ); +9 tests, 9 passed, 0 known failure, 0 skipped +[inst/erlangc.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/erlangc.m +***** test + fail("erlangc('foo',1)", "positive"); + fail("erlangc(1,'bar')", "positive"); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/qnmarkov.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnmarkov.m +***** 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 ); +***** 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 ); +***** ## + 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 ); +***** 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 ); +***** 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 ); +***** 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 ); +5 tests, 5 passed, 0 known failure, 0 skipped +[inst/qnmix.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnmix.m +***** 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 +4 tests, 4 passed, 0 known failure, 0 skipped +[inst/erlangb.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/erlangb.m +***** 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"); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/qnomvisits.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnomvisits.m +***** 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 - 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"); -17 tests, 17 passed, 0 known failure, 0 skipped +***** 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); +3 tests, 3 passed, 0 known failure, 0 skipped [inst/qnsolve.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnsolve.m ***** test @@ -3982,17 +4414,623 @@ N = [ 2 1 ]; [U R Q X] = qnsolve( "closed", N, QQ, V ); 9 tests, 9 passed, 0 known failure, 0 skipped -[inst/erlangb.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/erlangb.m +[inst/ctmcisir.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcisir.m ***** 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"); + 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 ); +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/qncsgb.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsgb.m +***** test + fail( "qncsgb( 1, [] )", "vector" ); + fail( "qncsgb( 1, [0 -1])", "nonnegative" ); + fail( "qncsgb( 0, [1 2] )", "> 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 +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/qsammm.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsammm.m +***** test + [U R Q X] = qsammm( 73,[10,15,20,20,25] ); + assert( U, 0.81, 1e-2 ); + assert( Q, 6.5278, 1e-4 ); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/qsmm1.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmm1.m +***** 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)); +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/ctmcmtta.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcmtta.m +***** test + Q = [0 1 0; 1 0 1; 0 1 0 ]; Q -= diag( sum(Q,2) ); + fail( "ctmcmtta(Q,[1 0 0])", "no absorbing"); +***** test + Q = [0 1 0; 1 0 1; 0 0 0; 0 0 0 ]; + fail( "ctmcmtta(Q,[1 0 0])", "square matrix"); +***** test + Q = [0 1 0; 1 0 1; 0 0 0 ]; + fail( "ctmcmtta(Q,[1 0 0])", "infinitesimal"); +***** 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) ); + assert( ctmcmtta( Q,[0 0 0 1] ), 0 ); # state 4 is absorbing +***** test + Q = [-1 1; 0 0]; + assert( ctmcmtta( Q, [0 1] ), 0 ); # state 2 is absorbing + assert( ctmcmtta( Q, [1 0] ), 1 ); # the result has been computed by hand +***** demo + mu = 0.01; + death = [ 3 4 5 ] * mu; + birth = 0*death; + Q = ctmcbd(birth,death); + t = ctmcmtta(Q,[0 0 0 1]) +***** demo + N = 100; + birth = death = ones(1,N-1); birth(1) = death(N-1) = 0; + Q = diag(birth,1)+diag(death,-1); + Q -= diag(sum(Q,2)); + t = zeros(1,N/2); + initial_state = 1:(N/2); + for i=initial_state + p = zeros(1,N); p(i) = 1; + t(i) = ctmcmtta(Q,p); + endfor + plot(initial_state,t,"+"); + xlabel("Initial state"); + ylabel("MTTA"); +5 tests, 5 passed, 0 known failure, 0 skipped +[inst/qncsmvablo.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsmvablo.m +***** 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 ); +5 tests, 5 passed, 0 known failure, 0 skipped +[inst/dtmcisir.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcisir.m +***** 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 ); +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/qnosbsb.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnosbsb.m +***** 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 ); +2 tests, 2 passed, 0 known failure, 0 skipped +[inst/qnmknode.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnmknode.m +***** test + fail( "qnmknode( 'pippo', 1 )", "must be one" ); + fail( "qnmknode( '-/g/1-ps', 1, 1, 1)", "Invalid call" ); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/ctmctaexps.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmctaexps.m +***** 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"); +***** 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"); 1 test, 1 passed, 0 known failure, 0 skipped +[inst/dtmcfpt.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcfpt.m +***** 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 ); +***** 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 +***** 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 ); +6 tests, 6 passed, 0 known failure, 0 skipped +[inst/qncmmvabs.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmmvabs.m +***** 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; +2 tests, 2 passed, 0 known failure, 0 skipped +[inst/ctmc.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmc.m +***** test + Q = [-1 1 0 0; 2 -3 1 0; 0 2 -3 1; 0 0 2 -2]; + q = ctmc(Q); + assert( q*Q, 0*q, 1e-5 ); + assert( q, [8/15 4/15 2/15 1/15], 1e-5 ); +***** test + fail( "ctmc([1 1; 1 1])", "infinitesimal" ); + fail( "ctmc([1 1 1; 1 1 1])", "square" ); +***** test + Q = [0 0 0; ... + 0 -1 1; ... + 0 1 -1]; + q = ctmc(Q); + assert( q*Q, 0*q, 1e-5 ); + assert( q, [ 0 0.5 0.5 ], 1e-5 ); +***** test + lambda = 1; + mu = 2; + Q = [ -lambda lambda 0 0 ; ... + mu -(lambda+mu) lambda 0 ; ... + 0 mu -(lambda+mu) lambda ; ... + 0 0 mu -mu ]; + q = ctmc(Q); + assert( q, [8/15 4/15 2/15 1/15], 1e-5 ); +***** test + Q = [ -1 0.4 0.6 0 0 0; ... + 2 -3 0 0.4 0.6 0; ... + 3 0 -4 0 0.4 0.6; ... + 0 2 0 -2 0 0; ... + 0 3 2 0 -5 0; ... + 0 0 3 0 0 -3 ]; + q = ctmc(Q); + assert( q, [0.6578 0.1315 0.1315 0.0263 0.0263 0.0263], 1e-4 ); +***** test + Q = [-1 1 0 0 0 0 0; ... + 0 -3 1 0 2 0 0; ... + 0 0 -3 1 0 2 0; ... + 0 0 0 -2 0 0 2; ... + 2 0 0 0 -3 1 0; ... + 0 2 0 0 0 -3 1; ... + 0 0 2 0 0 0 -2 ]; + q = ctmc(Q); + assert( q, [0.2192 0.1644 0.1507 0.0753 0.1096 0.1370 0.1438], 1e-4 ); +***** test + a = 0.2; + b = 0.8; + Q = [-a a; b -b]; + qlim = ctmc(Q); + q = ctmc(Q, 100, [1 0]); + assert( qlim, q, 1e-5 ); +***** test + ll = 0.1; + mu = 100; + eta = 5; + Q = zeros(9,9); + ## 6--1, 7=sleep2 8=sleep1 9=crash + Q(6,5) = 6*ll; + Q(5,4) = 5*ll; + Q(4,3) = 4*ll; + Q(3,2) = 3*ll; + Q(2,1) = 2*ll; + Q(2,7) = mu; + Q(1,9) = ll; + Q(1,8) = mu; + Q(8,9) = ll; + Q(7,8) = 2*ll; + Q(7,6) = eta; + Q(8,6) = eta; + Q -= diag(sum(Q,2)); + q0 = zeros(1,9); q0(6) = 1; + q = ctmc(Q,10,q0); + assert( q(9), 0.000504, 1e-6 ); + q = ctmc(Q,2,q0); + assert( q, [3.83e-7 1.938e-4 0.0654032 0.2216998 0.4016008 0.3079701 0.0030271 0.0000998 5e-6], 1e-5 ); + # Compute probability that no shuttle needs to leave during 10 years + Q(7,:) = Q(8,:) = 0; # make states 7 and 8 absorbing + q = ctmc(Q,10,q0); + assert( 1-sum(q(7:9)), 0.3901, 1e-4 ); +***** demo + Q = [ -1 1; ... + 1 -1 ]; + q = ctmc(Q) +***** demo + a = 0.2; + b = 0.15; + Q = [ -a a; b -b]; + T = linspace(0,14,50); + pp = zeros(2,length(T)); + for i=1:length(T) + pp(:,i) = ctmc(Q,T(i),[1 0]); + endfor + ss = ctmc(Q); # compute steady state probabilities + plot( T, pp(1,:), "b;p_0(t);", "linewidth", 2, ... + T, ss(1)*ones(size(T)), "b;Steady State;", ... + T, pp(2,:), "r;p_1(t);", "linewidth", 2, ... + T, ss(2)*ones(size(T)), "r;Steady State;" ); + xlabel("Time"); + legend("boxoff"); +***** test + sec = 1; + min = 60*sec; + hour = 60*min; + ## the state space enumeration is {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); + assert( p, [0.9983916, 0.000002995, 0.0000066559, 0.00159742, 0.0000012779], 1e-6 ); + Q(3,:) = Q(5,:) = 0; # make states 3 and 5 absorbing + p0 = [1 0 0 0 0]; + MTBF = ctmcmtta(Q, p0) / hour; + assert( fix(MTBF), 24857); +***** demo + ## + ## The code below is used in the paper: "M. Marzolla, + ## "A GNU Octave package for Queueing Networks and Markov Chains analysis" + ## (submitted to the ACM Transactions on Mathematical Software) + ## to analyze the reliability model from Figure 2. The model + ## has been originally described in the paper: + ## + ## David I. Heimann, Nitin Mittal, Kishor S. Trivedi, "Availability + ## and Reliability Modeling for Computer Systems", + ## Marshall C. Yovits (Ed.), Advances in Computers, Elsevier, Volume 31, + ## 1990, Pages 175-233, ISSN 0065-2458, ISBN 9780120121311, DOI + ## https://doi.org/10.1016/S0065-2458(08)60154-0. sep 1989, section + ## 2.5. + + mm = 60; hh = 60*mm; dd = 24*hh; yy = 365*dd; + a = 1/(10*mm); # 1/a = duration of reboot (10 min) + b = 1/30; # 1/b = reconfiguration time (30 sec) + g = 1/(5000*hh); # 1/g = processor MTTF (5000 h) + d = 1/(4*hh); # 1/d = processor MTTR (4 h) + c = 0.9; # recovery probability + [TWO,RC,RB,ONE,ZERO] = deal(1,2,3,4,5); + ## 2 RC RB 1 0 + Q = [ -2*g 2*c*g 2*(1-c)*g 0 0; ... # 2 + 0 -b 0 b 0; ... # RC + 0 0 -a a 0; ... # RB + d 0 0 -(g+d) g; ... # 1 + 0 0 0 d -d]; # 0 + p = ctmc(Q); + + disp("minutes/year spent in RC"); + p(RC)*yy/mm # minutes/year spent in RC + disp("minutes/year spent in RB"); + p(RB)*yy/mm # minutes/year spent in RB + disp("minutes/year spent in 0"); + p(ZERO)*yy/mm # minutes/year spent in 0 + + Q(ZERO,:) = Q(RB,:) = 0; # make states {0, RB} absorbing + p0 = [ 1 0 0 0 0 ] ; # initial state occupancy probabiliies + disp("MTBF (years)"); + MTBF = ctmcmtta(Q, p0) / yy # MTBF (years) +9 tests, 9 passed, 0 known failure, 0 skipped [inst/qncsmvald.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsmvald.m ***** test @@ -4051,28 +5089,6 @@ assert( Q1, Q2, 1e-3 ); assert( X1, X2, 1e-3 ); 4 tests, 4 passed, 0 known failure, 0 skipped -[inst/ctmcbd.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcbd.m -***** 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 ); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/dtmcexps.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcexps.m -***** 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 ); -2 tests, 2 passed, 0 known failure, 0 skipped [inst/dtmcmtta.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcmtta.m ***** test @@ -4173,822 +5189,19 @@ t = dtmcmtta(P); assert( t, [6 5 6 5 0 5 6 5 6], 10*eps ); 5 tests, 5 passed, 0 known failure, 0 skipped -[inst/qncmbsb.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmbsb.m -***** 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"); -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qnosbsb.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnosbsb.m -***** 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 ); -2 tests, 2 passed, 0 known failure, 0 skipped -[inst/qnmarkov.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnmarkov.m -***** 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 ); -***** 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 ); -***** ## - 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 ); -***** 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 ); -***** 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 ); -***** 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 ); -5 tests, 5 passed, 0 known failure, 0 skipped -[inst/qnosaba.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnosaba.m -***** 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 ); -2 tests, 2 passed, 0 known failure, 0 skipped -[inst/qncsconv.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsconv.m -***** 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 ); -***** 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 -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qnopen.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnopen.m -***** 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 ); -2 tests, 2 passed, 0 known failure, 0 skipped -[inst/qncsmva.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsmva.m -***** 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" ); -***** 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]); -***** 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 ); -***** 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)"); -9 tests, 9 passed, 0 known failure, 0 skipped -[inst/qncmaba.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmaba.m -***** 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"); -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qnos.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnos.m -***** 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 ); -***** 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 ); -6 tests, 6 passed, 0 known failure, 0 skipped -[inst/qncspb.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncspb.m -***** 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 -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qnomvisits.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnomvisits.m -***** 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); -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qsmmmk.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmmmk.m -***** 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)); -7 tests, 7 passed, 0 known failure, 0 skipped -[inst/qncsconvld.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsconvld.m -***** 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 ); -5 tests, 5 passed, 0 known failure, 0 skipped -[inst/dtmcbd.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcbd.m +[inst/ctmcbd.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcbd.m ***** 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) + 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 ); 1 test, 1 passed, 0 known failure, 0 skipped -[inst/qsmm1.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmm1.m -***** 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 ); +[inst/qnomaba.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnomaba.m ***** 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)); -3 tests, 3 passed, 0 known failure, 0 skipped + fail( "qnomaba( [1 1], [1 1 1; 1 1 1; 1 1 1] )", "2 rows" ); +1 test, 1 passed, 0 known failure, 0 skipped [inst/dtmc.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmc.m ***** test @@ -5061,6 +5274,34 @@ xlabel("Time Step"); legend("boxoff"); 6 tests, 6 passed, 0 known failure, 0 skipped +[inst/qncmpopmix.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmpopmix.m +***** demo + N = [2 3]; + mix = qncmpopmix(3, N) +***** test + N = [-1 2 2]; + fail( "qncmpopmix(1, N)" ); +***** test + N = [2 2 2]; + fail( "qncmpopmix(7, N)" ); +***** test + N = [2 3 4]; + f = qncmpopmix(0, N ); + assert( f, [0 0 0] ); + f = qncmpopmix( 1, N ); + assert( f, [1 0 0; 0 1 0; 0 0 1] ); + f = qncmpopmix( 2, N ); + assert( f, [2 0 0; 1 1 0; 0 2 0; 1 0 1; 0 1 1; 0 0 2] ); + f = qncmpopmix( 3, N ); + assert( f, [2 1 0; 1 2 0; 0 3 0; 2 0 1; 1 1 1; 0 2 1; 1 0 2; 0 1 2; 0 0 3] ); +***** test + N = [2 1]; + f = qncmpopmix( 1, N ); + assert( f, [1 0; 0 1] ); + f = qncmpopmix( 2, N ); + assert( f, [2 0; 1 1] ); +4 tests, 4 passed, 0 known failure, 0 skipped [inst/qncsaba.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsaba.m ***** test @@ -5096,355 +5337,66 @@ assert( Ru >= Rs-tol ); endfor 3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qnom.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnom.m -***** 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 ); -***** 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"); -5 tests, 5 passed, 0 known failure, 0 skipped -[inst/ctmc.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmc.m -***** test - Q = [-1 1 0 0; 2 -3 1 0; 0 2 -3 1; 0 0 2 -2]; - q = ctmc(Q); - assert( q*Q, 0*q, 1e-5 ); - assert( q, [8/15 4/15 2/15 1/15], 1e-5 ); -***** test - fail( "ctmc([1 1; 1 1])", "infinitesimal" ); - fail( "ctmc([1 1 1; 1 1 1])", "square" ); -***** test - Q = [0 0 0; ... - 0 -1 1; ... - 0 1 -1]; - q = ctmc(Q); - assert( q*Q, 0*q, 1e-5 ); - assert( q, [ 0 0.5 0.5 ], 1e-5 ); -***** test - lambda = 1; - mu = 2; - Q = [ -lambda lambda 0 0 ; ... - mu -(lambda+mu) lambda 0 ; ... - 0 mu -(lambda+mu) lambda ; ... - 0 0 mu -mu ]; - q = ctmc(Q); - assert( q, [8/15 4/15 2/15 1/15], 1e-5 ); -***** test - Q = [ -1 0.4 0.6 0 0 0; ... - 2 -3 0 0.4 0.6 0; ... - 3 0 -4 0 0.4 0.6; ... - 0 2 0 -2 0 0; ... - 0 3 2 0 -5 0; ... - 0 0 3 0 0 -3 ]; - q = ctmc(Q); - assert( q, [0.6578 0.1315 0.1315 0.0263 0.0263 0.0263], 1e-4 ); +[inst/dtmcexps.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcexps.m ***** test - Q = [-1 1 0 0 0 0 0; ... - 0 -3 1 0 2 0 0; ... - 0 0 -3 1 0 2 0; ... - 0 0 0 -2 0 0 2; ... - 2 0 0 0 -3 1 0; ... - 0 2 0 0 0 -3 1; ... - 0 0 2 0 0 0 -2 ]; - q = ctmc(Q); - assert( q, [0.2192 0.1644 0.1507 0.0753 0.1096 0.1370 0.1438], 1e-4 ); + 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 - a = 0.2; - b = 0.8; - Q = [-a a; b -b]; - qlim = ctmc(Q); - q = ctmc(Q, 100, [1 0]); - assert( qlim, q, 1e-5 ); + 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 ); +2 tests, 2 passed, 0 known failure, 0 skipped +[inst/qncsmvaap.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsmvaap.m ***** test - ll = 0.1; - mu = 100; - eta = 5; - Q = zeros(9,9); - ## 6--1, 7=sleep2 8=sleep1 9=crash - Q(6,5) = 6*ll; - Q(5,4) = 5*ll; - Q(4,3) = 4*ll; - Q(3,2) = 3*ll; - Q(2,1) = 2*ll; - Q(2,7) = mu; - Q(1,9) = ll; - Q(1,8) = mu; - Q(8,9) = ll; - Q(7,8) = 2*ll; - Q(7,6) = eta; - Q(8,6) = eta; - Q -= diag(sum(Q,2)); - q0 = zeros(1,9); q0(6) = 1; - q = ctmc(Q,10,q0); - assert( q(9), 0.000504, 1e-6 ); - q = ctmc(Q,2,q0); - assert( q, [3.83e-7 1.938e-4 0.0654032 0.2216998 0.4016008 0.3079701 0.0030271 0.0000998 5e-6], 1e-5 ); - # Compute probability that no shuttle needs to leave during 10 years - Q(7,:) = Q(8,:) = 0; # make states 7 and 8 absorbing - q = ctmc(Q,10,q0); - assert( 1-sum(q(7:9)), 0.3901, 1e-4 ); -***** demo - Q = [ -1 1; ... - 1 -1 ]; - q = ctmc(Q) -***** demo - a = 0.2; - b = 0.15; - Q = [ -a a; b -b]; - T = linspace(0,14,50); - pp = zeros(2,length(T)); - for i=1:length(T) - pp(:,i) = ctmc(Q,T(i),[1 0]); - endfor - ss = ctmc(Q); # compute steady state probabilities - plot( T, pp(1,:), "b;p_0(t);", "linewidth", 2, ... - T, ss(1)*ones(size(T)), "b;Steady State;", ... - T, pp(2,:), "r;p_1(t);", "linewidth", 2, ... - T, ss(2)*ones(size(T)), "r;Steady State;" ); - xlabel("Time"); - legend("boxoff"); + 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 - sec = 1; - min = 60*sec; - hour = 60*min; - ## the state space enumeration is {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); - assert( p, [0.9983916, 0.000002995, 0.0000066559, 0.00159742, 0.0000012779], 1e-6 ); - Q(3,:) = Q(5,:) = 0; # make states 3 and 5 absorbing - p0 = [1 0 0 0 0]; - MTBF = ctmcmtta(Q, p0) / hour; - assert( fix(MTBF), 24857); + # 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 - ## - ## The code below is used in the paper: "M. Marzolla, - ## "A GNU Octave package for Queueing Networks and Markov Chains analysis" - ## (submitted to the ACM Transactions on Mathematical Software) - ## to analyze the reliability model from Figure 2. The model - ## has been originally described in the paper: - ## - ## David I. Heimann, Nitin Mittal, Kishor S. Trivedi, "Availability - ## and Reliability Modeling for Computer Systems", - ## Marshall C. Yovits (Ed.), Advances in Computers, Elsevier, Volume 31, - ## 1990, Pages 175-233, ISSN 0065-2458, ISBN 9780120121311, DOI - ## https://doi.org/10.1016/S0065-2458(08)60154-0. sep 1989, section - ## 2.5. - - mm = 60; hh = 60*mm; dd = 24*hh; yy = 365*dd; - a = 1/(10*mm); # 1/a = duration of reboot (10 min) - b = 1/30; # 1/b = reconfiguration time (30 sec) - g = 1/(5000*hh); # 1/g = processor MTTF (5000 h) - d = 1/(4*hh); # 1/d = processor MTTR (4 h) - c = 0.9; # recovery probability - [TWO,RC,RB,ONE,ZERO] = deal(1,2,3,4,5); - ## 2 RC RB 1 0 - Q = [ -2*g 2*c*g 2*(1-c)*g 0 0; ... # 2 - 0 -b 0 b 0; ... # RC - 0 0 -a a 0; ... # RB - d 0 0 -(g+d) g; ... # 1 - 0 0 0 d -d]; # 0 - p = ctmc(Q); - - disp("minutes/year spent in RC"); - p(RC)*yy/mm # minutes/year spent in RC - disp("minutes/year spent in RB"); - p(RB)*yy/mm # minutes/year spent in RB - disp("minutes/year spent in 0"); - p(ZERO)*yy/mm # minutes/year spent in 0 - - Q(ZERO,:) = Q(RB,:) = 0; # make states {0, RB} absorbing - p0 = [ 1 0 0 0 0 ] ; # initial state occupancy probabiliies - disp("MTBF (years)"); - MTBF = ctmcmtta(Q, p0) / yy # MTBF (years) -9 tests, 9 passed, 0 known failure, 0 skipped -[inst/qncsgb.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsgb.m -***** test - fail( "qncsgb( 1, [] )", "vector" ); - fail( "qncsgb( 1, [0 -1])", "nonnegative" ); - fail( "qncsgb( 0, [1 2] )", "> 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]; + S = [ 0.125 0.3 0.2 ]; + V = [ 16 10 5 ]; + N = 30; 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 ); + 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 -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qsammm.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsammm.m -***** test - [U R Q X] = qsammm( 73,[10,15,20,20,25] ); - assert( U, 0.81, 1e-2 ); - assert( Q, 6.5278, 1e-4 ); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/qnomaba.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnomaba.m -***** test - fail( "qnomaba( [1 1], [1 1 1; 1 1 1; 1 1 1] )", "2 rows" ); -1 test, 1 passed, 0 known failure, 0 skipped + 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"); +2 tests, 2 passed, 0 known failure, 0 skipped [inst/qncscmva.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncscmva.m ***** test @@ -5512,339 +5464,250 @@ ax=axis(); ax(3) = 0; ax(4) = 40; axis(ax); legend("location","northwest"); legend("boxoff"); 3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qncsmvablo.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsmvablo.m -***** 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 ); +[inst/qsmmmk.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmmmk.m ***** 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 ); + 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 - # 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 ); + 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 ); -5 tests, 5 passed, 0 known failure, 0 skipped -[inst/engset.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/engset.m + assert( X1, X2, 1e-5 ); + #assert( [U1 R1 Q1 X1], [U2 R2 Q2 X2], 1e-5 ); ***** 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"); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/qncmmvabs.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmmvabs.m + 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 - 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" ); + 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 - 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; -2 tests, 2 passed, 0 known failure, 0 skipped -[inst/qncsbsb.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsbsb.m + # 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 - 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"); + # 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 - 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 -2 tests, 2 passed, 0 known failure, 0 skipped -[inst/qncsvisits.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsvisits.m + # 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)); +7 tests, 7 passed, 0 known failure, 0 skipped +[inst/qncmmva.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmmva.m ***** 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" ); + S = [1 1 2; 1 1 1]; + V = [1 1 1; 1 1 1]; + N = [1 1]; + m = [1 1 2]; + fail( "qncmmva(N)" ); + fail( "qncmmva(N,S,V,m)", "independent" ); + S = [0 0 0; 1 1 1]; + fail( "qncmmva(N,S,V,m)", "must contain at least" ); + S = [1 2 3; 1 2 3]; + N = [1 1]; + V = zeros(3,2,3); + fail( "qncmmva(N,S,V)", "size mismatch" ); + fail( "qncmmva([0.3 1], [1 2; 3 4])", "integer"); + fail( "qncmmva([-1 0], [1 2; 3 4])", "nonnegative"); ***** 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 ); + S = [1 1 1; 1 1 1]; + N = [0 0]; + [U R Q X] = qncmmva(N, S); + assert( U, 0*S ); + assert( R, 0*S ); + assert( Q, 0*S ); + assert( X, 0*S ); ***** 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) -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qncsmvaap.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsmvaap.m + S = [1 1 1; 1 1 1]; + V = [1 1 1; 1 1 1]; + N = [0 0]; + m = [2 2 2]; + [U R Q X] = qncmmva(N, S, V, m); + assert( U, 0*S ); + assert( R, 0*S ); + assert( Q, 0*S ); + assert( X, 0*S ); ***** 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"); + S = [ 1/10 1/3; 2/5 1 ]; + V = [ 10 9; 5 4 ]; + N = [ 1 1 ]; + [U R Q X] = qncmmva(N,S,V); + assert( Q, [ 4/19 15/19; 5/19 14/19 ], 1e-3 ); + assert( R .* V, [ 4/3 5; 5/2 7 ], 1e-3 ); + assert( diag( X ./ V )', [ 3/19 2/19 ], 1e-3 ); + assert( all(U(:)<=1) ); + assert( Q, R.*X, 1e-5 ); # Little's Law ***** 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"); -2 tests, 2 passed, 0 known failure, 0 skipped -[inst/qnmix.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnmix.m + S = [0.02 0.2 0.4 0.6]; + V = [1 0.4 0.2 0.1]; + N = [6]; + [U R Q X] = qncmmva( N, S, V ); + assert( Q, [0.244 2.261 2.261 1.234], 1e-3 ); + assert( R, [0.025 0.570 1.140 1.244], 1e-3 ); + assert( X, [9.920 3.968 1.984 0.992], 1e-3 ); + assert( U, [0.198 0.794 0.794 0.595], 1e-3 ); ***** 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" ); + S = [1 0 .025; 0 15 .5]; + V = [1 0 1; 0 1 1]; + N = [2 1]; + m = [-1 -1 1]; + [U R Q X] = qncmmva(N,S,V,m); + assert( R(1,1), 1, 1e-3 ); + assert( R(2,2), 15, 1e-3 ); + assert( R(1,3), .027, 1e-3 ); + assert( R(2,3), .525, 1e-3 ); + assert( X(1,1)+X(1,2), 1.949, 1e-3 ); + assert( X(2,1)+X(2,2), 0.064, 1e-3 ); + assert( sum(Q,1), [1.949, .966, .085], 1e-3 ); + assert( all(U(:,3)<=1) ); + assert( Q, R.*X, 1e-5 ); # Little's Law ***** 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 ); + 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); + # I replaced 14.3->14.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 ***** 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 ); + 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 ***** 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 ); + 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 ); +***** 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 -4 tests, 4 passed, 0 known failure, 0 skipped -[inst/qncmvisits.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmvisits.m ***** test - - ## Closed, multiclass network - - C = 2; K = 3; + C = 2; + K = 6; 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; + 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); - for c=1:C - for k=1:K - assert(V(c,k), sum(sum(V .* P(:,:,c,k))), 1e-5); - endfor - endfor + [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 ***** 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; # 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; @@ -5857,24 +5720,53 @@ P(2,1,2,4) = .49; P(2,3,2,1) = 1; P(2,4,2,1) = 1; + + # Compute visits + 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/ + # 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 ); +***** 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 ); +***** 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 +***** test C = 2; K = 3; S = [.01 .07 .10; ... - .05 0.7 .10 ]; + .05 .07 .10 ]; P = zeros(C,K,C,K); P(1,1,1,2) = .7; P(1,1,1,3) = .2; @@ -5882,226 +5774,207 @@ 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; + 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 = 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) ); + [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 ); ***** 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"); + 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 ); ***** 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); + 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 ); +***** 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,[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] ); -***** 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] ); -9 tests, 9 passed, 0 known failure, 0 skipped -[inst/dtmcchkP.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcchkP.m -***** 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 ); -5 tests, 5 passed, 0 known failure, 0 skipped -[inst/ctmcmtta.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcmtta.m -***** test - Q = [0 1 0; 1 0 1; 0 1 0 ]; Q -= diag( sum(Q,2) ); - fail( "ctmcmtta(Q,[1 0 0])", "no absorbing"); -***** test - Q = [0 1 0; 1 0 1; 0 0 0; 0 0 0 ]; - fail( "ctmcmtta(Q,[1 0 0])", "square matrix"); -***** test - Q = [0 1 0; 1 0 1; 0 0 0 ]; - fail( "ctmcmtta(Q,[1 0 0])", "infinitesimal"); -***** 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) ); - assert( ctmcmtta( Q,[0 0 0 1] ), 0 ); # state 4 is absorbing -***** test - Q = [-1 1; 0 0]; - assert( ctmcmtta( Q, [0 1] ), 0 ); # state 2 is absorbing - assert( ctmcmtta( Q, [1 0] ), 1 ); # the result has been computed by hand + 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) ***** demo - mu = 0.01; - death = [ 3 4 5 ] * mu; - birth = 0*death; - Q = ctmcbd(birth,death); - t = ctmcmtta(Q,[0 0 0 1]) + 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 - N = 100; - birth = death = ones(1,N-1); birth(1) = death(N-1) = 0; - Q = diag(birth,1)+diag(death,-1); - Q -= diag(sum(Q,2)); - t = zeros(1,N/2); - initial_state = 1:(N/2); - for i=initial_state - p = zeros(1,N); p(i) = 1; - t(i) = ctmcmtta(Q,p); + 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 - plot(initial_state,t,"+"); - xlabel("Initial state"); - ylabel("MTTA"); -5 tests, 5 passed, 0 known failure, 0 skipped -[inst/ctmctaexps.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmctaexps.m + 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"); +17 tests, 17 passed, 0 known failure, 0 skipped +[inst/qncmbsb.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmbsb.m ***** 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); + 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 - 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"); + assert( all(Xl <= Xmva) ); + assert( all(Xu >= Xmva) ); + assert( all(Rl <= Rmva) ); + assert( all(Xu >= Xmva) ); ***** 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 + 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 - clf; - semilogy(TT,A,";Steady-state;", ... - TT,At,";Instantaneous;", ... - TT,Abart,";Interval base;"); - ax = axis(); - ax(3) = 1-1e-5; - axis(ax); - legend("boxoff"); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/qncmnpop.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmnpop.m + 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"); +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/dtmcbd.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcbd.m ***** 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] ); + 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) 1 test, 1 passed, 0 known failure, 0 skipped [inst/ctmcexps.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcexps.m @@ -6152,66 +6025,192 @@ L = ctmcexps(Q,p0); disp(L); 2 tests, 2 passed, 0 known failure, 0 skipped -[inst/ctmcisir.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcisir.m +[inst/qsmminf.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmminf.m ***** test - Q = [-.5 .5 0; 1 0 0]; - fail( "ctmcisir(Q)" ); + 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)); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/qncmcb.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmcb.m ***** 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 ); + 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"); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/ctmcchkQ.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcchkQ.m ***** 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 ); -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qsmm1k.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmm1k.m + Q = [0]; + [result err] = ctmcchkQ(Q); + assert( result, 1 ); + assert( err, "" ); ***** 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 ); + N = 10; + Q = ctmcbd(rand(1,N-1),rand(1,N-1)); + [result err] = ctmcchkQ(Q); + assert( result, N ); + assert( err, "" ); ***** 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 ); + Q = [1 2 3; 4 5 6]; + [result err] = ctmcchkQ(Q); + assert( result, 0 ); + assert( index(err, "square") > 0 ); ***** 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)); -3 tests, 3 passed, 0 known failure, 0 skipped + 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 ); +5 tests, 5 passed, 0 known failure, 0 skipped +[inst/qnosaba.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnosaba.m +***** 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 ); +2 tests, 2 passed, 0 known failure, 0 skipped +[inst/qncmnpop.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmnpop.m +***** 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] ); +1 test, 1 passed, 0 known failure, 0 skipped +[inst/qncsconvld.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsconvld.m +***** 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 ); +5 tests, 5 passed, 0 known failure, 0 skipped +[inst/dtmctaexps.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmctaexps.m +***** 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 ); +1 test, 1 passed, 0 known failure, 0 skipped [inst/qsmmm.m] >>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmmm.m ***** demo @@ -6292,80 +6291,78 @@ legend("boxoff"); title(sprintf("PMF of M/M/\\infty and M/M/m systems, \\lambda = %g, \\mu = %g", lambda, mu)); 3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qnmknode.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qnmknode.m -***** test - fail( "qnmknode( 'pippo', 1 )", "must be one" ); - fail( "qnmknode( '-/g/1-ps', 1, 1, 1)", "Invalid call" ); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/qsmminf.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qsmminf.m -***** 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)); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/qncmpopmix.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmpopmix.m -***** demo - N = [2 3]; - mix = qncmpopmix(3, N) -***** test - N = [-1 2 2]; - fail( "qncmpopmix(1, N)" ); -***** test - N = [2 2 2]; - fail( "qncmpopmix(7, N)" ); +[inst/qncsconv.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsconv.m ***** test - N = [2 3 4]; - f = qncmpopmix(0, N ); - assert( f, [0 0 0] ); - f = qncmpopmix( 1, N ); - assert( f, [1 0 0; 0 1 0; 0 0 1] ); - f = qncmpopmix( 2, N ); - assert( f, [2 0 0; 1 1 0; 0 2 0; 1 0 1; 0 1 1; 0 0 2] ); - f = qncmpopmix( 3, N ); - assert( f, [2 1 0; 1 2 0; 0 3 0; 2 0 1; 1 1 1; 0 2 1; 1 0 2; 0 1 2; 0 0 3] ); + # 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 - N = [2 1]; - f = qncmpopmix( 1, N ); - assert( f, [1 0; 0 1] ); - f = qncmpopmix( 2, N ); - assert( f, [2 0; 1 1] ); -4 tests, 4 passed, 0 known failure, 0 skipped -[inst/dtmcisir.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcisir.m + # 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 - P = [0 .5 0; 0 0 0]; - fail( "dtmcisir(P)" ); + # 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 ); +***** 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 +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/qncmaba.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmaba.m ***** 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 ); + 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 - 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 ); -3 tests, 3 passed, 0 known failure, 0 skipped -[inst/qncmcb.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncmcb.m + [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]; @@ -6373,7 +6370,7 @@ Xl = Xu = Rl = Ru = Xmva = Rmva = zeros(NN,2); for n=1:NN N=[n,10]; - [a b c d] = qncmcb(N,S); + [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)'; @@ -6389,7 +6386,7 @@ Xl = Xu = Rl = Ru = Xmva = Rmva = zeros(NN,2); for n=1:NN N=[n,10]; - [a b c d] = qncmcb(N,S); + [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)'; @@ -6410,122 +6407,161 @@ 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"); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/dtmctaexps.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmctaexps.m -***** 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 ); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/dtmcfpt.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/dtmcfpt.m -***** 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 ); -***** 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 ); +3 tests, 3 passed, 0 known failure, 0 skipped +[inst/qncsmva.m] +>>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/qncsmva.m ***** 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 + 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" ); ***** 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 ); -6 tests, 6 passed, 0 known failure, 0 skipped -[inst/erlangc.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/erlangc.m + 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]); ***** test - fail("erlangc('foo',1)", "positive"); - fail("erlangc(1,'bar')", "positive"); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/ctmcfpt.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcfpt.m -***** 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) + 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 ); ***** 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) ); -1 test, 1 passed, 0 known failure, 0 skipped -[inst/ctmcchkQ.m] ->>>>> /build/reproducible-path/octave-queueing-1.2.8/inst/ctmcchkQ.m + 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 - Q = [0]; - [result err] = ctmcchkQ(Q); - assert( result, 1 ); - assert( err, "" ); + # 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 - N = 10; - Q = ctmcbd(rand(1,N-1),rand(1,N-1)); - [result err] = ctmcchkQ(Q); - assert( result, N ); - assert( err, "" ); + # 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 - Q = [1 2 3; 4 5 6]; - [result err] = ctmcchkQ(Q); - assert( result, 0 ); - assert( index(err, "square") > 0 ); + # 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 - 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 ); + # 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 - 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 ); -5 tests, 5 passed, 0 known failure, 0 skipped + # 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)"); +9 tests, 9 passed, 0 known failure, 0 skipped Checking C++ files ... Done running the unit tests. Summary: 204 tests, 204 passed, 0 known failures, 0 skipped @@ -6559,12 +6595,14 @@ dpkg-buildpackage: info: binary-only upload (no source included) dpkg-genchanges: info: including full source code in upload I: copying local configuration +I: user script /srv/workspace/pbuilder/2824/tmp/hooks/B01_cleanup starting +I: user script /srv/workspace/pbuilder/2824/tmp/hooks/B01_cleanup finished I: unmounting dev/ptmx filesystem I: unmounting dev/pts filesystem I: unmounting dev/shm filesystem I: unmounting proc filesystem I: unmounting sys filesystem I: cleaning the build env -I: removing directory /srv/workspace/pbuilder/8936 and its subdirectories -I: Current time: Sat Oct 5 22:02:52 -12 2024 -I: pbuilder-time-stamp: 1728208972 +I: removing directory /srv/workspace/pbuilder/2824 and its subdirectories +I: Current time: Sun Nov 9 06:27:41 +14 2025 +I: pbuilder-time-stamp: 1762619261