Mercurial > forge
changeset 9391:ea88fce5f7ff octave-forge
queueing: add new package for Moreno Marzolla
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/COPYING Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/DESCRIPTION Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,16 @@ +Name: queueing +Version: 1.0.0 +Date: 2012-02-03 +Author: Moreno Marzolla <marzolla@cs.unibo.it> +Maintainer: Moreno Marzolla <marzolla@cs.unibo.it> +Title: Queueing Networks and Markov chains analysis package for GNU Octave +Description: This package provides functions + for analyzing single station queueing systems, + Queueing Network and Markov chains. Open, closed and mixed + networks with single or multiple job classes are supported; + exact and approximate solution techniques are available. +Categories: Misc +Depends: octave (>= 3.0.0) +Autoload: yes +License: GPL version 3 or later +Url: http://www.moreno.marzolla.name/software/queueing/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/DESCRIPTION.in Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,16 @@ +Name: PROGNAME +Version: VERSIONNUM +Date: VERSIONDATE +Author: Moreno Marzolla <marzolla@cs.unibo.it> +Maintainer: Moreno Marzolla <marzolla@cs.unibo.it> +Title: Queueing Networks and Markov chains analysis package for GNU Octave +Description: This package provides functions + for analyzing single station queueing systems, + Queueing Network and Markov chains. Open, closed and mixed + networks with single or multiple job classes are supported; + exact and approximate solution techniques are available. +Categories: Misc +Depends: octave (>= 3.0.0) +Autoload: yes +License: GPL version 3 or later +Url: http://www.moreno.marzolla.name/software/queueing/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/INSTALL Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,167 @@ +This file documents the installation procedure of the `queueing' +toolbox. + + `queueing' is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License, version 3 or +later, as published by the Free Software Foundation. + + Note: This file (`INSTALL') is automatically generated from + `doc/installation.txi' in the `queueing' sources. Do not modify + this document directly, as changes will be lost. Modify the source + `doc/installation.txi' instead. + +1 Installing the queueing toolbox +********************************* + +1.1 Installation through Octave package management system +========================================================= + +The most recent version of `queueing' is 1.0.0 and can be downloaded +from + +`http://www.moreno.marzolla.name/software/queueing/queueing-1.0.0.tar.gz' + + To install `queueing' in the system-wide location, such that all +functions are automatically available when Octave starts, you can use +`pkg install' command. At the Octave prompt, type the following: + + octave:1> pkg install queueing-1.0.0.tar.gz + + (Note: you may need to start Octave as root in order to allow the +installation to copy the files to the target locations). After this, +all functions will be readily available each time Octave starts, +without the need to tweak the search path. To uninstall `queueing', use +the `pkg uninstall queueing' command. + + If you do not have root access, you can do a local installation by +issuing the following command at the Octave prompt: + + octave:1> pkg install -local queueing-1.0.0.tar.gz + + This will install `queueing' within the user's home directory, and +the package will be available to that user only. *Note:* Octave version +3.2.3 as shipped with Ubuntu 10.04 seems to ignore `-local' and always +tries to install the package on the system directory. + +1.2 Manual installation +======================= + +If you want to install `queueing' in a custom location, you can +download the source tarball from the URL above, and unpack it somewhere: + + tar xfz queueing-1.0.0.tar.gz + cd queueing-1.0.0/ + + Copy all `.m' files from the `inst/' directory to some target +location. Then, you can start Octave with the `-p' option to add the +target location to the search path, so that Octave will find all +`queueing' functions automatically: + + octave -p _/path/to/queueing_ + + For example, if all `queueing' m-files are in `/usr/local/queueing', +you can start Octave as follows: + + octave -p `/usr/local/queueing' + + If you want, you can add the following line to `~/.octaverc': + + addpath("_/path/to/queueing_"); + +so that the path `/usr/local/queueing' is automatically added to the +search path each time Octave is started, and you no longer need to +specify the `-p' option on the command line. + +1.3 Content of the source distribution +====================================== + +The `queueing' source distribution contains the following +subdirectories: + +`doc/' + Documentation source. Most of the documentation is extracted from + the comment blocks of individual function files from the `inst/' + directory. + +`inst/' + This directory contains the m-files which implement the various + Queueing Network algorithms provided by `queueing'. As a + notational convention, the names of source files containing + functions for Queueing Networks start with the `qn' prefix; the + name of source files containing functions for Continuous-Time + Markov Chains (CTMSs) start with the `ctmc' prefix, and the names + of files containing functions for Discrete-Time Markov Chains + (DTMCs) start with the `dtmc' prefix. + +`test/' + This directory contains the test functions used to invoke all + tests on all function files. + +`scripts/' + This directory contains some utility scripts mostly from GNU + Octave, which extract the documentation from the + specially-formatted comments in the m-files. + +`examples/' + This directory contains examples which are automatically extracted + from the `demo' blocks of the function files. + +`broken/' + This directory contains function files which are either not working + properly, or need additional testing before they can be moved to + the `inst/' directory. + + + The `queueing' package ships with a Makefile which can be used to +produce the documentation (in PDF and HTML format), and automatically +execute all function tests. Specifically, the following targets are +defined: + +`all' + Running `make' (or `make all') on the top-level directory builds + the programs used to extract the documentation from the comments + embedded in the m-files, and then produce the documentation in PDF + and HTML format (`doc/queueing.pdf' and `doc/queueing.html', + respectively). + +`check' + Running `make check' will execute all tests contained in the + m-files. If you modify the code of any function in the `inst/' + directory, you should run the tests to ensure that no errors have + been introduced. You are also encouraged to contribute new tests, + especially for functions which are not adequately validated. + +`clean' +`distclean' +`dist' + The `make clean', `make distclean' and `make dist' commands are + used to clean up the source directory and prepare the distribution + archive in compressed tar format. + + +1.4 Using the queueing toolbox +============================== + +You can use all functions by simply invoking their name with the +appropriate parameters; the `queueing' package should display an error +message in case of missing/wrong parameters. You can display the help +text for any function using the `help' command. For example: + + octave:2> help qnmvablo + + prints the documentation for the `qnmvablo' function. Additional +information can be found in the `queueing' manual, which is available +in PDF format in `doc/queueing.pdf' and in HTML format in +`doc/queueing.html'. + + Within GNU Octave, you can also run the test and demo blocks +associated to the functions, using the `test' and `demo' commands +respectively. To run all the tests of, say, the `qnmvablo' function: + + octave:3> test qnmvablo + -| PASSES 4 out of 4 tests + + To execute the demos of the `qnclosed' function, use the following: + + octave:4> demo qnclosed +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/Makefile Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,52 @@ +VERSIONNUM=1.0.0 +VERSIONDATE="2012-02-03" +PROGNAME=queueing + +DISTNAME=$(PROGNAME)-$(VERSIONNUM) +SUBDIRS=inst scripts examples doc test broken +DISTFILES=COPYING README Makefile DESCRIPTION DESCRIPTION.in INSTALL + +.PHONY: clean check + +ALL: DESCRIPTION doc/conf.texi + for d in $(SUBDIRS); do \ + $(MAKE) -C $$d ALL; \ + done + +doc/conf.texi: + \rm -f doc/conf.texi + echo "@set VERSION $(VERSIONNUM)" > doc/conf.texi + echo "@set VERSIONDATE $(VERSIONDATE)" >> doc/conf.texi + echo "@set top_srcdir " `pwd` >> doc/conf.texi + +DESCRIPTION: DESCRIPTION.in + cat DESCRIPTION.in | \ + sed "s/PROGNAME/$(PROGNAME)/g" | \ + sed "s/VERSIONNUM/$(VERSIONNUM)/g" | \ + sed "s/VERSIONDATE/$(VERSIONDATE)/g" > DESCRIPTION + +check: + $(MAKE) -C test check + +clean: + for d in $(SUBDIRS); do \ + $(MAKE) -C $$d clean; \ + done + \rm -r -f *~ *.tar.gz $(DISTNAME) + +distclean: clean + for d in $(SUBDIRS); do \ + $(MAKE) -C $$d distclean; \ + done + \rm -r -f doc/conf.texi fname DESCRIPTION $(DISTNAME) $(DISTNAME).tar.gz + +dist: ALL + \rm -r -f $(DISTNAME) fname + mkdir $(DISTNAME) + echo "$(DISTNAME)" > fname + for d in $(SUBDIRS); do \ + mkdir -p $(DISTNAME)/$$d; \ + $(MAKE) -C $$d dist; \ + done + ln $(DISTFILES) $(DISTNAME)/ + tar cfz $(DISTNAME).tar.gz $(DISTNAME)/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/README Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,52 @@ +=============================================================================== + The Octave queueing toolbox +=============================================================================== + +Copyright (C) 2008, 2009, 2010, 2011, 2012 +Moreno Marzolla <marzolla (at) cs.unibo.it> + +The queueing toolbox ("queueing", in short) is a collection of GNU +Octave scripts for numerical evaluation of queueing network +models. Open, closed and mixed networks are supported, with single or +multiple classes of customers. The queueing toolbox also provides +functions for steady-state and transient analysis of Markov chains, as +well as fo single station queueing systems. + +The latest version of the queueing package can be downloaded from + +http://www.moreno.marzolla.name/software/queueing/ + +This package requires GNU Octave; version 3.0.0 or later should work. +The package contains the following directories: + +inst/ + Contains the Octave m-scripts implementing all functions + provided by the queueing toolbox. + +doc/ + Contains the user documentation, which is automatically + generated from the texinfo strings embedded in the m-scripts. + +scripts/ + This directory contains some scripts used to extract + documentation strings from the m-files. The scripts here have + been taken almost verbatim from the GNU Octave distribution. + +examples/ + This directory contains demo functions which are automatically + extracted from the scripts included in the inst/ + directory. The demo functions are put in this directory so + that they can be easily embedded into the package documentation. + +test/ + This directory contains the script used to execute all + tests embedded within functions in the inst/ directory. + +broken/ + This directory contains scripts which are currently known + not to work correctly, or which are work-in-progress. + +This package can be distributed according to the terms of the GNU +General Public License, version 3 or later. See the file COPYING for +details. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/broken/Makefile Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,14 @@ +DISTFILES=Makefile $(wildcard *.m) + +.PHONY: check dist clean + +ALL: + +dist: + ln $(DISTFILES) ../`cat ../fname`/broken/ + +clean: + \rm -f *~ + +distclean: clean +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/broken/blkdiagonalize.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,151 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{T} @var{p}] =} blkdiagonalize (@var{M}) +## +## @strong{WARNING: this function has not been sufficiently tested} +## +## Given a square matrix @var{M}, return a new matrix @code{@var{T} = +## @var{M}(@var{p},@var{p})} such that @var{T} is in block triangular +## form. +## +## @strong{INPUTS} +## +## @table @var +## +## @item M +## +## Square matrix to be permuted in block-triangular form +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item T +## +## The matrix @var{M} permuted in block-triangular form +## +## @item p +## +## Vector representing the permutation. The matrix @var{T} +## can be derived as @code{@var{T} = @var{M}(@var{p},@var{p})} +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [T p] = blkdiagonalize( M ) + if ( nargin =! 1 ) + print_usage(); + endif + n = rows(M); + ( [n,n] == size(M) ) || \ + error( "M must be a square matrix" ); + p = linspace(1,n,n); # identify permutation + T = M; + for i=1:n-1 # loop over rows + ## find zero and nonzero elements in the i-th row + zel = find(T(i,:)==0); + nzl = find(T(i,:)!=0); + zeroel = zel(zel>i); + nzeroel = nzl(nzl>i); + perm = [ 1:i nzeroel zeroel ]; + + ## Update permutation + p = p(perm); + ## Permute matrix + T = T(perm,perm); + endfor +endfunction +%!demo +%! P = [0 0.4 0 0 0.3 0 0 0.3 0; ... +%! 0.3 0 0 0 0 0 0 0.7 0; ... +%! 0 0 0 0 0 0.3 0 0 0.7; ... +%! 0 0 0 0 1 0 0 0 0; ... +%! 0.3 0 0 0 0 0 0.7 0 0; ... +%! 0 0 0.3 0 0 0 0 0 0.7; ... +%! 1.0 0 0 0 0 0 0 0 0; ... +%! 0 0 0 1.0 0 0 0 0 0; ... +%! 0 0 0.4 0 0 0.6 0 0 0]; +%! P = blkdiagonalize(P); +%! spy(P); + +%!demo +%! A = ones(3); +%! B = 2*ones(2); +%! C = 3*ones(3); +%! D = 4*ones(7); +%! E = 5*ones(2); +%! M = blkdiag(A, B, C, D, E); +%! n = rows(M); +%! spy(M); +%! printf("Press any key or wait 5 seconds..."); +%! pause(5); +%! p = randperm(n); +%! M = M(p,p); +%! spy(M); +%! printf("Scrambled matrix. Press any key or wait 5 seconds..."); +%! pause(5); +%! T = blkdiagonalize(M); +%! spy(T); +%! printf("Unscrambled matrix" ); + +%!xtest +%! A = ones(3); +%! B = 2*ones(2); +%! C = 3*ones(3); +%! D = 4*ones(7); +%! E = 5*ones(2); +%! M = blkdiag(A, B, C, D, E); +%! n = rows(M); +%! p = randperm(n); +%! Mperm = M(p,p); +%! T = blkdiagonalize(Mperm); +%! assert( T, M ); + +## Given a block diagonal matrix M, find the size of all blocks. b(i) is +## the size of i-th along the diagonal. A zero matrix is considered to +## have a single block of size equal to the size of the matrix. +function b = findblocks(M) + n = rows(M); + (size(M) == [n,n]) || \ + error("M must be a square matrix"); + b = []; + i=d=1; + while( d<n ) + bb = M(i:d,i:d); + z1 = M(i:d,d+1:n); + z2 = M(d+1:n,i:d); + if ( any(bb) && !any(z1) && !any(z2) ) + b = [b d-i+1]; + i=d+1; + d=i; + else + d++; + endif + endwhile + if (i<d) + b = [b d-i+1]; + endif +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/broken/dtmc_period.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,72 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{p} =} dtmc_period (@var{P}) +## +## @cindex Markov chain, discrete-time +## +## Compute the period @code{@var{p}(i)} of state @math{i}, for all +## states. The period is defined as the greatest common divisor +## of the number of steps after which a DTMC returns to the starting +## state. If state @math{i} is non recurrent, then @code{@var{p}(i) = 0}. +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function p = dtmc_period( P ) + + n = dtmc_check_P(P); # ensure P is a transition probability matrix + + period = zeros(n,n); # period(i,j) = 1 iff state i returns to itself after exactly j steps + + Pi = P; + + for j=1:n + d = (diag(Pi) > 0); ## d(i) = 1 iff state i returns to itself after j steps + period(:,j) = d; + Pi = Pi*P; + endfor + + p = zeros(1,n); + F = (find( any(period > 0, 2) )'); # F = set of recurrent states + for i=F + p(i) = gcd( find(period(i,:) > 0) ); + endfor +endfunction +%!test +%! P = [0 1 0; 0 0 1; 1 0 0]; # 1 -> 2 -> 3 -> 1 +%! p = dtmc_period(P); +%! assert( p, [3 3 3] ); + +%!test +%! P = [1 0 0; 0 1 0; 0 0 1]; +%! p = dtmc_period(P); +%! assert( p, [1 1 1] ); + +%!test +%! P = [0 1 0; 0 0 1; 0 1 0]; # state 1 is non recurrent +%! p = dtmc_period(P); +%! assert( p, [0 2 2] ); + +%!test +%! P = [0 0 1 0; 0 0 0 1; 0 1 0 0; 0.5 0 0.5 0]; +%! p = dtmc_period(P); +%! assert( p, [1 1 1 1] );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/broken/lee_et_al_98.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,1249 @@ +## Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{P} =} lee_et_al_98 ( @var{mu}, @var{mu0}, @var{C}, @var{r}, @var{blocking_type} ) +## +## @strong{WARNING: this implementation is not working yet} +## +## Implementation of the numerical algorithm for approximate solution of +## single-class queueing networks with blocking. The algorithm is +## described in [1]. This is the implementation of Algorithm 1, p. 192 +## from the paper above, and can be used for cyclic networks. +## +## @strong{INPUTS} +## +## @table @var +## +## @item mu +## +## @code{@var{mu}(i)} is the service rate at service center @math{i}. +## This function aborts if @code{@var{mu}(i) <= 0} for some @math{i}. +## +## @item mu0 +## +## @code{@var{mu0}(i)} is the external arrival rate on service center +## @math{i}. If @code{@var{mu0}(i) <= 0} there is no external arrival on +## service center @math{i}. +## +## @item C +## +## @code{@var{C}(i)} is the capacity of service center @math{i}. The +## buffer size of service center @math{i} is @code{@var{C}(i)-1}. This +## function aborts if @code{@var{C}(i) < 1} for some @math{i}. +## +## @item r +## +## @code{@var{r}(i,j)} is the routing probability from service center +## @math{i} to service center @math{j}, that is, the probability that a +## job which completed execution on service center @math{i} is routed to +## service center @math{j}. If @math{\sum_{j} r(i,j) < 1} for some +## @math{i}, then the exit probability of jobs from service center +## @math{i} is @math{( 1 - \sum_{j} r(i,j) )}; this is the probability +## that a job leaves the system after completing service at service +## center @math{i}. +## +## @item blocking_type +## +## if @code{@var{blocking_type}(j)==0}, then Blocking-after-service +## (BAS) is assumed for service center @code{@var{S_u1}(j)}; if +## @code{@var{blocking_type}(j)!=0}, then Repetitive-service blocking is +## assumed for service center @code{@var{S_u1}(j)}. Note that +## Repetitive-service blocking can only be applied to saturated service +## centers (that is, @code{@var{blocking_type}(j)} can be set != 0 only +## if @code{@var{mu0}(j) > 0}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item P +## +## @code{@var{P}(i,n)} is the steady state probability that there are +## @math{n-1} jobs on service center @math{i}. +## +## @end table +## +## @strong{ISSUES} +## +## This implementation makes heavy use of global variables. The reason +## is that there are are many structures which must be passed along to +## different functions. To avoid cluttering the function definitions +## with lot of extra parameters, we make use of global variables. +## +## This implementation makes heavy use of multidimensional arrays. +## Unfortunately, index of octave arrays always start from 1. This is an +## issue, as in many cases (e.g., @var{P_b}), one of the indexes is +## supposed to start from 0. Thus, pay extra attention about the range +## of indexes. +## +## The algorithm by Lee et al. [1] makes heavy use of summations. While +## in octave it is relatively easy to sum the elements of an array (or +## of a matrix), it is not so easy to make nested summations, especially +## if these summations cannot be reduced to matrix/vector +## multiplications. In this implementation, there are many places in +## which nested loops are used. This is inefficient and makes the code +## difficult to read, but again, my understanding is that there is no +## better way to do that. +## +## This implementation is NOT optimized for speed. DO NOT perform speed +## benchmark on this implementation! +## +## @strong{REFERENCES} +## +## @noindent [1] H.S. Lee, A. Bouhchouch, Y. Dallery and Y. Frein, +## @cite{Performance evaluation of open queueing networks with arbitrary +## configuration and finite buffers}, Annals of Operations Research +## 79(1998), 181-206 +## +## @noindent [2] Hyo-Seong Lee; Stephen M. Pollock, @cite{Approximation +## Analysis of Open Acyclic Exponential Queueing Networks with +## Blocking}, Operations Research, Vol. 38, No. 6. (Nov. - Dec., 1990), +## pp. 1123-1134. +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla@cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ +## Created: 2007-11-20 + +global mu; # mu(1,j) j=1..M is the service rate at S_j +global C; # C(1,j) j=1..M is the capacity of buffer B_j +global r; # r(i,j) i=1..M, j=1..M is the routing probability from S_i to S_j +global C_max; # Scalar representing the maximum value of C() +global N_max; # Scalar representing the maximum value of N() +global mu_u; # mu_u(i,j) i=1..N(j), j=1..M is the upstream service rate of S_u i(j) +global P_b; # P_b(i,n+1,j) is the probability that at service completion instant, the server S_ui(j) sees n other servers being blocked by S_d(j), n=0..N_j-1 +global P_s; # P_s(j) is the probability that S_d(j) is starved at the service completion instant, j=1..M +global P; # P(n+1,j) is the steady state probability that T(j) is in state n, n=0,..C_j+N_j +global b_u; # bu_u(i,n+1,j) is the probability that n servers are blocked by S_d(j), including S_ui(j), n=1..N_j +global mu_d; # mu_d(j) is the service rate of S_d(j), j=1..M +global mu0; # mu0(j) is the external arrival rate to service center S_j, j=1..M. If S_j has no external arrival, then mu0(j) = 0 +global blocking_type; # array of integer: blocking_type(j) == 0 iff the blocking type of S_u1(j) is BAS, blocking_type(j) != 0 for repetitive-service blocking + +## Exported constants +global epsilon = 1e-5; # Maximum allowed error on throughput +global iter_count_max = 100; # Maximum number of iterations + +function result = lee_et_al_98( mu_, mu0_, C_, r_, blocking_type_ ) + + error( "*** The lee_et_al_98() function is currently BROKEN. Please do not use it ***" ); + + global mu; + global C; + global r; + global C_max; + global N_max; + global mu_u; + global P_b; + global P_s; + global P; + global b_u; + global mu_d; + global mu0; + global blocking_type; + + if ( nargin != 5 ) + print_usage(); + endif + + M = size(mu_, 2); ## Number of service centers + size(C_) == [1,M] || error( "lee_et_al_98() - parameter C must be a (1xM) vector" ); + size(r_) == [M,M] || error( "lee_et_al_98() - parameter r must be a (MxM) matrix" ); + size(mu0_) == [1,M] || error( "lee_et_al_98() - parameter mu0 must be a (1,M) vector" ); + all( C_ > 0 ) || error( "lee_et_al_98() - parameter C must contain elements >0 only" ); + all( mu_ > 0 ) || error( "lee_et_al_98() - parameter mu must contain elements >0 only" ); + size(blocking_type_) == [1,M] || error( "lee_et_al_98() - parameter blocking_type bust be a (1,M) vector" ); + + blocking_type = blocking_type_; + mu = [mu_ mu0_]; + mu0 = mu0_; + C = C_; + r = r_; + + ## Some constants + global epsilon; + global iter_count_max; + + ## Some variables + C_max = max(C); # Maximum buffer size + N_max = M+1; # M service centers plus one (optional) external source + mu_d = mu_; + P_b = zeros( N_max, N_max, M ); ## WARNING: the second index should start from 0, not 1!! + P_s = zeros( M ); + P = zeros( C_max+N_max+1, M ); ## WARNING: the first index should start from 0m not 1!! + b_u = zeros( M, N_max+1, M ); ## WARNING: the second index should start from 0, not 1!! + + mu_u = zeros( N_max, M ); + for j = 1:M + for i = 1:N(j) + k = f(i,j); + if ( is_saturated(i,j) ) + mu_u(i,j) = mu(k); + else + mu_u(i,j) = mu(k) * r(k,j); + endif + endfor + endfor + ## End initialization step + + ## Iteration step + iter_count = 1; + + do + + old_mu_u = mu_u; + old_mu_d = mu_d; + + for j=1:M # Begin iteration step + + P(1:C(j)+N(j)+1,j) = compute_P(j)'; + assert( sum(P(:,j)), 1, 1e-4 ); + + ## + ## 1 Calculate mu_d(j) using (5) + ## + mu_d( j ) = compute_mu_d( j ); + + ## + ## 2 Calculate P_s(j) using (3) + ## + P_s( j ) = compute_P_s( j ); + + ## + ## 3 Calculate P_b i(n:j) using (4) for n=0:N_j-1, i=1:N_j + ## + for i=1:N(j) + for n=1:N(j) + b_u(i,n+1,j) = compute_b_u(i,n,j); + endfor + endfor + for i=1:N(j) + for n=0:N(j)-1 + P_b(i,n+1,j) = compute_P_b( i, n, j ); + endfor + ##assert( sum(P_b(i,:,j)), 1, 1e-4 ); + endfor + + ## + ## 4 Calculate mu_u(i,k) using (7) for all k \in D_j where f(i,k)=j + ## + for k=D(j) + i = f_inverse_i(j,k); + assert(f(i,k)==j); + mu_u(i,k) = compute_mu_u(i,k); + endfor + + endfor # End iteration step + + err1 = abs( old_mu_d - mu_d ); + err2 = abs( old_mu_u - mu_u ); + iter_count++; + + until ( ( (err1 < epsilon) && (err2 < epsilon) ) + || (iter_count > iter_count_max) ); + + ## fprintf("Converged in %d iterations\n", iter_count ); + + ## Safety check: check that eq. (8) from [1] is satisfied + for j=1:M + for i=1:N(j) + k = f(i,j); + if ( k<=M ) + assert( compute_X_u(i,j), compute_X_d(k) * r(k,j), 1e-4 ); + endif + endfor + endfor + ## End safety check + + ## Reshape the result, so that result(i,n) is P_i(n+1), the + ## steady-state probability that (n+1) customers are in service center + ## S_i, n=1..C(j)+1 + result = zeros( M, C_max+1 ); + for j=1:M + ## P_j = compute_P(j); + result(j,[1:C(j)]) = P([1:C(j)],j)'; + result(j,C(j)+1) = sum( P([C(j)+1:C(j)+N(j)+1],j) ); + endfor + +endfunction +%!test +%! source("lee_et_al_98.m"); # This is used to check internal functions + +############################################################################## +## Usage: result = lee_et_al_98_acyclic( mu, mu0, C, r, blocking_type ) +## +## This is Algorithm 2, p. 193 [1], and can be used for acyclic networks +## only. The parameters have the exact same meaning as in function +## lee_et_al_98(). +# function result = lee_et_al_98_acyclic( mu_, mu0_, C_, r_, blocking_type_ ) + +# global mu; # mu(1,j) j=1..M is the service rate at S_j +# global C; # C(1,j) j=1..M is the capacity of buffer B_j +# global r; # r(i,j) i=1..M, j=1..M is the routing probability from S_i to S_j +# global C_max; +# global N_max; +# global mu_u; # mu_u(i,j) i=1..N(j), j=1..M is the upstream service rate of S_u i(j) +# global P_b; +# global P_s; +# global P; +# global b_u; +# global mu_d; +# global mu0; +# global blocking_type; + +# blocking_type = blocking_type_; + +# M = size(mu_, 2); ## Number of service centers +# size(C_) == [1,M] || error( "lee_et_al_98() - parameter C must be a (1xM) vector" ); +# size(r_) == [M,M] || error( "lee_et_al_98() - parameter r must be a (MxM) matrix" ); +# size(mu0_) == [1,M] || error( "lee_et_al_98() - parameter mu0 must be a (1,M) vector" ); +# all( C_ > 0 ) || error( "lee_et_al_98() - parameter C must contain elements >0 only" ); +# all( mu_ > 0 ) || error( "lee_et_al_98() - parameter mu must contain elements >0 only" ); + +# mu = [mu_ mu0_]; +# mu0 = mu0_; +# C = C_; +# r = r_; + +# ## Some constants +# global epsilon; +# global iter_count_max; + +# ## Some constants +# C_max = max(C); # Maximum buffer size +# N_max = M+1; +# mu_d = mu_; +# P_b = zeros( M, N_max, M ); ## WARNING: the second index should start from 0, not 1!! +# P = zeros( C_max+N_max+1,M ); ## WARNING: the first index should start from 0m not 1!! +# mu_u = zeros( N_max, M ); +# P_s = zeros( M ); +# b_u = zeros( M, N_max+1, M ); ## WARNING: the second index should start from 0, not 1!! + +# for j = 1:M +# for i = 1:N(j) +# k=f(i,j); +# if ( is_saturated(i,j) ) +# mu_u(i,j) = mu(k); +# else +# mu_u(i,j) = mu(k) * r(k,j); +# endif +# endfor +# endfor + +# ## End initialization step + +# ## Iteration step +# iter_count = 1; + +# do + +# old_mu_u = mu_u; +# old_mu_d = mu_d; + +# ## +# ## Step 1 +# ## +# for j=1:M + +# P(1:C(j)+N(j)+1,j) = compute_P(j)'; + +# ## +# ## 1.1 Calculate P_s(j) using (3) +# ## +# P_s( j ) = compute_P_s( j ); + +# ## +# ## 1.2 Calculate mu_u(i,k) using (7) for all k \in D_j where f(i,k)=j +# ## +# for k=D(j) +# i = f_inverse_i(j,k); +# mu_u(i,k) = compute_mu_u(i,k); +# endfor +# endfor + +# ## +# ## Step 2 +# ## +# for j=M:-1:1 + +# ##P(1:C(j)+N(j)+1,j) = compute_P(j)'; + +# ## +# ## 2.1 Calculate mu_d(j) using (5) +# ## +# mu_d(j) = compute_mu_d(j); + +# ## +# ## 2.2 Calculate P_b i(n:j) using (4) for n=0:N_j-1, i=1:N_j +# ## +# for i=1:N(j) +# for n=1:N(j) +# b_u(i,n+1,j) = compute_b_u(i,n,j); +# endfor +# endfor +# for i=1:N(j) +# for n=0:N(j)-1 +# P_b(i,n+1,j) = compute_P_b( i, n, j ); +# endfor +# endfor +# endfor + +# err1 = abs( old_mu_d - mu_d ); +# err2 = abs( old_mu_u - mu_u ); +# iter_count++; + +# until ( ( (err1 < epsilon) && (err2 < epsilon) ) || (iter_count > iter_count_max) ); + +# fprintf("Converged in %d iterations\n", iter_count ); + +# result = zeros( M, C_max+1 ); +# for j=1:M +# ## P_j = compute_P(j); +# result(j,[1:C(j)]) = P([1:C(j)],j)'; +# result(j,C(j)+1) = sum( P([C(j)+1:C(j)+N(j)+1],j ) ); +# endfor + +# endfunction + + +############################################################################## +## usage: result = f( i, j ) +## +## f(i,j) is the (scalar) index of the ith upstream server directly linked to +## buffer B_j. This function is defined on p. 186 of [1]. Valid ranges +## for the parameters are j=1..M, i=1..N(j). This function aborts on +## parameters out of range. +function result = f( i, j ) + global r; # not modified + ( i>=1 && i <= N(j) ) || error( "f() i-index out of bound" ); + ( j>=1 && j <= size(r,1)) || error( "f() j-index out of bound" ); + result = U(j)(i); +endfunction +%!test +%! global r mu0; +%! r = [0 1 1 0; 0 0 1 1; 0 0 0 1; 1 0 0 0]; +%! mu0 = [1 0 1 0]; +%! assert( f(1,3), 7 ); +%! assert( f(2,3), 1 ); +%! assert( f(3,3), 2 ); + + +############################################################################## +## Usage: result = is_saturated( i,j ) +## +## Returns 1 iff S_u i(j) is a saturated server (i.e., if S_u i(j) +## denotes an external arrival). +function result = is_saturated(i,j) + global r mu0; + M = size(r,2); + if ( f(i,j) > M ) + assert( mu0(f(i,j)-M) > 0 ); + assert( i == 1 ); + result = 1; + else + result = 0; + endif +endfunction +%!test +%! global r mu0; +%! r = [0 1 1 0; 0 0 1 1; 0 0 0 1; 1 0 0 0]; +%! mu0 = [1 0 1 0]; +%! assert( is_saturated(1,3), 1 ); +%! assert( is_saturated(1,1), 1 ); +%! assert( is_saturated(2,3), 0 ); +%! assert( is_saturated(3,3), 0 ); + + +############################################################################## +## usage: result = f_inverse_i( k, j ) +## +## Returns the (scalar) index i such that f(i,j) = k. That is, returns the +## "position" of server S_k in the list of upstream servers of S_j. +## Valid ranges for the parameters are k=1..M, j=1..M. This function +## aborts on parameters out of range. It also aborts if no index i +## exists such that f(i,j) = k. +function result = f_inverse_i( k, j ) + global r; # never modified + ( j>=1 && j<=size(r,1) ) || error( "f_inverse_i() - j parameter out of range" ); + result = find( U(j) == k ); + ( !isempty(result) ) || error( "f_inverse_i() - could not find inverse" ); + ( f(result,j) == k ) || error( "f_inverse_i() - wrong result" ); +endfunction +%!test +%! global r mu0; +%! r = [0 1 1 0; 0 0 1 1; 0 0 0 1; 1 0 0 0]; +%! mu0 = [1 0 1 0]; +%! assert( f_inverse_i(7,3), 1 ); +%! assert( f_inverse_i(1,3), 2 ); +%! assert( f_inverse_i(2,3), 3 ); + + +############################################################################## +## usage: result = omega( n, j ) +## +## Computes the scalar value \Omega_n(j), as defined on [1] p. 188. This +## function examines the global variable blocking_type to determine +## which variant of \Omega_n should be computed, and returns the +## appropriate result. +function result = omega( n, j ) + if ( get_blocking_type(j) == 0 ) + result = omega_BAS( n, j ); + else + result = omega_RSB( n, j ); + endif +endfunction + + +############################################################################## +## usage: result = omega_prime( n, i, j ) +## +## Computes the scalar value \Omega^i_n(j), as defined on [1] p. 189. +## This function examines the global variable blocking_type to determine +## which variant of \Omega^i_n should be computed, and returns the +## appropriate result. +function result = omega_prime( n, i, j ) + if ( get_blocking_type(j) == 0 ) + result = omega_prime_BAS( n, i, j ); + else + result = omega_prime_RSB( n, i, j ); + endif +endfunction + + +############################################################################## +## usage: omega_BAS( n, j ) +## +## Computes \Omega_n according to the upper part of Fig. 5, p. 188 on +## [1]. This function implements the Blocking-After-Service version of +## \Omega_n. Valid ranges for the parameter are n=0..N(j), j=1..M. This +## function aborts on parameters out of range. Note that \Omega_0 is +## defined to be 1, according to [2], p. 1125 +function result = omega_BAS( n, j ) + global mu_u; + + ( n>=0 && n<=N(j) ) || error( "omega_BAS() n parameter is invalid" ); + ( j>=1 && j<=size(mu_u,2) ) || error( "omega_BAS() j parameter is invalid" ); + + if ( n == 0 ) + result = 1; + else + combs = nchoosek( [1:N(j)], n ); + el = mu_u( :, j )'; # Gets the array of elements of the j-th column + result = sum( prod( el( combs ), 2 ) ); + endif +endfunction +%!test +%! global mu_u r mu mu0; +%! M=3; +%! mu_u = 10*rand(M); # to amplify errors +%! r = ones(M); +%! mu = zeros(1,2*M); +%! mu0 = zeros(1,M); +%! expected_result = mu_u(1,2)*mu_u(2,2) + mu_u(1,2)*mu_u(3,2) + mu_u(2,2)*mu_u(3,2); +%! assert(omega_BAS(2,2), expected_result); +%! assert(omega_BAS(0,2),1); + + +############################################################################## +## usage: result = omega_prime_BAS( n, i, j ) +## +## Computes \Omega^i_n for BAS blocking, according to [1], p. 189. +function result = omega_prime_BAS( n, i, j ) + global mu_u; # not modified + + ( i>0 && i<=N(j) ) || error( "omega_prime_BAS() i-index out of range" ); + ( j>0 && j<=size(mu_u,2) ) || error( "omega_prime_BAS() j-index out of range" ); + ( n>=0 && n<N(j) ) || error( "omega_prime_BAS() n-index out of range" ); + + if ( n == 0 ) + result = 1; + else + combs = nchoosek( [ 1:i-1 , i+1:N(j)], n ); + el = mu_u( :, j )'; # Gets the array of elements of the j-th column + result = sum( prod( el( combs ), 2 ) ); + endif +endfunction +%!test +%! global mu_u r mu mu0; +%! mu_u = 10*rand(3); # to aplify errors +%! mu = zeros(1,6); +%! mu0 = zeros(1,3); +%! r = ones(3); +%! M = 3; +%! assert(omega_prime_BAS(2,2,2), prod(mu_u([1,3],2)) ); +%! assert(omega_prime_BAS(2,1,2), prod(mu_u([2,3],2)) ); +%! assert( omega_prime_BAS(0,1,1), 1 ); + +%!test +%! global mu_u r mu mu0; +%! M=4; +%! mu_u = rand(M); +%! mu = zeros(1,2*M); +%! mu0 = zeros(1,M); +%! r = ones(M); +%! assert( omega_prime_BAS(3,1,3), prod([ mu_u(2,3) mu_u(3,3) mu_u(4,3) ]) ); + + +############################################################################## +## Usage: result = omega_RSB( n, j ) +## +## Computes \Omega_n for Repetitive-Service blocking, according to [1], +## fig. 6 p. 188. +function result = omega_RSB( n, j ) + global mu_u; + + ( n>=0 && n<=N(j) ) || error( "omega_RSB() n parameter is invalid" ); + ( j>0 && j<=size(mu_u,2) ) || error( "omega_RSB() j parameter is invalid" ); + + if ( n == 0 || n == N(j) ) ## FIEME??? + result = 1; + else + combs = nchoosek( [2:N(j)], n ); + el = (mu_u( :, j )'); # Gets the array of elements of the j-th column + result = sum( prod( el( combs ), 2 ) ); + endif +endfunction +%!test +%! global mu_u r mu mu0; +%! M=4; +%! mu_u = rand(M); +%! mu = zeros(1,2*M); +%! mu0 = zeros(1,M); +%! r = ones(M); +%! tmp = mu_u(:,2)'; +%! expected_result = sum( prod( tmp( [ 2 3; 2 4; 3 4 ] ), 2 ) ); +%! assert(omega_RSB(2,2), expected_result); +%! assert(omega_RSB(0,2), 1); + + +############################################################################## +## Usage: result = omega_prima_RSB( n, i, j ) +## +## Computes \Omega^i_n for Repetitive-Service blocking, according to +## [1], p. 189. Note the following assumption: we assume that +## omega_prime_RSB( i, B(j)-1, j ) == 1, even if the value of +## omega_prime_RSB for this special case is not considered in [1]. +function result = omega_prime_RSB( n, i, j ) + global mu_u; + + ( i>0 && i<=N(j) ) || error( "omega_prime_RSB() i-index out of range" ); + ( j>0 && j<=size(mu_u,2) ) || error( "omega_prime_RSB() j-index out of range" ); + ( n>=0 && n<N(j) ) || error( "omega_prime_RSB() n-index out of range" ); + + if ( n == 0 || n == N(j)-1 ) ## FIXME??? + result = 1; + else + combs = nchoosek( [ 2:i-1 , i+1:N(j)], n ); + el = (mu_u( :, j )'); # Gets the array of elements of the j-th column + result = sum( prod( el( combs ), 2 ) ); + endif +endfunction +%!test +%! global mu_u r mu mu0; +%! M=4; +%! mu_u = rand(M); +%! mu = zeros(1,2*M); +%! mu0 = zeros(1,M); +%! r = ones(M); +%! tmp = mu_u(:,2)'; +%! expected_result = mu_u(2,2)*mu_u(3,2) + mu_u(2,2)*mu_u(4,2) + mu_u(3,2)*mu_u(4,2); +%! assert(omega_prime_RSB(2,1,2), expected_result); +%! assert(omega_prime_RSB(2,2,2), mu_u(3,2)*mu_u(4,2) ); +%! assert(omega_prime_RSB(2,3,2), mu_u(2,2)*mu_u(4,2) ); +%! assert(omega_prime_RSB(0,1,2), 1); + +############################################################################## +## Usage: compute_mu_u(i,j) +## +## Uses eq (7) from [1] to compute \mu_u i (j), i=1..M, j=1..M. The +## result is a scalar value. WARNING: eq (7) is porbably wrong, as it is +## different from the one used in Lemma 1, p. 191 [1]. Here we use +## 1/mu_d(k) instead of 1/mu(k). +function result = compute_mu_u( i, j ) + global mu P_s r P_b mu_d mu_u; + + k = f(i,j); + assert( k<=size(r,1) ); + mu_star_k = sum( mu_u([1:N(k)],k) ); + +# result = r(k,j)/(P_s(k)/mu_star_k + 1/mu(k) - +# r(k,j)* +# sum( P_b(i,[1:N(j)],j) .* [1:N(j)]) / mu_d(j)); + + ## FIXME! Equation (7) is probably wrong. Check Lemma 1 p. 191 + result = r(k,j)/(P_s(k)/mu_star_k + 1/mu_d(k) - r(k,j)*sum( P_b(i,[1:N(j)],j) .* [1:N(j)])/mu_d(j)); +endfunction + + +############################################################################## +## Usage: result = compute_mu_d(j) +## +## Uses eq. (5) from [1] to compute \mu_d (j), j=1..M. The result is a +## scalar value. WARNING: Eq (5) is probably wrong: here we use sum( +## P_b(k,[1:N(m)],m) .* [1:N(m)] ) instead of sum( P_b(k,[1:N(j)],m) .* +## [1:N(j)] ). +function result = compute_mu_d( j ) + global mu_d P_b mu r; + + ( j>0 && j <= size(r,1)) || error( "compute_mu_d() - j index out of bound" ); + + s = 0; + for m=D(j) + k = f_inverse_i(j,m); + ## s += r(j,m) * sum( P_b(k,[1:N(j)],m) .* [1:N(j)] ) / mu_d(m); + + ## FIXME: Cambiato in accordo alla tesi di Bovino + s += r(j,m) * sum( P_b(k,[1:N(m)],m) .* [1:N(m)] ) / mu_d(m); + endfor + result = 1/( 1/mu(j) + s ); + ## If j is an exit server, then result must be equal to mu(j) + if ( size( D(j), 2 ) == 0 ) + assert( result, mu(j) ); + endif +endfunction + + +############################################################################## +## Usage: result = compute_P_s(j) +## +## Uses eq. (3) from [1] to compute P_s(j), j=1..M. P_s(j) is the +## probability that S_d(j) is starved (i.e., is empty) at the service +## completion instant. +function result = compute_P_s( j ) + global r P; + #P = compute_P(j); + M = size(r,2); + (j>=1 && j<=M) || error( "compute_P_s() - j index out of bound" ); + result = P(2,j) / ( 1 - P(1,j) ); +endfunction + + +############################################################################## +## Usage: result = compute_P(j) +## +## Computes P(n:j) by solving the appropriate birth-death process. This +## function returns a (1 x C(j)+N(j)+1 ) vector, where result(i) == +## P(i+1,j), i = 1..C(j)+N(j)+1 +function result = compute_P( j ) + global C; + if ( get_blocking_type(j) == 0 ) + result = compute_P_BAS(j); + else + result = compute_P_RSB(j); + endif + ## Check that successive marginal probabilities for nonblocking + ## states are equal each other. This is stated in [2], p. 1126 + if ( C(j) >= 3 ) + for i=0:C(j)-2 + assert( result(i+2)/result(i+1), result(i+3)/result(i+2), 1e-4 ); + endfor + endif +endfunction + + +############################################################################## +## Usage: result = compute_P_BAS(j) +## +## Compute P(n,j) for each n=0..C(j)+N(j) by solving the birth-death +## process. Returns a (1 x 1+C(j)+N(j)) vector +function result = compute_P_BAS( j ) + global mu_u mu_d C; + assert( get_blocking_type(j) == 0 ); + + ## Defines the transition probability matrix for the MC + mu_star_j = sum( mu_u([1:N(j)],j) ); + assert( mu_star_j, sum( mu_u(:,j) ) ); + + ## computes the steady-state probability + birth = zeros( 1, C(j)+N(j) ); + death = mu_d(j) * ones( 1, C(j)+N(j) ); + birth(1,[1:C(j)] ) = mu_star_j; + for i=1:N(j) + birth( 1, C(j)+i ) = i*omega_BAS(i,j)/omega_BAS(i-1,j); + endfor + result = ctmc_bd_solve( birth, death ); +endfunction + + +############################################################################## +## Usage: result = compute_P_RSB( j ) +## +## Same as compute_P, for Repetitive-service blocking +function result = compute_P_RSB( j ) + global mu_u mu_d C; + assert( get_blocking_type(j) != 0 ); + + ## Defines the transition probability matrix for the MC + mu_star_j = sum( mu_u([1:N(j)],j) ); + assert( mu_star_j, sum( mu_u(:,j) ) ); + + ## computes the steady-state probability + birth = zeros( 1, C(j)+N(j)-1 ); + death = mu_d(j) * ones( 1, C(j)+N(j)-1 ); + birth(1,[1:C(j)] ) = mu_star_j; + for i=1:N(j)-1 + birth( 1, C(j)+i ) = i*omega_RSB(i,j)/omega_RSB(i-1,j); + endfor + result = [ ctmc_bd_solve( birth, death ) 0 ]; +endfunction + + +############################################################################## +## Usage: result = compute_P_b( i, n, j ) +## +## Compute P_b i(n:j) using (4), where n=0..N(j)-1, i=1..N(j), j=1..M +## The result is a scalar value. +function result = compute_P_b( i,n,j ) + global b_u C P; + + ( n >= 0 && n < N(j) ) || error( "compute_P_b() - n index out of bound" ); + ( i >= 1 && i <= N(j) ) || error( "compute_P_b() - i index out of bound" ); + ## P = compute_P(j); + M = size(C,2); + + result = ( P(C(j)+n+1,j) - b_u(i,n+1,j) ) / ( 1 - sum( b_u( i, [2:(N(j)+1)], j ) ) ); + ## FIXME: the next seems necessary +# if ( get_blocking_type(j) == 1 && n == N(j)-1 ) +# assert( result, 0 ); +# endif +endfunction + + +############################################################################## +## Usage: result = compute_b_u(i,n,j) +## +## Compute b_u i(n:j) using (1), i=1..M, n=0..N(j), j=1..M. The result +## is a single scalar element. According to [2], we let b_u i(0:j) = 0. +function result = compute_b_u(i,n,j) + global mu_u C P; + M = size( C,2 ); + ( i>0 && i<=M ) || error( "compute_b_u() - i index out of bound" ); + ( j>0 && j<=M ) || error( "compute_b_u() - j index out of bound" ); + ( n >= 0 && n <= N(j) ) || error( "compute_b_u() - n index out of bound" ); + if ( n == 0 ) + result = 0; + else + ## P = compute_P( j ); + result = mu_u(i,j) * omega_prime( n-1,i,j ) / omega(n,j) * P(C(j)+n+1,j); + endif + if ( get_blocking_type(j) == 1 && n == N(j) ) + assert( result, 0 ); + endif +endfunction + + +############################################################################## +## Usage: result = U( i ) +## +## Returns a vector of the i-th element in the set U, that is, returns +## the index of the upstream servers for S_i, i=1..M +## +## @param r the MxM routing matrix +## +## @param mu0 the vector of external arrivals +function result = U( i ) + global r mu0; + M = size(r,2); + ( i>0 && i<=M ) || error( "U() - i index out of bound" ); + result = find( r(:,i) > 0 )'; + if ( mu0( i ) > 0 ) + result = [ M+i result ]; + endif +endfunction +%!test +%! global r mu0; +%! r = [0 1 1 0; 0 0 1 1; 0 0 0 1; 1 0 0 0]; +%! mu0 = [1 0 1 0]; +%! assert( U(1), [5 4] ); +%! assert( U(3), [7 1 2] ); + + +############################################################################## +## Usage: result = D( i ) +## +## Given the routing matrix r, computes the downstream index set D_i. +## D_i is defined as the set of indexes of downstream servers directly +## connected with S_i. +function result = D( i ) + global r; + ( i>0 && i<=size(r,1) ) || error( "D() - i index out of bound" ); + result = find( r(i,:) > 0 ); +endfunction +%!test +%! global r; +%! r = [0 1 1 0; 0 0 1 1; 0 0 0 1; 1 0 0 0]; +%! assert( D(2), [3 4] ); + + +############################################################################## +## Usage: result = N( i ) +## +## Returns a scalar representing the number of upstream servers of S_i, +## that is, returns the number of elements in U(i); i=1..M +function result = N( i ) + global r; + ( (i>0) && (i<=size(r,1)) ) || error( "N() - i index out of bound" ); + result = size( U(i), 2 ); +endfunction +%!test +%! global r mu0; +%! r = [0 1 1 0; 0 0 1 1; 0 0 0 1; 1 0 0 0]; +%! mu0 = [1 0 1 0]; +%! assert( N(1), 2 ); +%! assert( N(3), 3 ); + + +############################################################################## +## Usage: result = get_blocking_type( j ) +## +## Returns the blocking type for server S_u1(j); result == 0 means BAS, +## result == 1 means RSB. +function result = get_blocking_type( j ) + global r mu0 blocking_type; + M = size(r,2); + ## If blocking_type(j) != 0 and mu0(j) > 0, then result == 1 + ## (Repetitive-Service Blocking). Otherwise, result == 0 (BAS) + ( j >= 1 && j <= size(mu0,2) ) || error( "get_blocking_type() - j \ + parameter out of bounds" ); + if ( f(1,j) <= M ) + result = 0; # non-saturated servers are always BAS + return + endif + k = f(1,j) - M; + assert( mu0(k) > 0 ); + if ( blocking_type(k) != 0 ) + result = 1; # repetitive-service blocking + else + result = 0; # BAS + endif +endfunction +%!test +%! global r mu0 blocking_type; +%! r = [0 1 1 0; 0 0 1 1; 0 0 0 1; 1 0 0 0]; +%! mu0 = [1 0 1 0]; +%! blocking_type = [1 0 1 0]; +%! assert( get_blocking_type(1), 1 ); +%! assert( get_blocking_type(2), 0 ); +%! assert( get_blocking_type(3), 1 ); +%! assert( get_blocking_type(4), 0 ); + +# %!test +# %! r = [0 0.35 0.35; 0 0 0.65; 0 0 0]; +# %! C = [ 2 2 3 ]; +# %! mu = [ 2 1.5 1 ]; +# %! mu0 = [ 1.2 0.3 0.2 ]; +# %! P1 = lee_et_al_98( mu, mu0, C, r, [ 1 1 1 ] ); +# %! P2 = lee_et_al_98_acyclic( mu, mu0, C, r, [ 1 1 1 ] ); +# %! assert( P1, P2, 1e-4 ); + + +############################################################################## +## Usage: compute_X_u(i,j) +## +## Computes X_ui(j) using eq. (10) from Lee et al. [1] +function result = compute_X_u(i,j) + global P_b mu_d mu_u; + result = 1/( 1/mu_u(i,j) + 1/mu_d(j) * dot( P_b(i,[1:N(j)],j), [1:N(j)] ) ); +endfunction + + +############################################################################## +## Usage: compute_X_d(k) +## +## Computes X_d(k) using eq. (9) from Lee et al. [1] +function result = compute_X_d(k) + global P_s mu_d mu_u; + mu_star_k = sum(mu_u([1:N(k)],k)); + result = 1/( 1/mu_d(k) + P_s(k)/mu_star_k ); +endfunction + + +############################################################################## +## Usage: print_header() +## +## Prints the header used for the demo results +function print_header() + printf("%10s\t%5s\t%5s %5s\t%5s %5s %4s\n", \ + "Param", "Exact", "This", "Err%", "Paper", "Err%", "Res" ); +endfunction + + +############################################################################## +## Usage: compare( param, simulation, result, paper) +## +## This is a function used in the demos +## +## @param param The string representing the parameter name +## +## @param simulation The simulation result shown in the paper +## +## @param result The result computed by this implementation +## +## @param paper The result copmputed by the algorithm shown in the paper +function compare( param, simulation, result, paper ) + + err_res = ( result - simulation ) / simulation * 100; + err_pap = ( paper - simulation ) / simulation * 100; + tolerance = 1e-3; + + if ( abs( result - paper ) < tolerance ) + test_result = "PASS"; + else + test_result = "FAIL"; + endif + printf("%10s\t%5.3f\t%5.3f %5.1f\t%5.3f %5.1f %4s\n", param, simulation, result, err_res, paper, err_pap, test_result ); + +endfunction + +############################################################################## +### +### Start "real" tests +### + +%!demo +%! disp("Table V, p. 1130 Lee & Pollock [2]"); +%! r = [ 0 0.4 0.4; \ +%! 0 0 0.7; \ +%! 0 0 0 ]; +%! C = [ 20 2 2 ]; +%! mu = [ 2 2 2 ]; +%! mu0 = [ 1.5 0 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 1 0 0 ] ); +%! assert( get_blocking_type(1), 1 ); +%! assert( get_blocking_type(2), 0 ); +%! assert( get_blocking_type(3), 0 ); +%! assert( f(1,1), 4 ); +%! assert( f(1,2), 1 ); +%! assert( f(1,3), 1 ); +%! assert( f(2,3), 2 ); +%! print_header(); +%! compare( "P_1(0)", 0.1560, result(1,1), 0.1516 ); +%! compare( "P_1(1)", 0.1297, result(1,2), 0.1287 ); +%! compare( "P_1(2)", 0.1085, result(1,3), 0.1091 ); +%! compare( "P_1(3)", 0.0914, result(1,4), 0.0926 ); +%! compare( "P_1(4)", 0.0772, result(1,5), 0.0786 ); +%! compare( "P_1(5)", 0.0654, result(1,6), 0.0666 ); +%! compare( "P_2(0)", 0.6557, result(2,1), 0.6473 ); +%! compare( "P_2(1)", 0.2349, result(2,2), 0.2357 ); +%! compare( "P_2(2)", 0.1094, result(2,3), 0.1170 ); +%! compare( "P_3(0)", 0.4901, result(3,1), 0.4900 ); +%! compare( "P_3(1)", 0.2667, result(3,2), 0.2662 ); +%! compare( "P_3(2)", 0.2431, result(3,3), 0.2438 ); + +%!demo +%! disp("Table IV, p. 1130 Lee & Pollock [2]"); +%! r = [ 0 0.4 0.4; \ +%! 0 0 0.5; \ +%! 0 0 0 ]; +%! C = [ 1 1 1 ]; +%! mu = [ 1 1 1 ]; +%! mu0 = [ 3.0 0 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 1 0 0 ] ); +%! print_header(); +%! compare( "P_1(0)", 0.2154, result(1,1), 0.2092 ); +%! compare( "P_1(1)", 0.7846, result(1,2), 0.7909 ); +%! compare( "P_2(0)", 0.7051, result(2,1), 0.6968 ); +%! compare( "P_2(1)", 0.2949, result(2,2), 0.3032 ); +%! compare( "P_3(0)", 0.6123, result(3,1), 0.6235 ); +%! compare( "P_3(1)", 0.3877, result(3,2), 0.3765 ); + +%!demo +%! disp("Table X first group, p 1132 Lee & Pollock [2]"); +%! r = [0 0.35 0.35; \ +%! 0 0 0.65; \ +%! 0 0 0 ]; +%! C = [ 5 4 3 ]; +%! mu = [ 1 1 1 ]; +%! mu0 = [ 2 0.2 0.1 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 1 1 1 ] ) +%! print_header(); +%! compare( "P_1(5)", 0.558, result(1,6), 0.558 ); +%! compare( "P_2(4)", 0.074, result(2,5), 0.074 ); +%! compare( "P_3(3)", 0.279, result(3,4), 0.282 ); + +%!demo +%! disp("Table X, second group, p. 1132 Lee & Pollock [2]"); +%! r = [0 0.35 0.35; \ +%! 0 0 0.65; \ +%! 0 0 0 ]; +%! C = [ 2 2 3 ]; +%! mu = [ 2 1.5 1 ]; +%! mu0 = [ 1.2 0.3 0.2 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 1 1 1 ] ) +%! print_header(); +%! compare( "P_1(2)", 0.269, result(1,3), 0.272 ); +%! compare( "P_2(2)", 0.193, result(2,3), 0.206 ); +%! compare( "P_3(3)", 0.374, result(3,4), 0.391 ); + +%!demo +%! disp("Table 1 first group, p. 195 Lee & al. [1]"); +%! r = [0 1 0; \ +%! 0 0 1; \ +%! 0.1 0 0 ]; +%! C = [ 2 2 2 ]; +%! mu = [ 1 1 1 ]; +%! mu0 = [ 1 0 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 1 0 0 ] ) +%! print_header(); +%! compare( "P_1(0)", 0.206, result(1,1), 0.210 ); +%! compare( "P_1(2)", 0.458, result(1,3), 0.483 ); +%! compare( "P_2(0)", 0.265, result(2,1), 0.287 ); +%! compare( "P_2(2)", 0.450, result(2,3), 0.452 ); +%! compare( "P_3(0)", 0.376, result(3,1), 0.389 ); +%! compare( "P_3(2)", 0.334, result(3,3), 0.335 ); + +%!demo +%! disp("Table 1, second group, p. 195 Lee & al. [1]"); +%! r = [0 1 0; \ +%! 0 0 1; \ +%! 0.1 0 0 ]; +%! C = [ 1 1 1 ]; +%! mu = [ 1.5 1.5 1.5 ]; +%! mu0 = [ 1 0 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 1 0 0 ] ) +%! print_header(); +%! compare( "P_1(0)", 0.510, result(1,1), 0.478 ); +%! compare( "P_1(1)", 0.490, result(1,2), 0.522 ); +%! compare( "P_2(0)", 0.526, result(2,1), 0.532 ); +%! compare( "P_2(1)", 0.474, result(2,2), 0.468 ); +%! compare( "P_3(0)", 0.610, result(3,1), 0.620 ); +%! compare( "P_3(1)", 0.390, result(3,2), 0.380 ); + +%!demo +%! disp("Table 2, first group, p. 196 Lee & al. [1]"); +%! r = [0 0.2 0.2 0.3; \ +%! 0 0 0.6 0.3; \ +%! 0 0 0 0.8; \ +%! 0.1 0 0 0 ]; +%! C = [ 1 1 1 1 ]; +%! mu = [ 1 0.5 0.5 1 ]; +%! mu0 = [ 1 0.2 0.2 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 1 1 1 0 ] ) +%! print_header(); +%! compare( "P_1(0)", 0.364, result(1,1), 0.338 ); +%! compare( "P_1(1)", 0.636, result(1,2), 0.662 ); +%! compare( "P_2(0)", 0.490, result(2,1), 0.477 ); +%! compare( "P_2(1)", 0.510, result(2,2), 0.523 ); +%! compare( "P_3(0)", 0.389, result(3,1), 0.394 ); +%! compare( "P_3(1)", 0.611, result(3,2), 0.606 ); +%! compare( "P_4(0)", 0.589, result(4,1), 0.589 ); +%! compare( "P_4(1)", 0.411, result(4,2), 0.411 ); + +%!demo +%! disp("Table 3, left column, p. 197 Lee & al. [1]"); +%! r = [0 0.3 0 0 0.3 0 0 0.4; \ +%! 0 0 1 0 0 0 0 0; \ +%! 0 0 0 1 0 0 0 0; \ +%! 0 0.1 0 0 0 0 0 0.9; \ +%! 0 0 0 0 0 1 0 0; \ +%! 0 0 0 0 0 0 1 0; \ +%! 0 0 0 0 0.1 0 0 0.9; \ +%! 0 0 0 0 0 0 0 0 ]; +%! C = [ 2 2 2 2 2 2 2 2 ]; +%! mu = [ 1.5 1 1 1 1 1 1 1.5 ]; +%! mu0 = [ 1 0.2 0 0 0.2 0 0 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 0 0 0 0 0 0 0 0] ) +%! global mu_d; +%! assert( mu_d(8), mu(8) ); +%! print_header(); +%! compare( "P_1(0)", 0.220, result(1,1), 0.221 ); +%! compare( "P_1(2)", 0.547, result(1,3), 0.539 ); +%! compare( "P_2(0)", 0.434, result(2,1), 0.426 ); +%! compare( "P_2(2)", 0.306, result(2,3), 0.309 ); +%! compare( "P_3(0)", 0.415, result(3,1), 0.406 ); +%! compare( "P_3(2)", 0.315, result(3,3), 0.318 ); +%! compare( "P_4(0)", 0.377, result(4,1), 0.373 ); +%! compare( "P_4(2)", 0.348, result(4,3), 0.352 ); +%! compare( "P_5(0)", 0.434, result(5,1), 0.426 ); +%! compare( "P_5(2)", 0.305, result(5,3), 0.309 ); +%! compare( "P_6(0)", 0.416, result(6,1), 0.406 ); +%! compare( "P_6(2)", 0.315, result(6,3), 0.318 ); +%! compare( "P_7(0)", 0.376, result(7,1), 0.373 ); +%! compare( "P_7(2)", 0.363, result(7,3), 0.352 ); +%! compare( "P_8(0)", 0.280, result(8,1), 0.274 ); +%! compare( "P_8(2)", 0.492, result(8,3), 0.492 ); + +############################################################################## +## +## This is the first bunch of tests. Here we compare the result from the +## Lee et al. algorithm with those obtained from the (exact) MVA for +## open, single class networks. Assuming that there is enough buffer +## space in the original network, the result from Lee et al and MVA +## should be almost exactly the same. + +%!test +%! #printf("Simple tandem network with enough buffer space"); +%! r = [ 0 1 0; \ +%! 0 0 1; \ +%! 0.1 0 0]; +%! C = 20 * ones(1,3); +%! mu=[ 2 2 2 ]; +%! mu0=[ 1 0 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [1 0 0] ); +%! Q_lee = zeros(1,3); +%! [U R Q_mva] = qnopen( 1, 1 ./ mu, qnvisits(r, mu0) ); +%! for i=1:3 +%! Q_lee(i) = dot( result(i,:), [0:C(i)] ); +%! #printf("Q(%d) Lee=%5.3f MVA=%5.3f\n", i, Q_lee(i), Q_mva(i) ); +%! assert( Q_lee(i), Q_mva(i), 1e-4 ); +%! endfor + +%!test +%! #printf("Table 2, third group, p. 196 Lee & al. [1], enough buffer space"); +%! r = [0 0.2 0.2 0.3; \ +%! 0 0 0.6 0.3; \ +%! 0 0 0 0.8; \ +%! 0.1 0 0 0 ]; +%! C = 20*ones(1,4); +%! mu = [ 2 1 1 2 ]; +%! mu0 = [ 1 0.2 0.2 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [ 1 1 1 0 ] ); +%! Q_lee = zeros(1,4); +%! [U R Q_mva] = qnopen( 1, 1 ./ mu, qnvisits(r, mu0 ) ); +%! for i=1:4 +%! Q_lee(i) = dot( result(i,:), [0:C(i)] ); +%! #printf("Q(%d) Lee=%5.3f MVA=%5.3f\n", i, Q_lee(i), Q_mva(i) ); +%! assert( Q_lee(i), Q_mva(i), 1e-2 ); +%! endfor + +%!test +%! #printf("Table 3, right column, p. 197 Lee & al. [1], enough buffer space"); +%! r = [0 0.3 0 0 0.3 0 0 0.4; \ +%! 0 0 1 0 0 0 0 0; \ +%! 0 0 0 1 0 0 0 0; \ +%! 0 0.1 0 0 0 0 0 0.9; \ +%! 0 0 0 0 0 1 0 0; \ +%! 0 0 0 0 0 0 1 0; \ +%! 0 0 0 0 0.1 0 0 0.9; \ +%! 0 0 0 0 0 0 0 0 ]; +%! C = 20*ones(1,8); +%! mu = [ 2 1.5 1.5 1.5 1.5 1.5 1.5 2 ]; +%! mu0 = [ 1 0.2 0 0 0.2 0 0 0 ]; +%! result = lee_et_al_98( mu, mu0, C, r, [0 0 0 0 0 0 0 0] ); +%! Q_lee = zeros(1,8); +%! [U R Q_mva] = qnopen( 1, 1./ mu, qnvisits(r, mu0) ); +%! for i=1:8 +%! Q_lee(i) = dot( result(i,:), [0:C(i)] ); +%! #printf("Q(%d) Lee=%5.3f MVA=%5.3f\n", i, Q_lee(i), Q_mva(i) ); +%! assert( Q_lee(i), Q_mva(i), 1e-2 ); +%! endfor + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/broken/qnmmmk_alt.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,162 @@ +## Copyright (C) 2009 Dmitry Kolesnikov +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U} @var{R} @var{Q} @var{X} @var{p0} @var{pK}] =} qnmmmk_alt (@var{lambda}, @var{mu}, @var{m}, @var{K} ) +## +## @cindex @math{M/M/m/K} system +## +## Compute utilization, response time, average number of requests and +## throughput for a @math{M/M/m/K} finite capacity system. In a +## @math{M/M/m/K} queue there are @math{m \geq 1} service centers. At any +## moment, at most @math{K} requests can be in the system, @math{K +## \geq m}. +## +## @iftex +## +## The steady-state probability @math{\pi_k} that there are @math{k} +## jobs in the system, @math{0 \leq k \leq K} can be expressed as: +## +## @tex +## $$ +## \pi_k = \cases{ \displaystyle{{\rho^k \over k!} \pi_0} & if $0 \leq k \leq m$;\cr +## \displaystyle{{\rho^m \over m!} \left( \rho \over m \right)^{k-m} \pi_0} & if $m < k \leq K$\cr} +## $$ +## @end tex +## +## where @math{\rho = \lambda/\mu} is the offered load. The probability +## @math{\pi_0} that the system is empty can be computed by considering +## that all probabilities must sum to one: @math{\sum_{k=0}^K \pi_k = 1}, +## which gives: +## +## @tex +## $$ +## \pi_0 = \left[ \sum_{k=0}^m {\rho^k \over k!} + {\rho^m \over m!} \sum_{k=m+1}^K \left( {\rho \over m}\right)^{k-m} \right]^{-1} +## $$ +## @end tex +## +## @end iftex +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## +## Arrival rate (jobs/@math{s}, @code{@var{lambda}>0}). +## +## @item mu +## +## Service rate (jobs/@math{s}, @code{@var{mu}>0}). +## +## @item m +## +## Number of servers (@code{@var{m}>=1}). +## +## @item k +## +## Maximum number of requests allowed in the system (@code{@var{k} >= @var{m}}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## +## Service center utilization +## +## @item R +## +## Service center response time +## +## @item Q +## +## Average number of requests in the system +## +## @item X +## +## Service center throughput +## +## @item p0 +## +## Probability that there are no requests in the system. +## +## @item pK +## +## Probability that there are @math{K} requests in the system (i.e., +## probability that the system is full). +## +## @end table +## +## @var{lambda}, @var{mu}, @var{m} and @var{K} can be vectors of the +## same size. In this case, the results will be vectors as well. +## +## @seealso{qnmm1,qnmminf,qnmmm} +## +## @end deftypefn + +## Author: Dmitry Kolesnikov +function [U R Q X p0 pm pk] = qnmmmk_alt( lambda, mu, m, k) + if ( nargin != 4 ) + print_usage(); + endif + [err lambda mu m k] = common_size( lambda, mu, m, k ); + if ( err ) + error( "Parameters are not of common size" ); + endif + + ( isvector(lambda) && isvector(mu) && isvector(m) && isvector(k) ) || ... + error( "lambda, mu, m, k must be vectors of the same size" ); + all( k>0 ) || \ + error( "k must be strictly positive" ); + all( m>0 ) && all( m <= k ) || \ + error( "m must be in the range 1:k" ); + all( lambda>0 ) && all( mu>0 ) || \ + error( "lambda and mu must be >0" ); + + rho = lambda ./ mu; + i1 = 0:m; # range + i2 = (m+1):k; # range + p0 = 1 / ( sum( rho .^ i1 ./ factorial(i1) ) + rho^m/factorial(m)*sum( (rho/m).^(i2-m) ) ); + pm = p0 * (rho)^m / factorial(m); + pk = p0 * rho^k / (factorial(m) * m^(k-m)); + Q = (sum( i1 .* rho .^ i1 ./ factorial(i1) ) + ... + rho^m/factorial(m)*sum( i2.*((rho/m).^(i2-m)) ))*p0; + X = lambda*(1-pk); + U = X ./ (m .* mu ); + R = Q./X; + +endfunction +%!test +%! lambda = 0.8; +%! mu = 0.85; +%! k = 5; +%! [U1 R1 Q1 X1 p01 pm pk1] = qnmmmk_alt( lambda, mu, 1, k ); +%! [U2 R2 Q2 X2 p02 pk2] = qnmm1k( lambda, mu, k ); +%! assert( [U1 R1 Q1 X1 p01 pk1], [U2 R2 Q2 X2 p02 pk2], 1e-5 ); + +%!test +%! lambda = 0.8; +%! mu = 0.85; +%! m = 3; +%! k = 5; +%! [U1 R1 Q1 X1 p01] = qnmmmk_alt( lambda, mu, m, k ); +%! [U2 R2 Q2 X2 p02] = qnmmmk( lambda, mu, m, k ); +%! assert( [U1 R1 Q1 X1 p01], [U2 R2 Q2 X2 p02], 1e-5 );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/broken/qnopenmultig.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,238 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopenmultig (@var{lambda}, @var{c2lambda}. @var{mu}, @var{c2mu}, @var{P}) +## +## Approximate analysis of open, multiple-class networks with general +## arrival and service time distributions (@code{qnopenmultig} stands +## for "OPEN, MULTIclass, General"). Single server and multiple server +## nodes are supported. This function assumes a network with @math{K} +## service centers and @math{C} customer classes. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## @code{@var{lambda}(c, k)} is the external +## arrival rate of class @math{c} customers at center @math{k}. +## +## @item c2lambda +## @code{@var{c2lambda}(c, k)} is the squared coefficient of variation of +## class @math{c} arrival rate at center @math{k} +## +## @item mu +## @code{@var{mu}(c,k)} is the mean service rate of class @math{c} +## customers on the service center @math{k} (@code{@var{S}(c,k)>0}). +## +## @item c2mu +## @code{@var{c2mu}(c,k)} is the squared Coefficient of variation of class +## @math{c} service rate at center @math{k} +## +## @item P +## @code{@var{P}(r,i,s,j)} is the probability that a class @math{r} +## request which completes service at center @math{i} is routed +## to center @math{j} as class @math{s} request. @strong{Class +## switching is not supported}: therefore, @math{P(r,i,s,j) = 0} +## if @math{r \neq s}. +## +## @item m +## @code{@var{m}(k)} is the number of servers at service center +## @math{k}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## @code{@var{U}(c,k)} is the +## class @math{c} utilization of center @math{k}. +## +## @item R +## @code{@var{R}(c,k)} is the class @math{c} response time at +## center @math{k}. The system response time for +## class @math{c} requests can be computed +## as @code{dot(@var{R}, @var{V}, 2)}. +## +## @item Q +## @code{@var{Q}(c,k)} is the average number of class @math{c} requests +## at center @math{k}. The average number of class @math{c} requests +## in the system @var{Qc} can be computed as @code{Qc = sum(@var{Q}, 2)} +## +## @item X +## @code{@var{X}(c,k)} is the class @math{c} throughput +## at center @math{k}. +## +## @end table +## +## @seealso{qnopen,qnopensingle,qnvisits} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ +function [U R Q X] = qnopenmultig( l0, c20, mu, c2, P, m ) + + error("This function is not fully implemented yet"); + + if ( nargin < 5 || nargin > 6 ) + print_usage(); + endif + + ismatrix(l0) || \ + usage("lambda must be a matrix"); + + C = rows(l0); + K = columns(l0); + + size(c20) == size(l0) || \ + usage("c20 must have the same size of lambda"); + + size(mu) == size(l0) || \ + usage("mu must have the same size of lambda"); + + size(c2) == size(l0) || \ + usage("c2 must have the same size of lambda"); + + ismatrix(P) && ndims(P) == 4 && [C,K,C,K] == size(P) || \ + usage("Wrong size of matrix P (I was expecting %dx%dx%dx%d)", C, K, C, K); + + if ( nargin < 6 ) + m = ones(1,K); + else + ( isvector( m ) && length(m) == K && all( m >= 1 ) ) || \ + usage( "m must be >= 1" ); + m = m(:)'; # make m a row vector + endif + + ## Class switching is not allowed. Therefore, to be compliant with the + ## reference above (Bolch et al.), we drop one dimension from matrix P + P_ijr = zeros(K,K,C); + for r=1:C + P_ijr(:,:,r) = P(r,:,r,:); + endfor +#{ + for i=1:K + for j=1:K + for r=1:C + P_ijr(i,j,r) = P(r,i,r,j); + endfor + endfor + endfor +#} + + l = sum(sum(l0)) .* qnvisits(P,l0); + + c2A_ir = c2D_ir = zeros(K,C); + c2A_i_old = c2A_i = c2B_i = c2D_i = zeros(1,K); + c2_ijr = ones(K,K,C); + + ## the implementation that follows is based on Section 10.1.3 (p. + ## 439--441) of Bolch et al. In order to be facilitate debugging, we + ## make ourselves compliant with their notation. This means that class + ## and server indexes need to be swapped, e.g., they use rho(i,r) + ## instead of rho(r,i) to denote the class-r utilization on center i. + + lambda_ir = l'; + lambda0_ir = l0'; + c20_ir = c20'; + c2B_i = c2_ir = c2'; + mu_ir = mu'; + + lambda_i = sum(lambda_ir,2); # lambda_i(i) is the total arrival rate at center i + + rho_ir = zeros(K,C); # rho_ir(i,r) is the class r utilization at center i + for r=1:C # FIXME: parallelize this + for i=1:K + rho_ir(i,r) = lambda_ir(i,r) / ( m(i) * mu_ir(i,r) ); + endfor + endfor + + rho_i = sum(rho_ir,2); # rho_i(i) is the utilization of center i + + mu_i = zeros(1,K); # mu_i(i) is the mean service rate at center i + for i=1:K + mu_i(i) = 1 / sum( rho_ir(i,:) ./ lambda_i(i) ); + endfor + + do + + c2A_i_old = c2A_i; + + ## Decomposition of Whitt + + ## Merging + for r=1:C + for i=1:K + c2A_ir(i,r) = 1 / lambda_ir(i,r) * ... + (c20_ir(i,r)*lambda0_ir(i,r) + ... + sum( c2_ijr(:,i,r) .* lambda_ir(:,r) .* P_ijr(:,i,r) ) ); + endfor + endfor + + for i=1:K + c2A_i(i) = 1 / lambda_i(i) * sum(c2A_ir(i,:) .* lambda_ir(i,:) ); + endfor + + ## Coeff of variation + + for i=1:K + c2B_i(i) = -1 + sum( lambda_ir(i,:)/lambda_i(i) .* ... + ( mu_i(i) / (m(i) * mu_ir(i,:))).^2 .* ... + (c2_ir(i,:)+1) ); + endfor + + ## Flow (Pujolle) + for i=1:K + c2D_i(i) = 1 + (rho_i(i)^2 * (c2B_i(i) - 1) / sqrt(m(i))) + ... + (1 - rho_i(i)^2)*(c2A_i(i) - 1); +#{ + c2D_i(i) = rho_i(i)^2 * (c2B_i(i)+1) +... + (1-rho_i(i))*c2A_i(i) + ... + rho_i(i)*(1-2*rho_i(i)); +#} + endfor + + ## Splitting + for i=1:K + for j=1:K + for r=1:C + c2_ijr(i,j,r) = 1 + P_ijr(i,j,r) * (c2D_i(i) - 1); + endfor + endfor + endfor + + until ( norm(c2A_i - c2A_i_old, "inf") < 1e-3 ); + +endfunction + +%!demo +%! C = 1; K = 4; +%! P=zeros(C,K,C,K); +%! P(1,1,1,2) = .5; +%! P(1,1,1,3) = .5; +%! P(1,3,1,1) = .6; +%! P(1,2,1,1) = P(1,4,1,1) = 1; +%! mu = [25 33.333 16.666 20]; +%! c2B = [2 6 .5 .2]; +%! c20 = [0 0 0 4]; +%! lambda = [0 0 0 4]; +%! qnwhitt(lambda, c20, mu, c2B, P );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/broken/qnopensinglenexp.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,100 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopensinglenexp (@var{lambda}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopensingle (@var{lambda}, @var{S}, @var{V}, @var{m}) +## +## Approximate analysis of open queueing networks +## with general arrival and service time distributions. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## @code¬@var{lambda}(i,r)} is the external arrival rate of class-@math{r} +## requests at service center @math{i}. +## +## @item P +## @code{@var{P}(i,j,r)} is the probability that a class-@math{r} +## request moves to center @math{j} after completing service at center +## @math{i}. +## +## @item mu +## mu(i,r) service rate of class-r jobs at center i +## +## @item m +## m(i) is the number of servers at center i +## +## @end table +## +## Reference: Bolch et al., p. 439-444. +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +## +## WORK IN PROGRESS: DO NOT USE!! +## +function qnopensinglenexp( l0, c20ir, P, mu, m, c2ir ) + + error("This function is work in progress. Do not use it yet"); + + N = size(l0,1); # number of service centers + R = size(l0,2); # number of classes + lir = zeros(N, R); # arrival rate to node i of class r + for r=1:R # FIXME: avoid loop + lir(:,r) = l0(:,r) \ ( eye(N) - P(:,:,r) ); + endfor + lijr = zeros(N, N, R); # arrival rate from node i to node j of class r + for i=1:N # FIXME: avoid loop + for j=1:N + for r=1:R + lijr(i,j,r) = lir(i,t)*P(i,j,r); + endfor + endfor + endfor + li = sum(lir,2); # arrival rate to node i + roir = zeros(N,R); # utilization of node i due to customers of class r + for i=1:N + for r=1:R + roir(i,r) = lir(i,r) / (m(i)*mu(i,r)); + endfor + endfor + roi = sum(roir,2); # utilization of node i + mui = zeros(1,N); # mean service rate of node i + for i=1:N + mui(i) = 1 / ( sum( lir(i,:) ./ li(i) ./ (m(i) .* muir(i,:)) ) ); + endfor + c2Bi = zeros(1,N); # squared coefficient of variation of service time of node i + for i=1:N + c2Bi(i) = -1 + sum( lir(i,:) ./ li(i) .* (mu(i) ./ (m(i) .* mu(i,:)).^2 .* c2ir(i,:) + 1 ) ); + endfor + c2ijr = ones(N, N, R); + c2Air = zeros(N,R); + c2Ai = c2Di = zeros(1,N); + while 1==1 + ## merging + c2Air(i,:) = 1./lir(i,:) .* sum( c2ijr(j,i,:) + ## flow + endwhile + +endfunction \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/Makefile Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,42 @@ +DOC=queueing +CHAPTERS=summary.texi installation.texi markovchains.texi singlestation.texi queueingnetworks.texi conf.texi ack.texi contributing.texi gpl.texi gettingstarted.texi +DISTFILES=$(wildcard *.txi) Makefile $(DOC).pdf $(DOC).html $(DOC).texi + +.PHONY: clean + +ALL: pdf html ../INSTALL + +html: $(DOC).html + +pdf: $(DOC).pdf + +info: $(DOC).info + +../INSTALL: installation.texi + rm -f ../INSTALL + -$(MAKEINFO) -D INSTALLONLY \ + --no-validate --no-headers --no-split --output ../INSTALL $< + +$(DOC).html: $(DOC).texi $(CHAPTERS) + -$(MAKEINFO) --html --no-split $(DOC).texi + +$(DOC).pdf: $(DOC).texi $(CHAPTERS) + texi2pdf -o $(DOC).pdf $< + +$(DOC).info: $(DOC).texi $(CHAPTERS) + -$(MAKEINFO) $< + +%.texi: %.txi DOCSTRINGS + ../scripts/munge-texi -d DOCSTRINGS < $< > $@ + +DOCSTRINGS: $(wildcard ../inst/*.m) + (cd ../scripts; ./mkdoc ../inst) > DOCSTRINGS || \rm -f DOCSTRINGS + +dist: $(DOC).pdf $(DOC).html + ln $(DISTFILES) ../`cat ../fname`/doc/ + +clean: + \rm -f *.fns *.pdf *.aux *.log *.dvi *.out *.info *.html *.ky *.tp *.toc *.vr *.cp *.fn *.pg *.op *.au *.aus *.cps x.log *~ DOCSTRINGS $(CHAPTERS) ../INSTALL + +distclean: clean +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/ack.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,28 @@ +@c -*- texinfo -*- + +@c Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +@c +@c This file is part of the queueing toolbox, a Queueing Networks +@c analysis package for GNU Octave. +@c +@c The queueing toolbox is free software; you can redistribute it +@c and/or modify it under the terms of the GNU General Public License +@c as published by the Free Software Foundation; either version 3 of +@c the License, or (at your option) any later version. +@c +@c The queueing toolbox is distributed in the hope that it will be +@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty +@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with the queueing toolbox; see the file COPYING. If not, see +@c <http://www.gnu.org/licenses/>. + +@node Acknowledgements +@appendix Acknowledgements + +The following people (listed in alphabetical order) contributed to the +@code{queueing} package, either by providing feedback, reporting bugs +or contributing code: Philip Carinhas, Phil Colbourn, Yves Durand, +Marco Guazzone, Dmitry Kolesnikov.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/contributing.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,61 @@ +@c -*- texinfo -*- + +@c Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +@c +@c This file is part of the queueing toolbox, a Queueing Networks +@c analysis package for GNU Octave. +@c +@c The queueing toolbox is free software; you can redistribute it +@c and/or modify it under the terms of the GNU General Public License +@c as published by the Free Software Foundation; either version 3 of +@c the License, or (at your option) any later version. +@c +@c The queueing toolbox is distributed in the hope that it will be +@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty +@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with the queueing toolbox; see the file COPYING. If not, see +@c <http://www.gnu.org/licenses/>. + +@node Contributing Guidelines +@appendix Contributing Guidelines + +Contributions and bug reports are @emph{always} welcome. If you want +to contribute to the @code{queueing} package, here are some +guidelines: + +@itemize + +@item If you are contributing a new function, please embed proper +documentation within the function itself. The documentation must be in +@code{texinfo} format, so that it will be extracted and formatted into +the printable manual. See the existing functions of the +@code{queueing} package for the documentation style. + +@item The documentation should be as precise as possible. In particular, +always state what the valid ranges of the parameters are. + +@item If you are contributing a new function, ensure that the function +properly checks the validity of its input parameters. For example, +each function accepting vectors should check whether the dimensions +match. + +@item Always provide bibliographic references for each algorithm you +contribute. If your implementation differs in some way from the +reference you give, please describe how and why your implementation +differs. + +@item Include Octave test and demo blocks with your code. +Test blocks are particularly important, because Queueing Network +algorithms tend to be quite complex to implement correctly, and we +must ensure that the implementations provided with the +@code{queueing} package are (mostly) correct. + +@end itemize + +Send your contribution to Moreno Marzolla +(@email{marzolla@@cs.unibo.it}). Even if you are just a user of +@code{queueing}, and find this package useful, let me know by +dropping me a line. Thanks.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/gettingstarted.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,316 @@ +@c -*- texinfo -*- + +@c Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +@c +@c This file is part of the queueing toolbox, a Queueing Networks +@c analysis package for GNU Octave. +@c +@c The queueing toolbox is free software; you can redistribute it +@c and/or modify it under the terms of the GNU General Public License +@c as published by the Free Software Foundation; either version 3 of +@c the License, or (at your option) any later version. +@c +@c The queueing toolbox is distributed in the hope that it will be +@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty +@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with the queueing toolbox; see the file COPYING. If not, see +@c <http://www.gnu.org/licenses/>. + +@node Getting Started +@chapter Introduction and Getting Started + +@menu +* Analysis of Closed Networks:: +* Analysis of Open Networks:: +@end menu + +In this chapter we give some usage examples of the @code{queueing} +package. The reader is assumed to be familiar with Queueing Networks +(although some basic terminology and notation will be given +here). Additional usage examples are embedded in most of the function +files; to display and execute the demos associated with function +@emph{fname} you can type @command{demo @emph{fname}} at the Octave +prompt. For example + +@example +@kbd{demo qnclosed} +@end example + +@noindent executes all demos (if any) for the @command{qnclosed} function. + +@node Analysis of Closed Networks +@section Analysis of Closed Networks + +Let us consider a simple closed network with @math{K=3} service +centers. Each center is of type @math{M/M/1}--FCFS. We denote with +@math{S_i} the average service time at center @math{i}, @math{i=1, 2, +3}. Let @math{S_1 = 1.0}, @math{S_2 = 2.0} and @math{S_3 = 0.8}. The +routing of jobs within the network is described with a @emph{routing +probability matrix} @math{P}. Specifically, a request completing +service at center @math{i} is enqueued at center @math{j} with +probability @math{P_{ij}}. Let us assume the following routing +probability matrix: + +@iftex +@tex +$$ +P = \pmatrix{ 0 & 0.3 & 0.7 \cr + 1 & 0 & 0 \cr + 1 & 0 & 0 } +$$ +@end tex +@end iftex +@ifnottex +@example + [ 0 0.3 0.7 ] +P = [ 1 0 0 ] + [ 1 0 0 ] +@end example +@end ifnottex + +For example, according to matric @math{P} a job completing service at +center 1 is routed to center 2 with probability 0.3, and is routed to +center 3 with probability 0.7. + +The network above can be analyzed with the @command{qnclosed} +function; if there is just a single class of requests, as in the +example above, @command{qnclosed} calls @command{qnclosedsinglemva} +which implements the Mean Value Analysys (MVA) algorithm for +single-class, product-form network. + +@command{qnclosed} requires the following parameters: + +@table @var + +@item N +Number of requests in the network (since we are considering a closed +network, the number of requests is fixed) + +@item S +Array of average service times at the centers: @code{@var{S}(k)} is +the average service time at center @math{k}. + +@item V +Array of visit ratios: @code{@var{V}(k)} is the average number of +visits to center @math{k}. + +@end table + +As can be seen, we must compute the @emph{visit ratios} (or visit +counts) @math{V_k} for each center @math{k}. The visit counts satisfy +the following equations: + +@iftex +@tex +$$ +V_j = \sum_{i=1}^K V_i P_{ij} +$$ +@end tex +@end iftex +@ifnottex +@example +V_j = sum_i V_i P_ij +@end example +@end ifnottex + +We can compute @math{V_k} from the routing probability matrix +@math{P_{ij}} using the @command{qnvisits} function: + +@example +@group +@kbd{P = [0 0.3 0.7; 1 0 0; 1 0 0];} +@kbd{V = qnvisits(P)} + @result{} V = 1.00000 0.30000 0.70000 +@end group +@end example + +We can check that the computed values satisfy the above equation by +evaluating the following expression: + +@example +@kbd{V*P} + @result{} ans = 1.00000 0.30000 0.70000 +@end example + +@noindent which is equal to @math{V}. +Hence, we can analyze the network for a given population size @math{N} +(for example, @math{N=10}) as follows: + +@example +@group +@kbd{N = 10;} +@kbd{S = [1 2 0.8];} +@kbd{P = [0 0.3 0.7; 1 0 0; 1 0 0];} +@kbd{V = qnvisits(P);} +@kbd{[U R Q X] = qnclosed( N, S, V )} + @result{} U = 0.99139 0.59483 0.55518 + @result{} R = 7.4360 4.7531 1.7500 + @result{} Q = 7.3719 1.4136 1.2144 + @result{} X = 0.99139 0.29742 0.69397 +@end group +@end example + +The output of @command{qnclosed} includes the vector of utilizations +@math{U_k} at center @math{k}, response time @math{R_k}, average +number of customers @math{Q_k} and throughput @math{X_k}. In our +example, the throughput of center 1 is @math{X_1 = 0.99139}, and the +average number of requests in center 3 is @math{Q_3 = 1.2144}. The +utilization of center 1 is @math{U_1 = 0.99139}, which is the higher +value among the service centers. Tus, center 1 is the @emph{bottleneck +device}. + +This network can also be analyzed with the @command{qnsolve} +function. @command{qnsolve} can handle open, closed or mixed networks, +and allows the network to be described in a very flexible way. First, +let @var{Q1}, @var{Q2} and @var{Q3} be the variables describing the +service centers. Each variable is instantiated with the +@command{qnmknode} function. + +@example +@group +@kbd{Q1 = qnmknode( "m/m/m-fcfs", 1 );} +@kbd{Q2 = qnmknode( "m/m/m-fcfs", 2 );} +@kbd{Q3 = qnmknode( "m/m/m-fcfs", 0.8 );} +@end group +@end example + +The first parameter of @command{qnmknode} is a string describing the +type of the node. Here we use @code{"m/m/m-fcfs"} to denote a +@math{M/M/m}--FCFS center. The second parameter gives the average +service time. An optional third parameter can be used to specify the +number @math{m} of service centers. If omitted, it is assumed +@math{m=1} (single-server node). + +Now, the network can be analyzed as follows: + +@example +@group +@kbd{N = 10;} +@kbd{V = [1 0.3 0.7];} +@kbd{[U R Q X] = qnsolve( "closed", N, @{ Q1, Q2, Q3 @}, V )} + @result{} U = 0.99139 0.59483 0.55518 + @result{} R = 7.4360 4.7531 1.7500 + @result{} Q = 7.3719 1.4136 1.2144 + @result{} X = 0.99139 0.29742 0.69397 +@end group +@end example + +Of course, we get exactly the same results. Other functions can be used +for closed networks, @pxref{Algorithms for Product-Form QNs}. + +@node Analysis of Open Networks +@section Analysis of Open Networks + +Open networks can be analyzed in a similar way. Let us consider +an open network with @math{K=3} service centers, and routing +probability matrix as follows: + +@iftex +@tex +$$ +P = \pmatrix{ 0 & 0.3 & 0.5 \cr + 1 & 0 & 0 \cr + 1 & 0 & 0 } +$$ +@end tex +@end iftex +@ifnottex +@example + [ 0 0.3 0.5 ] +P = [ 1 0 0 ] + [ 1 0 0 ] +@end example +@end ifnottex + +In this network, requests can leave the system from center 1 with +probability @math{(1-(0.3+0.5) = 0.2}. We suppose that external jobs +arrive at center 1 with rate @math{\lambda_1 = 0.15}; there are no +arrivals at centers 2 and 3. + +Similarly to closed networks, we first need to compute the visit +counts @math{V_k} to center @math{k}. Again, we use the +@command{qnvisits} function as follows: + +@example +@group +@kbd{P = [0 0.3 0.5; 1 0 0; 1 0 0];} +@kbd{lambda = [0.15 0 0];} +@kbd{V = qnvisits(P, lambda)} + @result{} V = 5.00000 1.50000 2.50000 +@end group +@end example + +@noindent where @code{@var{lambda}(k)} is the arrival rate at center @math{k}, +and @var{P} is the routing matrix. The visit counts @math{V_k} for +open networks satisfy the following equation: + +@iftex +@tex +$$ +V_j = P_{0j} + \sum_{i=1}^K V_i P_{ij} +$$ +@end tex +@end iftex +@ifnottex +@example +V_j = sum_i V_i P_ij +@end example +@end ifnottex + +where @math{P_{0j}} is the probability of an external arrival to +center @math{j}. This can be computed as: + +@tex +$$ +P_{0j} = {\lambda_j \over \sum_{i=1}^K \lambda_i } +$$ +@end tex + +Assuming the same service times as in the previous example, the +network can be analyzed with the @command{qnopen} function, as +follows: + +@example +@group +@kbd{S = [1 2 0.8];} +@kbd{[U R Q X] = qnopen( sum(lambda), S, V )} + @result{} U = 0.75000 0.45000 0.30000 + @result{} R = 4.0000 3.6364 1.1429 + @result{} Q = 3.00000 0.81818 0.42857 + @result{} X = 0.75000 0.22500 0.37500 +@end group +@end example + +The first parameter of the @command{qnopen} function is the (scalar) +aggregate arrival rate. + +Again, it is possible to use the @command{qnsolve} high-level function: + +@example +@group +@kbd{Q1 = qnmknode( "m/m/m-fcfs", 1 );} +@kbd{Q2 = qnmknode( "m/m/m-fcfs", 2 );} +@kbd{Q3 = qnmknode( "m/m/m-fcfs", 0.8 );} +@kbd{lambda = [0.15 0 0];} +@kbd{[U R Q X] = qnsolve( "open", sum(lambda), @{ Q1, Q2, Q3 @}, V )} + @result{} U = 0.75000 0.45000 0.30000 + @result{} R = 4.0000 3.6364 1.1429 + @result{} Q = 3.00000 0.81818 0.42857 + @result{} X = 0.75000 0.22500 0.37500 +@end group +@end example + +@c @node Markov Chains Analysis +@c @section Markov Chains Analysis + +@c @subsection Discrete-Time Markov Chains + +@c (TODO) + +@c @subsection Continuous-Time Markov Chains + +@c (TODO) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/gpl.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,718 @@ +@node Copying +@appendix GNU GENERAL PUBLIC LICENSE +@cindex warranty +@cindex copyright + +@center Version 3, 29 June 2007 + +@display +Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. +@end display + +@heading Preamble + +The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom +to share and change all versions of a program---to make sure it remains +free software for all its users. We, the Free Software Foundation, +use the GNU General Public License for most of our software; it +applies also to any other work released this way by its authors. You +can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you +have certain responsibilities if you distribute copies of the +software, or if you modify it: responsibilities to respect the freedom +of others. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, +receive or can get the source code. And you must show them these +terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the +manufacturer can do so. This is fundamentally incompatible with the +aim of protecting users' freedom to change the software. The +systematic pattern of such abuse occurs in the area of products for +individuals to use, which is precisely where it is most unacceptable. +Therefore, we have designed this version of the GPL to prohibit the +practice for those products. If such problems arise substantially in +other domains, we stand ready to extend this provision to those +domains in future versions of the GPL, as needed to protect the +freedom of users. + +Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish +to avoid the special danger that patents applied to a free program +could make it effectively proprietary. To prevent this, the GPL +assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and +modification follow. + +@heading TERMS AND CONDITIONS + +@enumerate 0 +@item Definitions. + +``This License'' refers to version 3 of the GNU General Public License. + +``Copyright'' also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +``The Program'' refers to any copyrightable work licensed under this +License. Each licensee is addressed as ``you''. ``Licensees'' and +``recipients'' may be individuals or organizations. + +To ``modify'' a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a ``modified version'' of +the earlier work or a work ``based on'' the earlier work. + +A ``covered work'' means either the unmodified Program or a work based +on the Program. + +To ``propagate'' a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To ``convey'' a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays ``Appropriate Legal Notices'' to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +@item Source Code. + +The ``source code'' for a work means the preferred form of the work for +making modifications to it. ``Object code'' means any non-source form +of a work. + +A ``Standard Interface'' means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The ``System Libraries'' of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +``Major Component'', in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The ``Corresponding Source'' for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + +@item Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +@item Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + +@item Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +@item Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + +@enumerate a +@item +The work must carry prominent notices stating that you modified it, +and giving a relevant date. + +@item +The work must carry prominent notices stating that it is released +under this License and any conditions added under section 7. This +requirement modifies the requirement in section 4 to ``keep intact all +notices''. + +@item +You must license the entire work, as a whole, under this License to +anyone who comes into possession of a copy. This License will +therefore apply, along with any applicable section 7 additional terms, +to the whole of the work, and all its parts, regardless of how they +are packaged. This License gives no permission to license the work in +any other way, but it does not invalidate such permission if you have +separately received it. + +@item +If the work has interactive user interfaces, each must display +Appropriate Legal Notices; however, if the Program has interactive +interfaces that do not display Appropriate Legal Notices, your work +need not make them do so. +@end enumerate + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +``aggregate'' if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +@item Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + +@enumerate a +@item +Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by the +Corresponding Source fixed on a durable physical medium customarily +used for software interchange. + +@item +Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by a written +offer, valid for at least three years and valid for as long as you +offer spare parts or customer support for that product model, to give +anyone who possesses the object code either (1) a copy of the +Corresponding Source for all the software in the product that is +covered by this License, on a durable physical medium customarily used +for software interchange, for a price no more than your reasonable +cost of physically performing this conveying of source, or (2) access +to copy the Corresponding Source from a network server at no charge. + +@item +Convey individual copies of the object code with a copy of the written +offer to provide the Corresponding Source. This alternative is +allowed only occasionally and noncommercially, and only if you +received the object code with such an offer, in accord with subsection +6b. + +@item +Convey the object code by offering access from a designated place +(gratis or for a charge), and offer equivalent access to the +Corresponding Source in the same way through the same place at no +further charge. You need not require recipients to copy the +Corresponding Source along with the object code. If the place to copy +the object code is a network server, the Corresponding Source may be +on a different server (operated by you or a third party) that supports +equivalent copying facilities, provided you maintain clear directions +next to the object code saying where to find the Corresponding Source. +Regardless of what server hosts the Corresponding Source, you remain +obligated to ensure that it is available for as long as needed to +satisfy these requirements. + +@item +Convey the object code using peer-to-peer transmission, provided you +inform other peers where the object code and Corresponding Source of +the work are being offered to the general public at no charge under +subsection 6d. + +@end enumerate + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A ``User Product'' is either (1) a ``consumer product'', which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +``normally used'' refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +``Installation Information'' for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +@item Additional Terms. + +``Additional permissions'' are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + +@enumerate a +@item +Disclaiming warranty or limiting liability differently from the terms +of sections 15 and 16 of this License; or + +@item +Requiring preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices +displayed by works containing it; or + +@item +Prohibiting misrepresentation of the origin of that material, or +requiring that modified versions of such material be marked in +reasonable ways as different from the original version; or + +@item +Limiting the use for publicity purposes of names of licensors or +authors of the material; or + +@item +Declining to grant rights under trademark law for use of some trade +names, trademarks, or service marks; or + +@item +Requiring indemnification of licensors and authors of that material by +anyone who conveys the material (or modified versions of it) with +contractual assumptions of liability to the recipient, for any +liability that these contractual assumptions directly impose on those +licensors and authors. +@end enumerate + +All other non-permissive additional terms are considered ``further +restrictions'' within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + +@item Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +@item Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +@item Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An ``entity transaction'' is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +@item Patents. + +A ``contributor'' is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's ``contributor version''. + +A contributor's ``essential patent claims'' are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, ``control'' includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a ``patent license'' is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To ``grant'' such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. ``Knowingly relying'' means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is ``discriminatory'' if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +@item No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey +a covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree +to terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +@item Use with the GNU Affero General Public License. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +@item Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU General Public +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that numbered version or +of any later version published by the Free Software Foundation. If +the Program does not specify a version number of the GNU General +Public License, you may choose any version ever published by the Free +Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU General Public License can be used, that proxy's public +statement of acceptance of a version permanently authorizes you to +choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +@item Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +@item Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +@item Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +@end enumerate + +@heading END OF TERMS AND CONDITIONS + +@heading How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the ``copyright'' line and a pointer to where the full notice is found. + +@smallexample +@var{one line to give the program's name and a brief idea of what it does.} +Copyright (C) @var{year} @var{name of author} + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see @url{http://www.gnu.org/licenses/}. +@end smallexample + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +@smallexample +@var{program} Copyright (C) @var{year} @var{name of author} +This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. +This is free software, and you are welcome to redistribute it +under certain conditions; type @samp{show c} for details. +@end smallexample + +The hypothetical commands @samp{show w} and @samp{show c} should show +the appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an ``about box''. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a ``copyright disclaimer'' for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +@url{http://www.gnu.org/licenses/}. + +The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use +the GNU Lesser General Public License instead of this License. But +first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/installation.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,245 @@ +@c -*- texinfo -*- + +@c Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +@c +@c This file is part of the queueing toolbox, a Queueing Networks +@c analysis package for GNU Octave. +@c +@c The queueing toolbox is free software; you can redistribute it +@c and/or modify it under the terms of the GNU General Public License +@c as published by the Free Software Foundation; either version 3 of +@c the License, or (at your option) any later version. +@c +@c The queueing toolbox is distributed in the hope that it will be +@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty +@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with the queueing toolbox; see the file COPYING. If not, see +@c <http://www.gnu.org/licenses/>. + +@ifset INSTALLONLY +@include conf.texi + +This file documents the installation procedure of the @code{queueing} +toolbox. + +@code{queueing} is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License, version 3 +or later, as published by the Free Software Foundation. + +@quotation Note +This file (@file{INSTALL}) is automatically generated from +@file{doc/installation.txi} in the @code{queueing} sources. Do not +modify this document directly, as changes will be lost. Modify the +source @file{doc/installation.txi} instead. +@end quotation + +@end ifset + +@node Installation +@chapter Installing the queueing toolbox + +@menu +* Installation through Octave package management system:: +* Manual installation:: +* Content of the source distribution:: +* Using the queueing toolbox:: +@end menu + +@c +@c +@c + +@node Installation through Octave package management system +@section Installation through Octave package management system + +The most recent version of @code{queueing} is @value{VERSION} and can +be downloaded from + +@url{http://www.moreno.marzolla.name/software/queueing/queueing-@value{VERSION}.tar.gz} + +To install @code{queueing} in the system-wide location, such that all +functions are automatically available when Octave starts, you can use +@samp{pkg install} command. At the Octave prompt, type the following: + +@example +octave:1> @kbd{pkg install queueing-@value{VERSION}.tar.gz} +@end example + +(Note: you may need to start Octave as root in order to allow the +installation to copy the files to the target locations). After this, +all functions will be readily available each time Octave starts, +without the need to tweak the search path. To uninstall +@code{queueing}, use the @samp{pkg uninstall queueing} command. + +If you do not have root access, you can do a local installation by +issuing the following command at the Octave prompt: + +@example +octave:1> @kbd{pkg install -local queueing-@value{VERSION}.tar.gz} +@end example + +This will install @code{queueing} within the user's home directory, +and the package will be available to that user only. @strong{Note:} +Octave version 3.2.3 as shipped with Ubuntu 10.04 seems to ignore +@code{-local} and always tries to install the package on the system +directory. + +@c +@c +@c + +@node Manual installation +@section Manual installation + +If you want to install @code{queueing} in a custom location, you can +download the source tarball from the URL above, and unpack it +somewhere: + +@example +@kbd{tar xfz queueing-@value{VERSION}.tar.gz} +@kbd{cd queueing-@value{VERSION}/} +@end example + +Copy all @code{.m} files from the @file{inst/} directory to some +target location. Then, you can start Octave with the @option{-p} +option to add the target location to the search path, so that Octave +will find all @code{queueing} functions automatically: + +@example +@kbd{octave -p @emph{/path/to/queueing}} +@end example + +For example, if all @code{queueing} m-files are in +@file{/usr/local/queueing}, you can start Octave as follows: + +@example +@kbd{octave -p @file{/usr/local/queueing}} +@end example + +If you want, you can add the following line to @file{~/.octaverc}: + +@example +@kbd{addpath("@emph{/path/to/queueing}");} +@end example + +@noindent so that the path @file{/usr/local/queueing} is automatically +added to the search path each time Octave is started, and you no +longer need to specify the @option{-p} option on the command line. + +@c +@c +@c + +@node Content of the source distribution +@section Content of the source distribution + +The @code{queueing} source distribution contains the following +subdirectories: + +@table @file +@item doc/ +Documentation source. Most of the documentation is extracted from the +comment blocks of individual function files from the @file{inst/} +directory. + +@item inst/ +This directory contains the @verb{|m|}-files which implement the +various Queueing Network algorithms provided by @code{queueing}. As a +notational convention, the names of source files containing functions +for Queueing Networks start with the @samp{qn} prefix; the name of +source files containing functions for Continuous-Time Markov Chains +(CTMSs) start with the @samp{ctmc} prefix, and the names of files +containing functions for Discrete-Time Markov Chains (DTMCs) start +with the @samp{dtmc} prefix. + +@item test/ +This directory contains the test functions used to invoke all tests on +all function files. + +@item scripts/ +This directory contains some utility scripts mostly from GNU Octave, +which extract the documentation from the specially-formatted comments +in the @verb{|m|}-files. + +@item examples/ +This directory contains examples which are automatically extracted +from the @samp{demo} blocks of the function files. + +@item broken/ +This directory contains function files which are either not working +properly, or need additional testing before they can be moved to the +@file{inst/} directory. + +@end table + +The @code{queueing} package ships with a Makefile which can be used +to produce the documentation (in PDF and HTML format), and +automatically execute all function tests. Specifically, the following +targets are defined: + +@table @code +@item all +Running @samp{make} (or @samp{make all}) on the top-level directory +builds the programs used to extract the documentation from the +comments embedded in the @verb{|m|}-files, and then produce the +documentation in PDF and HTML format (@file{doc/queueing.pdf} and +@file{doc/queueing.html}, respectively). + +@item check +Running @samp{make check} will execute all tests contained in the +@verb{|m|}-files. If you modify the code of any function in the +@file{inst/} directory, you should run the tests to ensure that no +errors have been introduced. You are also encouraged to contribute new +tests, especially for functions which are not adequately validated. + +@item clean +@itemx distclean +@itemx dist +The @samp{make clean}, @samp{make distclean} and @samp{make dist} +commands are used to clean up the source directory and prepare the +distribution archive in compressed tar format. + +@end table + +@c +@c +@c + +@node Using the queueing toolbox +@section Using the queueing toolbox + +You can use all functions by simply invoking their name with the +appropriate parameters; the @code{queueing} package should display an +error message in case of missing/wrong parameters. You can display the +help text for any function using the @command{help} command. For +example: + +@example +octave:2> @kbd{help qnmvablo} +@end example + +prints the documentation for the @command{qnmvablo} function. +Additional information can be found in the @code{queueing} manual, +which is available in PDF format in @file{doc/queueing.pdf} and in +HTML format in @file{doc/queueing.html}. + +Within GNU Octave, you can also run the test and demo blocks +associated to the functions, using the @command{test} and +@command{demo} commands respectively. To run all the tests of, say, +the @command{qnmvablo} function: + +@example +octave:3> @kbd{test qnmvablo} +@print{} PASSES 4 out of 4 tests +@end example + +To execute the demos of the @command{qnclosed} function, use the +following: + +@example +octave:4> @kbd{demo qnclosed} +@end example +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/markovchains.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,253 @@ +@c -*- texinfo -*- + +@c Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +@c +@c This file is part of the queueing toolbox, a Queueing Networks +@c analysis package for GNU Octave. +@c +@c The queueing toolbox is free software; you can redistribute it +@c and/or modify it under the terms of the GNU General Public License +@c as published by the Free Software Foundation; either version 3 of +@c the License, or (at your option) any later version. +@c +@c The queueing toolbox is distributed in the hope that it will be +@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty +@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with the queueing toolbox; see the file COPYING. If not, see +@c <http://www.gnu.org/licenses/>. + +@node Markov Chains +@chapter Markov Chains + +@menu +* Discrete-Time Markov Chains:: +* Continuous-Time Markov Chains:: +@end menu + +@node Discrete-Time Markov Chains +@section Discrete-Time Markov Chains + +@menu +* DTMC Stationary Probability:: +* DTMC First Passage Times:: +@end menu + +@node DTMC Stationary Probability +@subsection Stationary Probability + +@DOCSTRING(dtmc) + +@node DTMC First Passage Times +@subsection First Passage Times + +The First Passage Time @math{M_{i j}} is defined as the average +number of transitions needed to visit state @math{j} for the first +time, starting from state @math{i}. Matrix @math{\bf M} satisfies the +property that + +@iftex +@tex +$$ M_{i j} = 1 + \sum_{k \neq j} P_{i k} M_{k j}$$ +@end tex +@end iftex +@ifnottex +@example +@group + ___ + \ +M_ij = 1 + > P_ij * M_kj + /___ + k!=j +@end group +@end example +@end ifnottex + +@DOCSTRING(dtmc_fpt) + +@c +@c +@c +@node Continuous-Time Markov Chains +@section Continuous-Time Markov Chains + +@menu +* CTMC Stationary Probability:: +* Birth-Death process:: +* Expected Sojourn Time:: +* Time-Averaged Expected Sojourn Time:: +* Expected Time to Absorption:: +* CTMC First Passage Times:: +@end menu + +@node CTMC Stationary Probability +@subsection Stationary Probability + +@DOCSTRING(ctmc) + +@noindent @strong{EXAMPLE} + +Consider a two-state CTMC such that transition rates between states +are equal to 1. This can be solved as follows: + +@example +@group +@verbatiminclude @value{top_srcdir}/examples/demo_1_ctmc.m + @result{} q = 0.50000 0.50000 +@end group +@end example + +@c +@c +@c +@node Birth-Death process +@subsection Birth-Death process + +@DOCSTRING(ctmc_bd) + +@c +@c +@c +@node Expected Sojourn Time +@subsection Expected Sojourn Time + +Given a @math{N} state continuous-time Markov Chain with infinitesimal +generator matrix @math{\bf Q}, we define the vector @math{{\bf L}(t) = +(L_1(t), L_2(t), \ldots L_N(t))} such that @math{L_i(t)} is the +expected sojourn time in state @math{i} during the interval +@math{[0,t)}, assuming that the initial occupancy probability at time +0 was @math{{\bf \pi}(0)}. Then, @math{{\bf L}(t)} is the solution of +the following differential equation: + +@iftex +@tex +$$ { d{\bf L}(t) \over dt} = {\bf L}(t){\bf Q} + {\bf \pi}(0), \qquad {\bf L}(0) = {\bf 0} $$ +@end tex +@end iftex +@ifnottex +@example +@group + dL + --(t) = L(t) Q + pi(0), L(0) = 0 + dt +@end group +@end example +@end ifnottex + +The function @code{ctmc_exps} can be used to compute @math{{\bf +L}(t)}, by using the @code{lsode} Octave function to solve the above +linear differential equation. + +@DOCSTRING(ctmc_exps) + +@noindent @strong{EXAMPLE} + +Let us consider a pure-birth, 4-states CTMC such that the transition +rate from state @math{i} to state @math{i+1} is @math{\lambda_i = i +\lambda} (@math{i=1, 2, 3}), with @math{\lambda = 0.5}. The following +code computes the expected sojourn time in state @math{i}, +given the initial occupancy probability @math{p_0=(1,0,0,0)}. + +@example +@group +@verbatiminclude @value{top_srcdir}/examples/demo_1_ctmc_exps.m +@end group +@end example + +@c +@c +@c +@node Time-Averaged Expected Sojourn Time +@subsection Time-Averaged Expected Sojourn Time + +@DOCSTRING(ctmc_taexps) + +@noindent @strong{EXAMPLE} + +@example +@group +@verbatiminclude @value{top_srcdir}/examples/demo_1_ctmc_taexps.m +@end group +@end example + +@c +@c +@c +@node Expected Time to Absorption +@subsection Expected Time to Absorption + +If we consider a Markov Chain with absorbing states, it is possible to +define the @emph{expected time to absorption} as the expected time +until the system goes into an absorbing state. More specifically, let +us suppose that @math{A} is the set of transient (i.e., non-absorbing) +states of a CTMC with @math{N} states and infinitesimal generator +matrix @math{\bf Q}. The expected time to absorption @math{{\bf +L}_A(\infty)} is defined as the solution of the following equation: + +@iftex +@tex +$$ {\bf L}_A(\infty){\bf Q}_A = -{\bf \pi}_A(0) $$ +@end tex +@end iftex +@ifnottex +@example +@group +L_A( inf ) Q_A = -pi_A(0) +@end group +@end example +@end ifnottex + +@noindent where @math{{\bf Q}_A} is the restriction of matrix @math{\bf Q} to +only states in @math{A}, and @math{{\bf \pi}_A(0)} is the initial +state occupancy probability at time 0, restricted to states in +@math{A}. + +@DOCSTRING(ctmc_mtta) + +@noindent @strong{EXAMPLE} + +Let us consider a simple model of a redundant disk array. We assume +that the array is made of 5 independent disks, such that the array can +tolerate up to 2 disk failures without losing data. If three or more +disks break, the array is dead and unrecoverable. We want to estimate +the Mean-Time-To-Failure (MTTF) of the disk array. + +We model this system as a 4 states Markov chain with state space +@math{\{ 2, 3, 4, 5 \}}. State @math{i} denotes the fact that exactly +@math{i} disks are active; state @math{2} is absorbing. Let @math{\mu} +be the failure rate of a single disk. The system starts in state +@math{5} (all disks are operational). We use a pure death process, +with death rate from state @math{i} to state @math{i-1} is @math{\mu +i}, for @math{i = 3, 4, 5}). + +The MTTF of the disk array is the MTTA of the Markov Chain, and can be +computed with the following expression: + +@example +@group +@verbatiminclude @value{top_srcdir}/examples/demo_1_ctmc_mtta.m + @result{} t = 78.333 +@end group +@end example + +@noindent @strong{REFERENCES} + +G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications}, Wiley, +1998. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@c +@c +@c +@node CTMC First Passage Times +@subsection First Passage Times +@DOCSTRING(ctmc_fpt) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/queueing.html Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,5482 @@ +<html lang="en"> +<head> +<title>queueing</title> +<meta http-equiv="Content-Type" content="text/html"> +<meta name="description" content="User manual for the queueing toolbox, a GNU Octave package for queueing networks and Markov chains analysis. This package supports single-station queueing systems, queueing networks and Markov chains. The queueing toolbox implements, among others, the Mean Value Analysis (MVA) and convolution algorithms for product-form queueing networks. Transient and steady-state analysis of Markov chains is also implemented."> +<meta name="generator" content="makeinfo 4.13"> +<link title="Top" rel="top" href="#Top"> +<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage"> +<meta http-equiv="Content-Style-Type" content="text/css"> +<style type="text/css"><!-- + pre.display { font-family:inherit } + pre.format { font-family:inherit } + pre.smalldisplay { font-family:inherit; font-size:smaller } + pre.smallformat { font-family:inherit; font-size:smaller } + pre.smallexample { font-size:smaller } + pre.smalllisp { font-size:smaller } + span.sc { font-variant:small-caps } + span.roman { font-family:serif; font-weight:normal; } + span.sansserif { font-family:sans-serif; font-weight:normal; } +--></style> +</head> +<body> +Copyright © 2008, 2009, 2010, 2011, 2012 Moreno Marzolla. + + <p>Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + + <p>Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of +a permission notice identical to this one. + + <p>Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for +modified versions. + +<div class="contents"> +<h2>Table of Contents</h2> +<ul> +<li><a name="toc_Top" href="#Top">queueing</a> +<li><a name="toc_Summary" href="#Summary">1 Summary</a> +<li><a name="toc_Installation" href="#Installation">2 Installing the queueing toolbox</a> +<ul> +<li><a href="#Installation-through-Octave-package-management-system">2.1 Installation through Octave package management system</a> +<li><a href="#Manual-installation">2.2 Manual installation</a> +<li><a href="#Content-of-the-source-distribution">2.3 Content of the source distribution</a> +<li><a href="#Using-the-queueing-toolbox">2.4 Using the queueing toolbox</a> +</li></ul> +<li><a name="toc_Getting-Started" href="#Getting-Started">3 Introduction and Getting Started</a> +<ul> +<li><a href="#Analysis-of-Closed-Networks">3.1 Analysis of Closed Networks</a> +<li><a href="#Analysis-of-Open-Networks">3.2 Analysis of Open Networks</a> +</li></ul> +<li><a name="toc_Markov-Chains" href="#Markov-Chains">4 Markov Chains</a> +<ul> +<li><a href="#Discrete_002dTime-Markov-Chains">4.1 Discrete-Time Markov Chains</a> +<ul> +<li><a href="#DTMC-Stationary-Probability">4.1.1 Stationary Probability</a> +<li><a href="#DTMC-First-Passage-Times">4.1.2 First Passage Times</a> +</li></ul> +<li><a href="#Continuous_002dTime-Markov-Chains">4.2 Continuous-Time Markov Chains</a> +<ul> +<li><a href="#CTMC-Stationary-Probability">4.2.1 Stationary Probability</a> +<li><a href="#Birth_002dDeath-process">4.2.2 Birth-Death process</a> +<li><a href="#Expected-Sojourn-Time">4.2.3 Expected Sojourn Time</a> +<li><a href="#Time_002dAveraged-Expected-Sojourn-Time">4.2.4 Time-Averaged Expected Sojourn Time</a> +<li><a href="#Expected-Time-to-Absorption">4.2.5 Expected Time to Absorption</a> +<li><a href="#CTMC-First-Passage-Times">4.2.6 First Passage Times</a> +</li></ul> +</li></ul> +<li><a name="toc_Single-Station-Queueing-Systems" href="#Single-Station-Queueing-Systems">5 Single Station Queueing Systems</a> +<ul> +<li><a href="#The-M_002fM_002f1-System">5.1 The M/M/1 System</a> +<li><a href="#The-M_002fM_002fm-System">5.2 The M/M/m System</a> +<li><a href="#The-M_002fM_002finf-System">5.3 The M/M/inf System</a> +<li><a href="#The-M_002fM_002f1_002fK-System">5.4 The M/M/1/K System</a> +<li><a href="#The-M_002fM_002fm_002fK-System">5.5 The M/M/m/K System</a> +<li><a href="#The-Asymmetric-M_002fM_002fm-System">5.6 The Asymmetric M/M/m System</a> +<li><a href="#The-M_002fG_002f1-System">5.7 The M/G/1 System</a> +<li><a href="#The-M_002fHm_002f1-System">5.8 The M/H_m/1 System</a> +</li></ul> +<li><a name="toc_Queueing-Networks" href="#Queueing-Networks">6 Queueing Networks</a> +<ul> +<li><a href="#Introduction-to-QNs">6.1 Introduction to QNs</a> +<ul> +<li><a href="#Introduction-to-QNs">6.1.1 Single class models</a> +<li><a href="#Introduction-to-QNs">6.1.2 Multiple class models</a> +</li></ul> +<li><a href="#Generic-Algorithms">6.2 Generic Algorithms</a> +<li><a href="#Algorithms-for-Product_002dForm-QNs">6.3 Algorithms for Product-Form QNs</a> +<ul> +<li><a href="#Algorithms-for-Product_002dForm-QNs">6.3.1 Jackson Networks</a> +<li><a href="#Algorithms-for-Product_002dForm-QNs">6.3.2 The Convolution Algorithm</a> +<li><a href="#Algorithms-for-Product_002dForm-QNs">6.3.3 Open networks</a> +<li><a href="#Algorithms-for-Product_002dForm-QNs">6.3.4 Closed Networks</a> +<li><a href="#Algorithms-for-Product_002dForm-QNs">6.3.5 Mixed Networks</a> +</li></ul> +<li><a href="#Algorithms-for-non-Product_002dform-QNs">6.4 Algorithms for non Product-Form QNs</a> +<li><a href="#Bounds-on-performance">6.5 Bounds on performance</a> +<li><a href="#Utility-functions">6.6 Utility functions</a> +<ul> +<li><a href="#Utility-functions">6.6.1 Open or closed networks</a> +<li><a href="#Utility-functions">6.6.2 Computation of the visit counts</a> +<li><a href="#Utility-functions">6.6.3 Other utility functions</a> +</li></ul> +</li></ul> +<li><a name="toc_Contributing-Guidelines" href="#Contributing-Guidelines">Appendix A Contributing Guidelines</a> +<li><a name="toc_Acknowledgements" href="#Acknowledgements">Appendix B Acknowledgements</a> +<li><a name="toc_Copying" href="#Copying">Appendix C GNU GENERAL PUBLIC LICENSE</a> +<li><a name="toc_Concept-Index" href="#Concept-Index">Concept Index</a> +<li><a name="toc_Function-Index" href="#Function-Index">Function Index</a> +<li><a name="toc_Author-Index" href="#Author-Index">Author Index</a> +</li></ul> +</div> + +<div class="node"> +<a name="Top"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Summary">Summary</a>, +Up: <a rel="up" accesskey="u" href="#dir">(dir)</a> + +</div> + +<h2 class="unnumbered">queueing</h2> + +<p>This manual documents how to install and run the Queueing Toolbox. +It corresponds to version 1.0.0 of the package. + +<!-- --> +<ul class="menu"> +<li><a accesskey="1" href="#Summary">Summary</a> +<li><a accesskey="2" href="#Installation">Installation</a>: Installation of the queueing toolbox. +<li><a accesskey="3" href="#Getting-Started">Getting Started</a>: Getting started with the queueing toolbox. +<li><a accesskey="4" href="#Markov-Chains">Markov Chains</a>: Functions for Markov Chains. +<li><a accesskey="5" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a>: Functions for single-station queueing systems. +<li><a accesskey="6" href="#Queueing-Networks">Queueing Networks</a>: Functions for queueing networks. +<li><a accesskey="7" href="#Contributing-Guidelines">Contributing Guidelines</a>: How to contribute. +<li><a accesskey="8" href="#Acknowledgements">Acknowledgements</a>: People who contributed to the queueing toolbox. +<li><a accesskey="9" href="#Copying">Copying</a>: The GNU General Public License. +<li><a href="#Concept-Index">Concept Index</a>: An item for each concept. +<li><a href="#Function-Index">Function Index</a>: An item for each function. +<li><a href="#Author-Index">Author Index</a>: An item for each author. +</ul> + +<!-- --> +<!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<!-- *- texinfo -*- --> +<!-- Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla --> +<!-- This file is part of the queueing toolbox, a Queueing Networks --> +<!-- analysis package for GNU Octave. --> +<!-- The queueing toolbox is free software; you can redistribute it --> +<!-- and/or modify it under the terms of the GNU General Public License --> +<!-- as published by the Free Software Foundation; either version 3 of --> +<!-- the License, or (at your option) any later version. --> +<!-- The queueing toolbox is distributed in the hope that it will be --> +<!-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty --> +<!-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with the queueing toolbox; see the file COPYING. If not, see --> +<!-- <http://www.gnu.org/licenses/>. --> +<div class="node"> +<a name="Summary"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Installation">Installation</a>, +Previous: <a rel="previous" accesskey="p" href="#Top">Top</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="chapter">1 Summary</h2> + +<p>This document describes the <code>queueing</code> toolbox for GNU Octave +(<code>queueing</code> in short). The <code>queueing</code> toolbox, previously +known as <code>qnetworks</code>, is a collection of functions written in GNU +Octave for analyzing queueing networks and Markov +chains. Specifically, <code>queueing</code> contains functions for analyzing +Jackson networks, open, closed or mixed product-form BCMP networks, +and computation of performance bounds. The following algorithms have +been implemented + + <ul> +<li>Convolution for closed, single-class product-form networks +with load-dependent service centers; + + <li>Exact and approximate Mean Value Analysis (MVA) for single and +multiple class product-form closed networks; + + <li>MVA for mixed, multiple class product-form networks +with load-independent service centers; + + <li>Approximate MVA for closed, single-class networks with blocking +(MVABLO algorithm by F. Akyildiz); + + <li>Computation of Asymptotic Bounds, Balanced System Bounds +and Geometric Bounds; + + </ul> + +<p class="noindent"><code>queueing</code> +provides functions for analyzing the following kind of single-station +queueing systems: + + <ul> +<li>M/M/1 +<li>M/M/m +<li>M/M/\infty +<li>M/M/1/k single-server, finite capacity system +<li>M/M/m/k multiple-server, finite capacity system +<li>Asymmetric M/M/m +<li>M/G/1 (general service time distribution) +<li>M/H_m/1 (Hyperexponential service time distribution) +</ul> + + <p>Functions for Markov chain analysis are also provided (discrete and +continuous time Markov chains are supported): + + <ul> +<li>Birth-death process; +<li>Computation of transient and steady-state occupancy probabilities; +<li>Computation of mean time to absorption; +<li>Computation of time-averages sojourn time. +<li>Computation of mean passage times + + </ul> + + <p>The <code>queueing</code> toolbox is distributed under the terms of the GNU +General Public License (GPL), version 3 or later +(see <a href="#Copying">Copying</a>). You are encouraged to share this software with +others, and make this package more useful by contributing additional +functions and reporting problems. See <a href="#Contributing-Guidelines">Contributing Guidelines</a>. + + <p>If you use the <code>queueing</code> toolbox in a technical paper, please +cite it as: + + <blockquote> +Moreno Marzolla, <em>The qnetworks Toolbox: A Software Package for +Queueing Networks Analysis</em>. Khalid Al-Begain, Dieter Fiems and +William J. Knottenbelt, Editors, Proceedings 17th International +Conference on Analytical and Stochastic Modeling Techniques and +Applications (ASMTA 2010) Cardiff, UK, June 14–16, 2010, volume 6148 +of Lecture Notes in Computer Science, Springer, pp. 102–116, ISBN +978-3-642-13567-5 +</blockquote> + + <p>If you use BibTeX, this is the citation block: + +<pre class="verbatim">@inproceedings{queueing, + author = {Moreno Marzolla}, + title = {The qnetworks Toolbox: A Software Package for Queueing + Networks Analysis}, + booktitle = {Analytical and Stochastic Modeling Techniques and + Applications, 17th International Conference, + ASMTA 2010, Cardiff, UK, June 14-16, 2010. Proceedings}, + editor = {Khalid Al-Begain and Dieter Fiems and William J. Knottenbelt}, + year = {2010}, + publisher = {Springer}, + series = {Lecture Notes in Computer Science}, + volume = {6148}, + pages = {102--116}, + ee = {http://dx.doi.org/10.1007/978-3-642-13568-2_8}, + isbn = {978-3-642-13567-5} +} +</pre> + + <p>An early draft of the paper above is available as Technical Report +<a href="http://www.informatica.unibo.it/ricerca/ublcs/2010/UBLCS-2010-04">UBLCS-2010-04</a>, February 2010, Department of Computer Science, +University of Bologna, Italy. + +<!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<!-- *- texinfo -*- --> +<!-- Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla --> +<!-- This file is part of the queueing toolbox, a Queueing Networks --> +<!-- analysis package for GNU Octave. --> +<!-- The queueing toolbox is free software; you can redistribute it --> +<!-- and/or modify it under the terms of the GNU General Public License --> +<!-- as published by the Free Software Foundation; either version 3 of --> +<!-- the License, or (at your option) any later version. --> +<!-- The queueing toolbox is distributed in the hope that it will be --> +<!-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty --> +<!-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with the queueing toolbox; see the file COPYING. If not, see --> +<!-- <http://www.gnu.org/licenses/>. --> +<div class="node"> +<a name="Installation"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Getting-Started">Getting Started</a>, +Previous: <a rel="previous" accesskey="p" href="#Summary">Summary</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="chapter">2 Installing the queueing toolbox</h2> + +<ul class="menu"> +<li><a accesskey="1" href="#Installation-through-Octave-package-management-system">Installation through Octave package management system</a> +<li><a accesskey="2" href="#Manual-installation">Manual installation</a> +<li><a accesskey="3" href="#Content-of-the-source-distribution">Content of the source distribution</a> +<li><a accesskey="4" href="#Using-the-queueing-toolbox">Using the queueing toolbox</a> +</ul> + +<div class="node"> +<a name="Installation-through-Octave-package-management-system"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Manual-installation">Manual installation</a>, +Up: <a rel="up" accesskey="u" href="#Installation">Installation</a> + +</div> + +<h3 class="section">2.1 Installation through Octave package management system</h3> + +<p>The most recent version of <code>queueing</code> is 1.0.0 and can +be downloaded from + + <p><a href="http://www.moreno.marzolla.name/software/queueing/queueing-1.0.0.tar.gz">http://www.moreno.marzolla.name/software/queueing/queueing-1.0.0.tar.gz</a> + + <p>To install <code>queueing</code> in the system-wide location, such that all +functions are automatically available when Octave starts, you can use +‘<samp><span class="samp">pkg install</span></samp>’ command. At the Octave prompt, type the following: + +<pre class="example"> octave:1> <kbd>pkg install queueing-1.0.0.tar.gz</kbd> +</pre> + <p>(Note: you may need to start Octave as root in order to allow the +installation to copy the files to the target locations). After this, +all functions will be readily available each time Octave starts, +without the need to tweak the search path. To uninstall +<code>queueing</code>, use the ‘<samp><span class="samp">pkg uninstall queueing</span></samp>’ command. + + <p>If you do not have root access, you can do a local installation by +issuing the following command at the Octave prompt: + +<pre class="example"> octave:1> <kbd>pkg install -local queueing-1.0.0.tar.gz</kbd> +</pre> + <p>This will install <code>queueing</code> within the user's home directory, +and the package will be available to that user only. <strong>Note:</strong> +Octave version 3.2.3 as shipped with Ubuntu 10.04 seems to ignore +<code>-local</code> and always tries to install the package on the system +directory. + +<div class="node"> +<a name="Manual-installation"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Content-of-the-source-distribution">Content of the source distribution</a>, +Previous: <a rel="previous" accesskey="p" href="#Installation-through-Octave-package-management-system">Installation through Octave package management system</a>, +Up: <a rel="up" accesskey="u" href="#Installation">Installation</a> + +</div> + +<h3 class="section">2.2 Manual installation</h3> + +<p>If you want to install <code>queueing</code> in a custom location, you can +download the source tarball from the URL above, and unpack it +somewhere: + +<pre class="example"> <kbd>tar xfz queueing-1.0.0.tar.gz</kbd> + <kbd>cd queueing-1.0.0/</kbd> +</pre> + <p>Copy all <code>.m</code> files from the <samp><span class="file">inst/</span></samp> directory to some +target location. Then, you can start Octave with the <samp><span class="option">-p</span></samp> +option to add the target location to the search path, so that Octave +will find all <code>queueing</code> functions automatically: + +<pre class="example"> <kbd>octave -p </kbd><em>/path/to/queueing</em> +</pre> + <p>For example, if all <code>queueing</code> m-files are in +<samp><span class="file">/usr/local/queueing</span></samp>, you can start Octave as follows: + +<pre class="example"> <kbd>octave -p </kbd><samp><span class="file">/usr/local/queueing</span></samp> +</pre> + <p>If you want, you can add the following line to <samp><span class="file">~/.octaverc</span></samp>: + +<pre class="example"> <kbd>addpath("</kbd><em>/path/to/queueing</em><kbd>");</kbd> +</pre> + <p class="noindent">so that the path <samp><span class="file">/usr/local/queueing</span></samp> is automatically +added to the search path each time Octave is started, and you no +longer need to specify the <samp><span class="option">-p</span></samp> option on the command line. + +<div class="node"> +<a name="Content-of-the-source-distribution"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Using-the-queueing-toolbox">Using the queueing toolbox</a>, +Previous: <a rel="previous" accesskey="p" href="#Manual-installation">Manual installation</a>, +Up: <a rel="up" accesskey="u" href="#Installation">Installation</a> + +</div> + +<h3 class="section">2.3 Content of the source distribution</h3> + +<p>The <code>queueing</code> source distribution contains the following +subdirectories: + + <dl> +<dt><samp><span class="file">doc/</span></samp><dd>Documentation source. Most of the documentation is extracted from the +comment blocks of individual function files from the <samp><span class="file">inst/</span></samp> +directory. + + <br><dt><samp><span class="file">inst/</span></samp><dd>This directory contains the <tt>m</tt>-files which implement the +various Queueing Network algorithms provided by <code>queueing</code>. As a +notational convention, the names of source files containing functions +for Queueing Networks start with the ‘<samp><span class="samp">qn</span></samp>’ prefix; the name of +source files containing functions for Continuous-Time Markov Chains +(CTMSs) start with the ‘<samp><span class="samp">ctmc</span></samp>’ prefix, and the names of files +containing functions for Discrete-Time Markov Chains (DTMCs) start +with the ‘<samp><span class="samp">dtmc</span></samp>’ prefix. + + <br><dt><samp><span class="file">test/</span></samp><dd>This directory contains the test functions used to invoke all tests on +all function files. + + <br><dt><samp><span class="file">scripts/</span></samp><dd>This directory contains some utility scripts mostly from GNU Octave, +which extract the documentation from the specially-formatted comments +in the <tt>m</tt>-files. + + <br><dt><samp><span class="file">examples/</span></samp><dd>This directory contains examples which are automatically extracted +from the ‘<samp><span class="samp">demo</span></samp>’ blocks of the function files. + + <br><dt><samp><span class="file">broken/</span></samp><dd>This directory contains function files which are either not working +properly, or need additional testing before they can be moved to the +<samp><span class="file">inst/</span></samp> directory. + + </dl> + + <p>The <code>queueing</code> package ships with a Makefile which can be used +to produce the documentation (in PDF and HTML format), and +automatically execute all function tests. Specifically, the following +targets are defined: + + <dl> +<dt><code>all</code><dd>Running ‘<samp><span class="samp">make</span></samp>’ (or ‘<samp><span class="samp">make all</span></samp>’) on the top-level directory +builds the programs used to extract the documentation from the +comments embedded in the <tt>m</tt>-files, and then produce the +documentation in PDF and HTML format (<samp><span class="file">doc/queueing.pdf</span></samp> and +<samp><span class="file">doc/queueing.html</span></samp>, respectively). + + <br><dt><code>check</code><dd>Running ‘<samp><span class="samp">make check</span></samp>’ will execute all tests contained in the +<tt>m</tt>-files. If you modify the code of any function in the +<samp><span class="file">inst/</span></samp> directory, you should run the tests to ensure that no +errors have been introduced. You are also encouraged to contribute new +tests, especially for functions which are not adequately validated. + + <br><dt><code>clean</code><dt><code>distclean</code><dt><code>dist</code><dd>The ‘<samp><span class="samp">make clean</span></samp>’, ‘<samp><span class="samp">make distclean</span></samp>’ and ‘<samp><span class="samp">make dist</span></samp>’ +commands are used to clean up the source directory and prepare the +distribution archive in compressed tar format. + + </dl> + +<div class="node"> +<a name="Using-the-queueing-toolbox"></a> +<p><hr> +Previous: <a rel="previous" accesskey="p" href="#Content-of-the-source-distribution">Content of the source distribution</a>, +Up: <a rel="up" accesskey="u" href="#Installation">Installation</a> + +</div> + +<h3 class="section">2.4 Using the queueing toolbox</h3> + +<p>You can use all functions by simply invoking their name with the +appropriate parameters; the <code>queueing</code> package should display an +error message in case of missing/wrong parameters. You can display the +help text for any function using the <samp><span class="command">help</span></samp> command. For +example: + +<pre class="example"> octave:2> <kbd>help qnmvablo</kbd> +</pre> + <p>prints the documentation for the <samp><span class="command">qnmvablo</span></samp> function. +Additional information can be found in the <code>queueing</code> manual, +which is available in PDF format in <samp><span class="file">doc/queueing.pdf</span></samp> and in +HTML format in <samp><span class="file">doc/queueing.html</span></samp>. + + <p>Within GNU Octave, you can also run the test and demo blocks +associated to the functions, using the <samp><span class="command">test</span></samp> and +<samp><span class="command">demo</span></samp> commands respectively. To run all the tests of, say, +the <samp><span class="command">qnmvablo</span></samp> function: + +<pre class="example"> octave:3> <kbd>test qnmvablo</kbd> + -| PASSES 4 out of 4 tests +</pre> + <p>To execute the demos of the <samp><span class="command">qnclosed</span></samp> function, use the +following: + +<pre class="example"> octave:4> <kbd>demo qnclosed</kbd> +</pre> + <!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<!-- *- texinfo -*- --> +<!-- Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla --> +<!-- This file is part of the queueing toolbox, a Queueing Networks --> +<!-- analysis package for GNU Octave. --> +<!-- The queueing toolbox is free software; you can redistribute it --> +<!-- and/or modify it under the terms of the GNU General Public License --> +<!-- as published by the Free Software Foundation; either version 3 of --> +<!-- the License, or (at your option) any later version. --> +<!-- The queueing toolbox is distributed in the hope that it will be --> +<!-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty --> +<!-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with the queueing toolbox; see the file COPYING. If not, see --> +<!-- <http://www.gnu.org/licenses/>. --> +<div class="node"> +<a name="Getting-Started"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Markov-Chains">Markov Chains</a>, +Previous: <a rel="previous" accesskey="p" href="#Installation">Installation</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="chapter">3 Introduction and Getting Started</h2> + +<ul class="menu"> +<li><a accesskey="1" href="#Analysis-of-Closed-Networks">Analysis of Closed Networks</a> +<li><a accesskey="2" href="#Analysis-of-Open-Networks">Analysis of Open Networks</a> +</ul> + +<p>In this chapter we give some usage examples of the <code>queueing</code> +package. The reader is assumed to be familiar with Queueing Networks +(although some basic terminology and notation will be given +here). Additional usage examples are embedded in most of the function +files; to display and execute the demos associated with function +<em>fname</em> you can type <samp><span class="command">demo </span><em>fname</em></samp> at the Octave +prompt. For example + +<pre class="example"> <kbd>demo qnclosed</kbd> +</pre> + <p class="noindent">executes all demos (if any) for the <samp><span class="command">qnclosed</span></samp> function. + +<div class="node"> +<a name="Analysis-of-Closed-Networks"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Analysis-of-Open-Networks">Analysis of Open Networks</a>, +Up: <a rel="up" accesskey="u" href="#Getting-Started">Getting Started</a> + +</div> + +<h3 class="section">3.1 Analysis of Closed Networks</h3> + +<p>Let us consider a simple closed network with K=3 service +centers. Each center is of type M/M/1–FCFS. We denote with +S_i the average service time at center i, i=1, 2, +3. Let S_1 = 1.0, S_2 = 2.0 and S_3 = 0.8. The +routing of jobs within the network is described with a <em>routing +probability matrix</em> P. Specifically, a request completing +service at center i is enqueued at center j with +probability P_ij. Let us assume the following routing +probability matrix: + +<pre class="example"> [ 0 0.3 0.7 ] + P = [ 1 0 0 ] + [ 1 0 0 ] +</pre> + <p>For example, according to matric P a job completing service at +center 1 is routed to center 2 with probability 0.3, and is routed to +center 3 with probability 0.7. + + <p>The network above can be analyzed with the <samp><span class="command">qnclosed</span></samp> +function; if there is just a single class of requests, as in the +example above, <samp><span class="command">qnclosed</span></samp> calls <samp><span class="command">qnclosedsinglemva</span></samp> +which implements the Mean Value Analysys (MVA) algorithm for +single-class, product-form network. + + <p><samp><span class="command">qnclosed</span></samp> requires the following parameters: + + <dl> +<dt><var>N</var><dd>Number of requests in the network (since we are considering a closed +network, the number of requests is fixed) + + <br><dt><var>S</var><dd>Array of average service times at the centers: <var>S</var><code>(k)</code> is +the average service time at center k. + + <br><dt><var>V</var><dd>Array of visit ratios: <var>V</var><code>(k)</code> is the average number of +visits to center k. + + </dl> + + <p>As can be seen, we must compute the <em>visit ratios</em> (or visit +counts) V_k for each center k. The visit counts satisfy +the following equations: + +<pre class="example"> V_j = sum_i V_i P_ij +</pre> + <p>We can compute V_k from the routing probability matrix +P_ij using the <samp><span class="command">qnvisits</span></samp> function: + +<pre class="example"> <kbd>P = [0 0.3 0.7; 1 0 0; 1 0 0];</kbd> + <kbd>V = qnvisits(P)</kbd> + ⇒ V = 1.00000 0.30000 0.70000 +</pre> + <p>We can check that the computed values satisfy the above equation by +evaluating the following expression: + +<pre class="example"> <kbd>V*P</kbd> + ⇒ ans = 1.00000 0.30000 0.70000 +</pre> + <p class="noindent">which is equal to V. +Hence, we can analyze the network for a given population size N +(for example, N=10) as follows: + +<pre class="example"> <kbd>N = 10;</kbd> + <kbd>S = [1 2 0.8];</kbd> + <kbd>P = [0 0.3 0.7; 1 0 0; 1 0 0];</kbd> + <kbd>V = qnvisits(P);</kbd> + <kbd>[U R Q X] = qnclosed( N, S, V )</kbd> + ⇒ U = 0.99139 0.59483 0.55518 + ⇒ R = 7.4360 4.7531 1.7500 + ⇒ Q = 7.3719 1.4136 1.2144 + ⇒ X = 0.99139 0.29742 0.69397 +</pre> + <p>The output of <samp><span class="command">qnclosed</span></samp> includes the vector of utilizations +U_k at center k, response time R_k, average +number of customers Q_k and throughput X_k. In our +example, the throughput of center 1 is X_1 = 0.99139, and the +average number of requests in center 3 is Q_3 = 1.2144. The +utilization of center 1 is U_1 = 0.99139, which is the higher +value among the service centers. Tus, center 1 is the <em>bottleneck +device</em>. + + <p>This network can also be analyzed with the <samp><span class="command">qnsolve</span></samp> +function. <samp><span class="command">qnsolve</span></samp> can handle open, closed or mixed networks, +and allows the network to be described in a very flexible way. First, +let <var>Q1</var>, <var>Q2</var> and <var>Q3</var> be the variables describing the +service centers. Each variable is instantiated with the +<samp><span class="command">qnmknode</span></samp> function. + +<pre class="example"> <kbd>Q1 = qnmknode( "m/m/m-fcfs", 1 );</kbd> + <kbd>Q2 = qnmknode( "m/m/m-fcfs", 2 );</kbd> + <kbd>Q3 = qnmknode( "m/m/m-fcfs", 0.8 );</kbd> +</pre> + <p>The first parameter of <samp><span class="command">qnmknode</span></samp> is a string describing the +type of the node. Here we use <code>"m/m/m-fcfs"</code> to denote a +M/M/m–FCFS center. The second parameter gives the average +service time. An optional third parameter can be used to specify the +number m of service centers. If omitted, it is assumed +m=1 (single-server node). + + <p>Now, the network can be analyzed as follows: + +<pre class="example"> <kbd>N = 10;</kbd> + <kbd>V = [1 0.3 0.7];</kbd> + <kbd>[U R Q X] = qnsolve( "closed", N, { Q1, Q2, Q3 }, V )</kbd> + ⇒ U = 0.99139 0.59483 0.55518 + ⇒ R = 7.4360 4.7531 1.7500 + ⇒ Q = 7.3719 1.4136 1.2144 + ⇒ X = 0.99139 0.29742 0.69397 +</pre> + <p>Of course, we get exactly the same results. Other functions can be used +for closed networks, see <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a>. + +<div class="node"> +<a name="Analysis-of-Open-Networks"></a> +<p><hr> +Previous: <a rel="previous" accesskey="p" href="#Analysis-of-Closed-Networks">Analysis of Closed Networks</a>, +Up: <a rel="up" accesskey="u" href="#Getting-Started">Getting Started</a> + +</div> + +<h3 class="section">3.2 Analysis of Open Networks</h3> + +<p>Open networks can be analyzed in a similar way. Let us consider +an open network with K=3 service centers, and routing +probability matrix as follows: + +<pre class="example"> [ 0 0.3 0.5 ] + P = [ 1 0 0 ] + [ 1 0 0 ] +</pre> + <p>In this network, requests can leave the system from center 1 with +probability (1-(0.3+0.5) = 0.2. We suppose that external jobs +arrive at center 1 with rate \lambda_1 = 0.15; there are no +arrivals at centers 2 and 3. + + <p>Similarly to closed networks, we first need to compute the visit +counts V_k to center k. Again, we use the +<samp><span class="command">qnvisits</span></samp> function as follows: + +<pre class="example"> <kbd>P = [0 0.3 0.5; 1 0 0; 1 0 0];</kbd> + <kbd>lambda = [0.15 0 0];</kbd> + <kbd>V = qnvisits(P, lambda)</kbd> + ⇒ V = 5.00000 1.50000 2.50000 +</pre> + <p class="noindent">where <var>lambda</var><code>(k)</code> is the arrival rate at center k, +and <var>P</var> is the routing matrix. The visit counts V_k for +open networks satisfy the following equation: + +<pre class="example"> V_j = sum_i V_i P_ij +</pre> + <p>where P_0j is the probability of an external arrival to +center j. This can be computed as: + + <p>Assuming the same service times as in the previous example, the +network can be analyzed with the <samp><span class="command">qnopen</span></samp> function, as +follows: + +<pre class="example"> <kbd>S = [1 2 0.8];</kbd> + <kbd>[U R Q X] = qnopen( sum(lambda), S, V )</kbd> + ⇒ U = 0.75000 0.45000 0.30000 + ⇒ R = 4.0000 3.6364 1.1429 + ⇒ Q = 3.00000 0.81818 0.42857 + ⇒ X = 0.75000 0.22500 0.37500 +</pre> + <p>The first parameter of the <samp><span class="command">qnopen</span></samp> function is the (scalar) +aggregate arrival rate. + + <p>Again, it is possible to use the <samp><span class="command">qnsolve</span></samp> high-level function: + +<pre class="example"> <kbd>Q1 = qnmknode( "m/m/m-fcfs", 1 );</kbd> + <kbd>Q2 = qnmknode( "m/m/m-fcfs", 2 );</kbd> + <kbd>Q3 = qnmknode( "m/m/m-fcfs", 0.8 );</kbd> + <kbd>lambda = [0.15 0 0];</kbd> + <kbd>[U R Q X] = qnsolve( "open", sum(lambda), { Q1, Q2, Q3 }, V )</kbd> + ⇒ U = 0.75000 0.45000 0.30000 + ⇒ R = 4.0000 3.6364 1.1429 + ⇒ Q = 3.00000 0.81818 0.42857 + ⇒ X = 0.75000 0.22500 0.37500 +</pre> + <!-- @node Markov Chains Analysis --> +<!-- @section Markov Chains Analysis --> +<!-- @subsection Discrete-Time Markov Chains --> +<!-- (TODO) --> +<!-- @subsection Continuous-Time Markov Chains --> +<!-- (TODO) --> +<!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<!-- *- texinfo -*- --> +<!-- Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla --> +<!-- This file is part of the queueing toolbox, a Queueing Networks --> +<!-- analysis package for GNU Octave. --> +<!-- The queueing toolbox is free software; you can redistribute it --> +<!-- and/or modify it under the terms of the GNU General Public License --> +<!-- as published by the Free Software Foundation; either version 3 of --> +<!-- the License, or (at your option) any later version. --> +<!-- The queueing toolbox is distributed in the hope that it will be --> +<!-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty --> +<!-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with the queueing toolbox; see the file COPYING. If not, see --> +<!-- <http://www.gnu.org/licenses/>. --> +<div class="node"> +<a name="Markov-Chains"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a>, +Previous: <a rel="previous" accesskey="p" href="#Getting-Started">Getting Started</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="chapter">4 Markov Chains</h2> + +<ul class="menu"> +<li><a accesskey="1" href="#Discrete_002dTime-Markov-Chains">Discrete-Time Markov Chains</a> +<li><a accesskey="2" href="#Continuous_002dTime-Markov-Chains">Continuous-Time Markov Chains</a> +</ul> + +<div class="node"> +<a name="Discrete-Time-Markov-Chains"></a> +<a name="Discrete_002dTime-Markov-Chains"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Continuous_002dTime-Markov-Chains">Continuous-Time Markov Chains</a>, +Up: <a rel="up" accesskey="u" href="#Markov-Chains">Markov Chains</a> + +</div> + +<h3 class="section">4.1 Discrete-Time Markov Chains</h3> + +<ul class="menu"> +<li><a accesskey="1" href="#DTMC-Stationary-Probability">DTMC Stationary Probability</a> +<li><a accesskey="2" href="#DTMC-First-Passage-Times">DTMC First Passage Times</a> +</ul> + +<div class="node"> +<a name="DTMC-Stationary-Probability"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#DTMC-First-Passage-Times">DTMC First Passage Times</a>, +Up: <a rel="up" accesskey="u" href="#Discrete_002dTime-Markov-Chains">Discrete-Time Markov Chains</a> + +</div> + +<h4 class="subsection">4.1.1 Stationary Probability</h4> + +<p><a name="doc_002ddtmc"></a> + +<div class="defun"> +— Function File: <var>p</var> = <b>dtmc</b> (<var>P</var>)<var><a name="index-dtmc-1"></a></var><br> +— Function File: <var>p</var> = <b>dtmc</b> (<var>P, n, p0</var>)<var><a name="index-dtmc-2"></a></var><br> +<blockquote> + <p><a name="index-Markov-chain_002c-discrete-time-3"></a><a name="index-Discrete-time-Markov-chain-4"></a><a name="index-Markov-chain_002c-stationary-probabilities-5"></a><a name="index-Stationary-probabilities-6"></a> +With a single argument, compute the steady-state probability vector +<var>p</var><code>(1), ..., </code><var>p</var><code>(N)</code> for a +Discrete-Time Markov Chain given the N \times N transition +probability matrix <var>P</var>. With three arguments, compute the +probability vector <var>p</var><code>(1), ..., </code><var>p</var><code>(N)</code> +after <var>n</var> steps, given initial probability vector <var>p0</var> at +time 0. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>P</var><dd><var>P</var><code>(i,j)</code> is the transition probability from state i +to state j. <var>P</var> must be an irreducible stochastic matrix, +which means that the sum of each row must be 1 (\sum_j=1^N P_i j = 1), and the rank of +<var>P</var> must be equal to its dimension. + + <br><dt><var>n</var><dd>Step at which to compute the transient probability + + <br><dt><var>p0</var><dd><var>p0</var><code>(i)</code> is the probability that at step 0 the system +is in state i. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>p</var><dd>If this function is invoked with a single argument, +<var>p</var><code>(i)</code> is the steady-state probability that the system is +in state i. <var>p</var> satisfies the equations p = p\bf P and \sum_i=1^N p_i = 1. If this function is invoked +with three arguments, <var>p</var><code>(i)</code> is the marginal probability +that the system is in state i at step <var>n</var>, +given the initial probabilities <var>p0</var><code>(i)</code> that the initial state is +i. + + </dl> + + </blockquote></div> + +<div class="node"> +<a name="DTMC-First-Passage-Times"></a> +<p><hr> +Previous: <a rel="previous" accesskey="p" href="#DTMC-Stationary-Probability">DTMC Stationary Probability</a>, +Up: <a rel="up" accesskey="u" href="#Discrete_002dTime-Markov-Chains">Discrete-Time Markov Chains</a> + +</div> + +<h4 class="subsection">4.1.2 First Passage Times</h4> + +<p>The First Passage Time M_i j is defined as the average +number of transitions needed to visit state j for the first +time, starting from state i. Matrix \bf M satisfies the +property that + +<pre class="example"> ___ + \ + M_ij = 1 + > P_ij * M_kj + /___ + k!=j +</pre> + <p><a name="doc_002ddtmc_005ffpt"></a> + +<div class="defun"> +— Function File: <var>M</var> = <b>dtmc_fpt</b> (<var>P</var>)<var><a name="index-dtmc_005ffpt-7"></a></var><br> +— Function File: <var>m</var> = <b>dtmc_fpt</b> (<var>P, i, j</var>)<var><a name="index-dtmc_005ffpt-8"></a></var><br> +<blockquote> + <p><a name="index-Markov-chain_002c-discrete-time-9"></a><a name="index-First-passage-times-10"></a> +If called with a single argument, computes the mean first passage +times <var>M</var><code>(i,j)</code>, that are the average number of transitions before +state <var>j</var> is reached, starting from state <var>i</var>, for all +1 \leq i, j \leq N. If called with three arguments, returns +the single value <var>m</var><code> = </code><var>M</var><code>(i,j)</code>. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>P</var><dd><var>P</var><code>(i,j)</code> is the transition probability from state i +to state j. <var>P</var> must be an irreducible stochastic matrix, +which means that the sum of each row must be 1 (\sum_j=1^N +P_i j = 1), and the rank of <var>P</var> must be equal to its +dimension. + + <br><dt><var>i</var><dd>Initial state. + + <br><dt><var>j</var><dd>Destination state. If <var>j</var> is a vector, returns the mean first passage +time to any state in <var>j</var>. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>M</var><dd>If this function is called with a single argument, the result +<var>M</var><code>(i,j)</code> is the average number of transitions before state +<var>j</var> is reached for the first time, starting from state <var>i</var>. + + <br><dt><var>m</var><dd>If this function is called with three arguments, the result <var>m</var> +is the average number of transitions before state <var>j</var> is visited +for the first time, starting from state <var>i</var>. + + </dl> + + </blockquote></div> + +<div class="node"> +<a name="Continuous-Time-Markov-Chains"></a> +<a name="Continuous_002dTime-Markov-Chains"></a> +<p><hr> +Previous: <a rel="previous" accesskey="p" href="#Discrete_002dTime-Markov-Chains">Discrete-Time Markov Chains</a>, +Up: <a rel="up" accesskey="u" href="#Markov-Chains">Markov Chains</a> + +</div> + +<h3 class="section">4.2 Continuous-Time Markov Chains</h3> + +<ul class="menu"> +<li><a accesskey="1" href="#CTMC-Stationary-Probability">CTMC Stationary Probability</a> +<li><a accesskey="2" href="#Birth_002dDeath-process">Birth-Death process</a> +<li><a accesskey="3" href="#Expected-Sojourn-Time">Expected Sojourn Time</a> +<li><a accesskey="4" href="#Time_002dAveraged-Expected-Sojourn-Time">Time-Averaged Expected Sojourn Time</a> +<li><a accesskey="5" href="#Expected-Time-to-Absorption">Expected Time to Absorption</a> +<li><a accesskey="6" href="#CTMC-First-Passage-Times">CTMC First Passage Times</a> +</ul> + +<div class="node"> +<a name="CTMC-Stationary-Probability"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Birth_002dDeath-process">Birth-Death process</a>, +Up: <a rel="up" accesskey="u" href="#Continuous_002dTime-Markov-Chains">Continuous-Time Markov Chains</a> + +</div> + +<h4 class="subsection">4.2.1 Stationary Probability</h4> + +<p><a name="doc_002dctmc"></a> + +<div class="defun"> +— Function File: <var>p</var> = <b>ctmc</b> (<var>Q</var>)<var><a name="index-ctmc-11"></a></var><br> +— Function File: <var>p</var> = <b>ctmc</b> (<var>Q, t. q0</var>)<var><a name="index-ctmc-12"></a></var><br> +<blockquote> + <p><a name="index-Markov-chain_002c-continuous-time-13"></a><a name="index-Continuous-time-Markov-chain-14"></a><a name="index-Markov-chain_002c-state-occupancy-probabilities-15"></a><a name="index-Stationary-probabilities-16"></a> +With a single argument, compute the stationary state occupancy +probability vector <var>p</var>(1), <small class="dots">...</small>, <var>p</var>(N) for a +Continuous-Time Markov Chain with infinitesimal generator matrix +<var>Q</var> of size N \times N. With three arguments, compute the +state occupancy probabilities <var>p</var>(1), <small class="dots">...</small>, <var>p</var>(N) at time +<var>t</var>, given initial state occupancy probabilities <var>p0</var> at time +0. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>Q</var><dd>Infinitesimal generator matrix. <var>Q</var> is a N \times N square +matrix where <var>Q</var><code>(i,j)</code> is the transition rate from state +i to state j, for 1 ≤ i \neq j ≤ N. +Transition rates must be nonnegative, and \sum_j=1^N Q_i j = 0 + + <br><dt><var>t</var><dd>Time at which to compute the transient probability + + <br><dt><var>p0</var><dd><var>p0</var><code>(i)</code> is the probability that the system +is in state i at time 0 . + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>p</var><dd>If this function is invoked with a single argument, +<var>p</var><code>(i)</code> is the steady-state probability that the system is +in state i, i = 1, <small class="dots">...</small>, N. The vector <var>p</var> +satisfies the equation p\bf Q = 0 and \sum_i=1^N p_i = 1. +If this function is invoked with three arguments, <var>p</var><code>(i)</code> +is the probability that the system is in state i at time <var>t</var>, +given the initial occupancy probabilities <var>q0</var>. + + </dl> + + </blockquote></div> + +<p class="noindent"><strong>EXAMPLE</strong> + + <p>Consider a two-state CTMC such that transition rates between states +are equal to 1. This can be solved as follows: + +<pre class="example"><pre class="verbatim"> Q = [ -1 1; \ + 1 -1 ]; + q = ctmc(Q)</pre> ⇒ q = 0.50000 0.50000 +</pre> + <div class="node"> +<a name="Birth-Death-process"></a> +<a name="Birth_002dDeath-process"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Expected-Sojourn-Time">Expected Sojourn Time</a>, +Previous: <a rel="previous" accesskey="p" href="#CTMC-Stationary-Probability">CTMC Stationary Probability</a>, +Up: <a rel="up" accesskey="u" href="#Continuous_002dTime-Markov-Chains">Continuous-Time Markov Chains</a> + +</div> + +<h4 class="subsection">4.2.2 Birth-Death process</h4> + +<p><a name="doc_002dctmc_005fbd"></a> + +<div class="defun"> +— Function File: <var>p</var> = <b>ctmc_bd</b> (<var>birth, death</var>)<var><a name="index-ctmc_005fbd-17"></a></var><br> +<blockquote> + <p><a name="index-Markov-chain_002c-continuous-time-18"></a><a name="index-Birth_002ddeath-process-19"></a> +Compute the steady-state solution of a birth-death process with state +space (1, <small class="dots">...</small>, N). + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>birth</var><dd>Vector with N-1 elements, where <var>birth</var><code>(i)</code> is the +transition rate from state i to state i+1. + + <br><dt><var>death</var><dd>Vector with N-1 elements, where <var>death</var><code>(i)</code> is the +transition rate from state i+1 to state i. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>p</var><dd><var>p</var><code>(i)</code> is the steady-state probability that the system is +in state i, i=1, <small class="dots">...</small>, N. + + </dl> + + </blockquote></div> + +<div class="node"> +<a name="Expected-Sojourn-Time"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Time_002dAveraged-Expected-Sojourn-Time">Time-Averaged Expected Sojourn Time</a>, +Previous: <a rel="previous" accesskey="p" href="#Birth_002dDeath-process">Birth-Death process</a>, +Up: <a rel="up" accesskey="u" href="#Continuous_002dTime-Markov-Chains">Continuous-Time Markov Chains</a> + +</div> + +<h4 class="subsection">4.2.3 Expected Sojourn Time</h4> + +<p>Given a N state continuous-time Markov Chain with infinitesimal +generator matrix \bf Q, we define the vector \bf L(t) = +(L_1(t), L_2(t), \ldots L_N(t)) such that L_i(t) is the +expected sojourn time in state i during the interval +[0,t), assuming that the initial occupancy probability at time +0 was \bf \pi(0). Then, \bf L(t) is the solution of +the following differential equation: + +<pre class="example"> dL + --(t) = L(t) Q + pi(0), L(0) = 0 + dt +</pre> + <p>The function <code>ctmc_exps</code> can be used to compute \bf +L(t), by using the <code>lsode</code> Octave function to solve the above +linear differential equation. + + <p><a name="doc_002dctmc_005fexps"></a> + +<div class="defun"> +— Function File: <var>L</var> = <b>ctmc_exps</b> (<var>Q, tt, p</var>)<var><a name="index-ctmc_005fexps-20"></a></var><br> +<blockquote> + <p><a name="index-Markov-chain_002c-continuous-time-21"></a><a name="index-Expected-sojourn-time-22"></a> +Compute the expected total time <var>L</var><code>(t,j)</code> spent in state +j during the time interval <code>[0,</code><var>tt</var><code>(t))</code>, assuming +that at time 0 the state occupancy probability was <var>p</var>. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>Q</var><dd>Infinitesimal generator matrix. <var>Q</var><code>(i,j)</code> is the transition +rate from state i to state j, +1 ≤ i \neq j ≤ N. The matrix <var>Q</var> must also satisfy the +condition <code>sum(</code><var>Q</var><code>,2) == 0</code> + + <br><dt><var>tt</var><dd>This parameter is a vector used for numerical integration. The first +element <var>tt</var><code>(1)</code> must be 0, and the last element +<var>tt</var><code>(end)</code> must be the upper bound of the interval +[0,t) of interest (<var>tt</var><code>(end) == t</code>). + + <br><dt><var>p</var><dd><var>p</var><code>(i)</code> is the probability that at time 0 the system was in +state i, for all i = 1, <small class="dots">...</small>, N + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>L</var><dd><var>L</var><code>(t,j)</code> is the expected time spent in state j +during the interval <code>[0,</code><var>tt</var><code>(t))</code>. <code>1 ≤ </code><var>t</var><code> ≤ length(</code><var>tt</var><code>)</code> + + </dl> + + </blockquote></div> + +<p class="noindent"><strong>EXAMPLE</strong> + + <p>Let us consider a pure-birth, 4-states CTMC such that the transition +rate from state i to state i+1 is \lambda_i = i +\lambda (i=1, 2, 3), with \lambda = 0.5. The following +code computes the expected sojourn time in state i, +given the initial occupancy probability p_0=(1,0,0,0). + +<pre class="example"><pre class="verbatim"> lambda = 0.5; + N = 4; + birth = lambda*linspace(1,N-1,N-1); + death = zeros(1,N-1); + Q = diag(birth,1)+diag(death,-1); + Q -= diag(sum(Q,2)); + tt = linspace(0,10,100); + p0 = zeros(1,N); p0(1)=1; + L = ctmc_exps(Q,tt,p0); + plot( tt, L(:,1), ";State 1;", "linewidth", 2, \ + tt, L(:,2), ";State 2;", "linewidth", 2, \ + tt, L(:,3), ";State 3;", "linewidth", 2, \ + tt, L(:,4), ";State 4 (absorbing);", "linewidth", 2); + legend("location","northwest"); + xlabel("Time"); + ylabel("Expected sojourn time");</pre> +</pre> + <div class="node"> +<a name="Time-Averaged-Expected-Sojourn-Time"></a> +<a name="Time_002dAveraged-Expected-Sojourn-Time"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Expected-Time-to-Absorption">Expected Time to Absorption</a>, +Previous: <a rel="previous" accesskey="p" href="#Expected-Sojourn-Time">Expected Sojourn Time</a>, +Up: <a rel="up" accesskey="u" href="#Continuous_002dTime-Markov-Chains">Continuous-Time Markov Chains</a> + +</div> + +<h4 class="subsection">4.2.4 Time-Averaged Expected Sojourn Time</h4> + +<p><a name="doc_002dctmc_005ftaexps"></a> + +<div class="defun"> +— Function File: <var>M</var> = <b>ctmc_taexps</b> (<var>Q, tt, p</var>)<var><a name="index-ctmc_005ftaexps-23"></a></var><br> +<blockquote> + <p><a name="index-Markov-chain_002c-continuous-time-24"></a><a name="index-Time_002dalveraged-sojourn-time-25"></a> +Compute the <em>time-averaged sojourn time</em> <var>M</var><code>(t,j)</code>, +defined as the fraction of the time interval <code>[0,</code><var>tt</var><code>(t))</code> spent in +state j, assuming that at time 0 the state occupancy +probability was <var>p</var>. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>Q</var><dd>Infinitesimal generator matrix. <var>Q</var><code>(i,j)</code> is the transition +rate from state i to state j, +1 ≤ i \neq j ≤ N. The +matrix <var>Q</var> must also satisfy the condition <code>sum(</code><var>Q</var><code>,2) == 0</code> + + <br><dt><var>tt</var><dd>This parameter is a vector used for numerical integration of the +sujourn time. The first element <var>tt</var><code>(1)</code> must be slightly +larger than 0, and the +last element <var>tt</var><code>(end)</code> must be the upper limit of the +interval [0,t) of interest (<var>tt</var><code>(end) == t</code>). +This vector is used by the ODE solver to compute the solution +<var>M</var>. + + <br><dt><var>p</var><dd><var>p</var><code>(i)</code> is the probability that, at time 0, the system was in +state i, for all i = 1, <small class="dots">...</small>, N + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>M</var><dd><var>M</var><code>(t,j)</code> is the expected fraction of time spent in state +j during the interval [0,tt(t)) assuming that the state +occupancy probability at time zero was <var>p</var>. <code>1 ≤ +</code><var>t</var><code> ≤ length(</code><var>tt</var><code>)</code> + + </dl> + + </blockquote></div> + +<p class="noindent"><strong>EXAMPLE</strong> + +<pre class="example"><pre class="verbatim"> lambda = 0.5; + N = 4; + birth = lambda*linspace(1,N-1,N-1); + death = zeros(1,N-1); + Q = diag(birth,1)+diag(death,-1); + Q -= diag(sum(Q,2)); + t = linspace(1e-3,50,500); + p = zeros(1,N); p(1)=1; + M = ctmc_taexps(Q,t,p); + 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"); + xlabel("Time"); + ylabel("Time-averaged Expected sojourn time");</pre> +</pre> + <div class="node"> +<a name="Expected-Time-to-Absorption"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#CTMC-First-Passage-Times">CTMC First Passage Times</a>, +Previous: <a rel="previous" accesskey="p" href="#Time_002dAveraged-Expected-Sojourn-Time">Time-Averaged Expected Sojourn Time</a>, +Up: <a rel="up" accesskey="u" href="#Continuous_002dTime-Markov-Chains">Continuous-Time Markov Chains</a> + +</div> + +<h4 class="subsection">4.2.5 Expected Time to Absorption</h4> + +<p>If we consider a Markov Chain with absorbing states, it is possible to +define the <em>expected time to absorption</em> as the expected time +until the system goes into an absorbing state. More specifically, let +us suppose that A is the set of transient (i.e., non-absorbing) +states of a CTMC with N states and infinitesimal generator +matrix \bf Q. The expected time to absorption \bf +L_A(\infty) is defined as the solution of the following equation: + +<pre class="example"> L_A( inf ) Q_A = -pi_A(0) +</pre> + <p class="noindent">where \bf Q_A is the restriction of matrix \bf Q to +only states in A, and \bf \pi_A(0) is the initial +state occupancy probability at time 0, restricted to states in +A. + + <p><a name="doc_002dctmc_005fmtta"></a> + +<div class="defun"> +— Function File: <var>t</var> = <b>ctmc_mtta</b> (<var>Q, p</var>)<var><a name="index-ctmc_005fmtta-26"></a></var><br> +<blockquote> + <p><a name="index-Markov-chain_002c-continuous-time-27"></a><a name="index-Mean-time-to-absorption-28"></a> +Compute the Mean-Time to Absorption (MTTA) starting from initial +occupancy probability <var>p</var> at time 0. If there are no absorbing +states, this function fails with an error. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>Q</var><dd>N \times N infinitesimal generator matrix. <var>Q</var><code>(i,j)</code> +is the transition rate from state i to state j, i +\neq j. The matrix <var>Q</var> must satisfy the condition +\sum_j=1^N Q_i j = 0 + + <br><dt><var>p</var><dd><var>p</var><code>(i)</code> is the probability that the system is in state i +at time 0, for each i=1, <small class="dots">...</small>, N + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>t</var><dd>Mean time to absorption of the process represented by matrix <var>Q</var>. +If there are no absorbing states, this function fails. + + </dl> + + </blockquote></div> + +<p class="noindent"><strong>EXAMPLE</strong> + + <p>Let us consider a simple model of a redundant disk array. We assume +that the array is made of 5 independent disks, such that the array can +tolerate up to 2 disk failures without losing data. If three or more +disks break, the array is dead and unrecoverable. We want to estimate +the Mean-Time-To-Failure (MTTF) of the disk array. + + <p>We model this system as a 4 states Markov chain with state space +\ 2, 3, 4, 5 \. State i denotes the fact that exactly +i disks are active; state 2 is absorbing. Let \mu +be the failure rate of a single disk. The system starts in state +5 (all disks are operational). We use a pure death process, +with death rate from state i to state i-1 is \mu +i, for i = 3, 4, 5). + + <p>The MTTF of the disk array is the MTTA of the Markov Chain, and can be +computed with the following expression: + +<pre class="example"><pre class="verbatim"> mu = 0.01; + death = [ 3 4 5 ] * mu; + Q = diag(death,-1); + Q -= diag(sum(Q,2)); + t = ctmc_mtta(Q,[0 0 0 1])</pre> ⇒ t = 78.333 +</pre> + <p class="noindent"><strong>REFERENCES</strong> + + <p>G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, <cite>Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications</cite>, Wiley, +1998. + + <p><a name="index-Bolch_002c-G_002e-29"></a><a name="index-Greiner_002c-S_002e-30"></a><a name="index-de-Meer_002c-H_002e-31"></a><a name="index-Trivedi_002c-K_002e-32"></a> +<div class="node"> +<a name="CTMC-First-Passage-Times"></a> +<p><hr> +Previous: <a rel="previous" accesskey="p" href="#Expected-Time-to-Absorption">Expected Time to Absorption</a>, +Up: <a rel="up" accesskey="u" href="#Continuous_002dTime-Markov-Chains">Continuous-Time Markov Chains</a> + +</div> + +<h4 class="subsection">4.2.6 First Passage Times</h4> + +<p><a name="doc_002dctmc_005ffpt"></a> + +<div class="defun"> +— Function File: <var>M</var> = <b>ctmc_fpt</b> (<var>Q</var>)<var><a name="index-ctmc_005ffpt-33"></a></var><br> +— Function File: <var>m</var> = <b>ctmc_fpt</b> (<var>Q, i, j</var>)<var><a name="index-ctmc_005ffpt-34"></a></var><br> +<blockquote> + <p><a name="index-Markov-chain_002c-continuous-time-35"></a><a name="index-First-passage-times-36"></a> +If called with a single argument, computes the mean first passage +times <var>M</var><code>(i,j)</code>, the average times before state <var>j</var> is +reached, starting from state <var>i</var>, for all 1 \leq i, j \leq +N. If called with three arguments, returns the single value +<var>m</var><code> = </code><var>M</var><code>(i,j)</code>. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>Q</var><dd>Infinitesimal generator matrix. <var>Q</var> is a N \times N square +matrix where <var>Q</var><code>(i,j)</code> is the transition rate from state +i to state j, for 1 ≤ i \neq j ≤ N. +Transition rates must be nonnegative, and \sum_j=1^N Q_i j = 0 + + <br><dt><var>i</var><dd>Initial state. + + <br><dt><var>j</var><dd>Destination state. If <var>j</var> is a vector, returns the mean first passage +time to any state in <var>j</var>. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>M</var><dd>If this function is called with a single argument, the result +<var>M</var><code>(i,j)</code> is the average time before state +<var>j</var> is visited for the first time, starting from state <var>i</var>. + + <br><dt><var>m</var><dd>If this function is called with three arguments, the result +<var>m</var> is the average time before state <var>j</var> is visited for the first +time, starting from state <var>i</var>. + + </dl> + + </blockquote></div> + +<!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<!-- *- texinfo -*- --> +<!-- Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla --> +<!-- This file is part of the queueing toolbox, a Queueing Networks --> +<!-- analysis package for GNU Octave. --> +<!-- The queueing toolbox is free software; you can redistribute it --> +<!-- and/or modify it under the terms of the GNU General Public License --> +<!-- as published by the Free Software Foundation; either version 3 of --> +<!-- the License, or (at your option) any later version. --> +<!-- The queueing toolbox is distributed in the hope that it will be --> +<!-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty --> +<!-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with the queueing toolbox; see the file COPYING. If not, see --> +<!-- <http://www.gnu.org/licenses/>. --> +<div class="node"> +<a name="Single-Station-Queueing-Systems"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Queueing-Networks">Queueing Networks</a>, +Previous: <a rel="previous" accesskey="p" href="#Markov-Chains">Markov Chains</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="chapter">5 Single Station Queueing Systems</h2> + +<p>Single Station Queueing Systems contain a single station, and are thus +quite easy to analyze. The <code>queueing</code> package contains functions +for handling the following types of queues: + +<ul class="menu"> +<li><a accesskey="1" href="#The-M_002fM_002f1-System">The M/M/1 System</a>: Single-server queueing station. +<li><a accesskey="2" href="#The-M_002fM_002fm-System">The M/M/m System</a>: Multiple-server queueing station. +<li><a accesskey="3" href="#The-M_002fM_002finf-System">The M/M/inf System</a>: Infinite-server (delay center) station. +<li><a accesskey="4" href="#The-M_002fM_002f1_002fK-System">The M/M/1/K System</a>: Single-server, finite-capacity queueing station. +<li><a accesskey="5" href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a>: Multiple-server, finite-capacity queueing station. +<li><a accesskey="6" href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a>: Asymmetric multiple-server queueing station. +<li><a accesskey="7" href="#The-M_002fG_002f1-System">The M/G/1 System</a>: Single-server with general service time distribution. +<li><a accesskey="8" href="#The-M_002fHm_002f1-System">The M/Hm/1 System</a>: Single-server with hyperexponential service time distribution. +</ul> + + <p>The functions which analyze the queues above can be used as building +blocks for analyzing Queueing Networks. For example, Jackson networks +can be solved by computing the aggregate arrival rates to each node, +and then solving each node in isolation as if it were a single station +queueing system. + +<!-- M/M/1 --> +<div class="node"> +<a name="The-M%2fM%2f1-System"></a> +<a name="The-M_002fM_002f1-System"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#The-M_002fM_002fm-System">The M/M/m System</a>, +Up: <a rel="up" accesskey="u" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a> + +</div> + +<h3 class="section">5.1 The M/M/1 System</h3> + +<p>The M/M/1 system is made of a single server connected to an +unlimited FCFS queue. The mean arrival rate is Poisson with arrival +rate \lambda; the service time is exponentially distributed +with average service rate \mu. The system is stable if +\lambda < \mu. + + <p><a name="doc_002dqnmm1"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>p0</var>] = <b>qnmm1</b> (<var>lambda, mu</var>)<var><a name="index-qnmm1-37"></a></var><br> +<blockquote> + <p><a name="index-g_t_0040math_007bM_002fM_002f1_007d-system-38"></a> +Compute utilization, response time, average number of requests +and throughput for a M/M/1 queue. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Arrival rate (<var>lambda</var><code> > 0</code>). + + <br><dt><var>mu</var><dd>Service rate (<var>mu</var><code> > </code><var>lambda</var>). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>Server utilization + + <br><dt><var>R</var><dd>Service center response time + + <br><dt><var>Q</var><dd>Average number of requests in the system + + <br><dt><var>X</var><dd>Service center throughput. If the system is ergodic, +we will always have <var>X</var><code> = </code><var>lambda</var> + + <br><dt><var>p0</var><dd>Steady-state probability that there are no requests in the system. + + </dl> + + <p><var>lambda</var> and <var>mu</var> can be vectors of the same size. In this +case, the results will be vectors as well. + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnmmm, qnmminf, qnmmmk. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + +<p class="noindent">G. Bolch, S. Greiner, H. de Meer and K. Trivedi, <cite>Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications</cite>, Wiley, 1998, Section 6.3. + + <p><a name="index-Bolch_002c-G_002e-39"></a><a name="index-Greiner_002c-S_002e-40"></a><a name="index-de-Meer_002c-H_002e-41"></a><a name="index-Trivedi_002c-K_002e-42"></a> +<!-- M/M/m --> +<div class="node"> +<a name="The-M%2fM%2fm-System"></a> +<a name="The-M_002fM_002fm-System"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#The-M_002fM_002finf-System">The M/M/inf System</a>, +Previous: <a rel="previous" accesskey="p" href="#The-M_002fM_002f1-System">The M/M/1 System</a>, +Up: <a rel="up" accesskey="u" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a> + +</div> + +<h3 class="section">5.2 The M/M/m System</h3> + +<p>The M/M/m system is similar to the M/M/1 system, except +that there are m \geq 1 identical servers connected to a single +queue. Thus, at most m requests can be served at the same +time. The M/M/m system can be seen as a single server with +load-dependent service rate \mu(n), which is a function of the +number n of nodes in the center: + +<pre class="example"> <code>mu(n) = min(m,n)*mu</code> +</pre> + <p><a name="doc_002dqnmmm"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>p0</var>, <var>pm</var>] = <b>qnmmm</b> (<var>lambda, mu</var>)<var><a name="index-qnmmm-43"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>p0</var>, <var>pm</var>] = <b>qnmmm</b> (<var>lambda, mu, m</var>)<var><a name="index-qnmmm-44"></a></var><br> +<blockquote> + <p><a name="index-g_t_0040math_007bM_002fM_002fm_007d-system-45"></a> +Compute utilization, response time, average number of requests in +service and throughput for a M/M/m queue, a queueing +system with m identical service centers connected to a single queue. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Arrival rate (<var>lambda</var><code>>0</code>). + + <br><dt><var>mu</var><dd>Service rate (<var>mu</var><code>></code><var>lambda</var>). + + <br><dt><var>m</var><dd>Number of servers (<var>m</var><code> ≥ 1</code>). +If omitted, it is assumed <var>m</var><code>=1</code>. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>Service center utilization, U = \lambda / (m \mu). + + <br><dt><var>R</var><dd>Service center response time + + <br><dt><var>Q</var><dd>Average number of requests in the system + + <br><dt><var>X</var><dd>Service center throughput. If the system is ergodic, +we will always have <var>X</var><code> = </code><var>lambda</var> + + <br><dt><var>p0</var><dd>Steady-state probability that there are 0 requests in the system + + <br><dt><var>pm</var><dd>Steady-state probability that an arriving request has to wait in the +queue + + </dl> + + <p><var>lambda</var>, <var>mu</var> and <var>m</var> can be vectors of the same size. In this +case, the results will be vectors as well. + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnmm1,qnmminf,qnmmmk. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + +<p class="noindent">G. Bolch, S. Greiner, H. de Meer and K. Trivedi, <cite>Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications</cite>, Wiley, 1998, Section 6.5. + + <p><a name="index-Bolch_002c-G_002e-46"></a><a name="index-Greiner_002c-S_002e-47"></a><a name="index-de-Meer_002c-H_002e-48"></a><a name="index-Trivedi_002c-K_002e-49"></a> +<!-- M/M/inf --> +<div class="node"> +<a name="The-M%2fM%2finf-System"></a> +<a name="The-M_002fM_002finf-System"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#The-M_002fM_002f1_002fK-System">The M/M/1/K System</a>, +Previous: <a rel="previous" accesskey="p" href="#The-M_002fM_002fm-System">The M/M/m System</a>, +Up: <a rel="up" accesskey="u" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a> + +</div> + +<h3 class="section">5.3 The M/M/inf System</h3> + +<p>The M/M/\infty system is similar to the M/M/m system, +except that there are infinitely many identical servers (that is, +m = \infty). Each new request is assigned to a new server, so +that queueing never occurs. The M/M/\infty system is always +stable. + + <p><a name="doc_002dqnmminf"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>p0</var>] = <b>qnmminf</b> (<var>lambda, mu</var>)<var><a name="index-qnmminf-50"></a></var><br> +<blockquote> + <p>Compute utilization, response time, average number of requests and +throughput for a M/M/\infty queue. This is a system with an +infinite number of identical servers. Note that a M/M/\infty +system is always stable, regardless the values of the arrival and +service rates. + + <p><a name="index-g_t_0040math_007bM_002fM_002f_007dinf-system-51"></a> + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Arrival rate (<var>lambda</var><code>>0</code>). + + <br><dt><var>mu</var><dd>Service rate (<var>mu</var><code>>0</code>). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>Traffic intensity (defined as \lambda/\mu). Note that this is +different from the utilization, which in the case of M/M/\infty +centers is always zero. + + <p><a name="index-traffic-intensity-52"></a> +<br><dt><var>R</var><dd>Service center response time. + + <br><dt><var>Q</var><dd>Average number of requests in the system (which is equal to the +traffic intensity \lambda/\mu). + + <br><dt><var>X</var><dd>Throughput (which is always equal to <var>X</var><code> = </code><var>lambda</var>). + + <br><dt><var>p0</var><dd>Steady-state probability that there are no requests in the system + + </dl> + + <p><var>lambda</var> and <var>mu</var> can be vectors of the same size. In this +case, the results will be vectors as well. + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnmm1,qnmmm,qnmmmk. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + +<p class="noindent">G. Bolch, S. Greiner, H. de Meer and K. Trivedi, <cite>Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications</cite>, Wiley, 1998, Section 6.4. + + <p><a name="index-Bolch_002c-G_002e-53"></a><a name="index-Greiner_002c-S_002e-54"></a><a name="index-de-Meer_002c-H_002e-55"></a><a name="index-Trivedi_002c-K_002e-56"></a> +<!-- M/M/1/k --> +<div class="node"> +<a name="The-M%2fM%2f1%2fK-System"></a> +<a name="The-M_002fM_002f1_002fK-System"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a>, +Previous: <a rel="previous" accesskey="p" href="#The-M_002fM_002finf-System">The M/M/inf System</a>, +Up: <a rel="up" accesskey="u" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a> + +</div> + +<h3 class="section">5.4 The M/M/1/K System</h3> + +<p>In a M/M/1/K finite capacity system there can be at most +k jobs at any time. If a new request tries to join the system +when there are already K other requests, the arriving request +is lost. The queue has K-1 slots. The M/M/1/K system is +always stable, regardless of the arrival and service rates +\lambda and \mu. + + <p><a name="doc_002dqnmm1k"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>p0</var>, <var>pK</var>] = <b>qnmm1k</b> (<var>lambda, mu, K</var>)<var><a name="index-qnmm1k-57"></a></var><br> +<blockquote> + <p><a name="index-g_t_0040math_007bM_002fM_002f1_002fK_007d-system-58"></a> +Compute utilization, response time, average number of requests and +throughput for a M/M/1/K finite capacity system. In a +M/M/1/K queue there is a single server; the maximum number of +requests in the system is K, and the maximum queue length is +K-1. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Arrival rate (<var>lambda</var><code>>0</code>). + + <br><dt><var>mu</var><dd>Service rate (<var>mu</var><code>>0</code>). + + <br><dt><var>K</var><dd>Maximum number of requests allowed in the system (<var>K</var><code> ≥ 1</code>). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>Service center utilization, which is defined as <var>U</var><code> = 1-</code><var>p0</var> + + <br><dt><var>R</var><dd>Service center response time + + <br><dt><var>Q</var><dd>Average number of requests in the system + + <br><dt><var>X</var><dd>Service center throughput + + <br><dt><var>p0</var><dd>Steady-state probability that there are no requests in the system + + <br><dt><var>pK</var><dd>Steady-state probability that there are K requests in the system +(i.e., that the system is full) + + </dl> + + <p><var>lambda</var>, <var>mu</var> and <var>K</var> can be vectors of the +same size. In this case, the results will be vectors as well. + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnmm1,qnmminf,qnmmm. + + </blockquote></div> + +<!-- M/M/m/k --> +<div class="node"> +<a name="The-M%2fM%2fm%2fK-System"></a> +<a name="The-M_002fM_002fm_002fK-System"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a>, +Previous: <a rel="previous" accesskey="p" href="#The-M_002fM_002f1_002fK-System">The M/M/1/K System</a>, +Up: <a rel="up" accesskey="u" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a> + +</div> + +<h3 class="section">5.5 The M/M/m/K System</h3> + +<p>The M/M/m/K finite capacity system is similar to the +M/M/1/k system except that the number of servers is m, +where 1 \leq m \leq K. The queue is made of K-m +slots. The M/M/m/K system is always stable. + + <p><a name="doc_002dqnmmmk"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>p0</var>, <var>pK</var>] = <b>qnmmmk</b> (<var>lambda, mu, m, K</var>)<var><a name="index-qnmmmk-59"></a></var><br> +<blockquote> + <p><a name="index-g_t_0040math_007bM_002fM_002fm_002fK_007d-system-60"></a> +Compute utilization, response time, average number of requests and +throughput for a M/M/m/K finite capacity system. In a +M/M/m/K system there are m \geq 1 identical service +centers sharing a fixed-capacity queue. At any time, at most K ≥ m requests can be in the system. The maximum queue length +is K-m. This function generates and +solves the underlying CTMC. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Arrival rate (<var>lambda</var><code>>0</code>). + + <br><dt><var>mu</var><dd>Service rate (<var>mu</var><code>>0</code>). + + <br><dt><var>m</var><dd>Number of servers (<var>m</var><code> ≥ 1</code>). + + <br><dt><var>K</var><dd>Maximum number of requests allowed in the system, +including those inside the service centers +(<var>K</var><code> ≥ </code><var>m</var>). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>Service center utilization + + <br><dt><var>R</var><dd>Service center response time + + <br><dt><var>Q</var><dd>Average number of requests in the system + + <br><dt><var>X</var><dd>Service center throughput + + <br><dt><var>p0</var><dd>Steady-state probability that there are no requests in the system. + + <br><dt><var>pK</var><dd>Steady-state probability that there are <var>K</var> requests in the system +(i.e., probability that the system is full). + + </dl> + + <p><var>lambda</var>, <var>mu</var>, <var>m</var> and <var>K</var> can be either scalars, or +vectors of the same size. In this case, the results will be vectors +as well. + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnmm1,qnmminf,qnmmm. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + +<p class="noindent">G. Bolch, S. Greiner, H. de Meer and K. Trivedi, <cite>Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications</cite>, Wiley, 1998, Section 6.6. + + <p><a name="index-Bolch_002c-G_002e-61"></a><a name="index-Greiner_002c-S_002e-62"></a><a name="index-de-Meer_002c-H_002e-63"></a><a name="index-Trivedi_002c-K_002e-64"></a> + +<!-- Approximate M/M/m --> +<div class="node"> +<a name="The-Asymmetric-M%2fM%2fm-System"></a> +<a name="The-Asymmetric-M_002fM_002fm-System"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#The-M_002fG_002f1-System">The M/G/1 System</a>, +Previous: <a rel="previous" accesskey="p" href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a>, +Up: <a rel="up" accesskey="u" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a> + +</div> + +<h3 class="section">5.6 The Asymmetric M/M/m System</h3> + +<p>The Asymmetric M/M/m system contains m servers connected +to a single queue. Differently from the M/M/m system, in the +asymmetric M/M/m each server may have a different service time. + + <p><a name="doc_002dqnammm"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnammm</b> (<var>lambda, mu</var>)<var><a name="index-qnammm-65"></a></var><br> +<blockquote> + <p><a name="index-Asymmetric-_0040math_007bM_002fM_002fm_007d-system-66"></a> +Compute <em>approximate</em> utilization, response time, average number +of requests in service and throughput for an asymmetric M/M/m +queue. In this system there are m different service centers +connected to a single queue. Each server has its own (possibly different) +service rate. If there is more than one server available, requests +are routed to a randomly-chosen one. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Arrival rate (<var>lambda</var><code>>0</code>). + + <br><dt><var>mu</var><dd><var>mu</var><code>(i)</code> is the service rate of server +i, 1 ≤ i ≤ m. +The system must be ergodic (<var>lambda</var><code> < sum(</code><var>mu</var><code>)</code>). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>Approximate service center utilization, +U = \lambda / ( \sum_i \mu_i ). + + <br><dt><var>R</var><dd>Approximate service center response time + + <br><dt><var>Q</var><dd>Approximate number of requests in the system + + <br><dt><var>X</var><dd>Approximate service center throughput. If the system is ergodic, +we will always have <var>X</var><code> = </code><var>lambda</var> + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnmmm. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + +<p class="noindent">G. Bolch, S. Greiner, H. de Meer and K. Trivedi, <cite>Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications</cite>, Wiley, 1998 + + <p><a name="index-Bolch_002c-G_002e-67"></a><a name="index-Greiner_002c-S_002e-68"></a><a name="index-de-Meer_002c-H_002e-69"></a><a name="index-Trivedi_002c-K_002e-70"></a> +<div class="node"> +<a name="The-M%2fG%2f1-System"></a> +<a name="The-M_002fG_002f1-System"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#The-M_002fHm_002f1-System">The M/Hm/1 System</a>, +Previous: <a rel="previous" accesskey="p" href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a>, +Up: <a rel="up" accesskey="u" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a> + +</div> + +<h3 class="section">5.7 The M/G/1 System</h3> + +<p><a name="doc_002dqnmg1"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>p0</var>] = <b>qnmg1</b> (<var>lambda, xavg, x2nd</var>)<var><a name="index-qnmg1-71"></a></var><br> +<blockquote> + <p><a name="index-g_t_0040math_007bM_002fG_002f1_007d-system-72"></a> +Compute utilization, response time, average number of requests and +throughput for a M/G/1 system. The service time distribution +is described by its mean <var>xavg</var>, and by its second moment +<var>x2nd</var>. The computations are based on results from L. Kleinrock, +<cite>Queuing Systems</cite>, Wiley, Vol 2, and Pollaczek-Khinchine formula. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Arrival rate. + + <br><dt><var>xavg</var><dd>Average service time + + <br><dt><var>x2nd</var><dd>Second moment of service time distribution + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>Service center utilization + + <br><dt><var>R</var><dd>Service center response time + + <br><dt><var>Q</var><dd>Average number of requests in the system + + <br><dt><var>X</var><dd>Service center throughput + + <br><dt><var>p0</var><dd>probability that there is not any request at system + + </dl> + + <p><var>lambda</var>, <var>xavg</var>, <var>t2nd</var> can be vectors of the +same size. In this case, the results will be vectors as well. + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnmh1. + + </blockquote></div> + +<div class="node"> +<a name="The-M%2fHm%2f1-System"></a> +<a name="The-M_002fHm_002f1-System"></a> +<p><hr> +Previous: <a rel="previous" accesskey="p" href="#The-M_002fG_002f1-System">The M/G/1 System</a>, +Up: <a rel="up" accesskey="u" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a> + +</div> + +<h3 class="section">5.8 The M/H_m/1 System</h3> + +<p><a name="doc_002dqnmh1"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>p0</var>] = <b>qnmh1</b> (<var>lambda, mu, alpha</var>)<var><a name="index-qnmh1-73"></a></var><br> +<blockquote> + <p><a name="index-g_t_0040math_007bM_002fH_005fm_002f1_007d-system-74"></a> +Compute utilization, response time, average number of requests and +throughput for a M/H_m/1 system. In this system, the customer +service times have hyper-exponential distribution: + + <pre class="example"> ___ m + \ + B(x) = > alpha(j) * (1-exp(-mu(j)*x)) x>0 + /__ + j=1 +</pre> + <p>where \alpha_j is the probability that the request is served +at phase j, in which case the average service rate is +\mu_j. After completing service at phase j, for +some j, the request exits the system. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Arrival rate. + + <br><dt><var>mu</var><dd><var>mu</var><code>(j)</code> is the phase j service rate. The total +number of phases m is <code>length(</code><var>mu</var><code>)</code>. + + <br><dt><var>alpha</var><dd><var>alpha</var><code>(j)</code> is the probability that a request +is served at phase j. <var>alpha</var> must have the same size +as <var>mu</var>. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>Service center utilization + + <br><dt><var>R</var><dd>Service center response time + + <br><dt><var>Q</var><dd>Average number of requests in the system + + <br><dt><var>X</var><dd>Service center throughput + + </dl> + + <!-- @seealso{qnmhr1} --> + </blockquote></div> + +<!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<!-- *- texinfo -*- --> +<!-- Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla --> +<!-- This file is part of the queueing toolbox, a Queueing Networks --> +<!-- analysis package for GNU Octave. --> +<!-- The queueing toolbox is free software; you can redistribute it --> +<!-- and/or modify it under the terms of the GNU General Public License --> +<!-- as published by the Free Software Foundation; either version 3 of --> +<!-- the License, or (at your option) any later version. --> +<!-- The queueing toolbox is distributed in the hope that it will be --> +<!-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty --> +<!-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with the queueing toolbox; see the file COPYING. If not, see --> +<!-- <http://www.gnu.org/licenses/>. --> +<div class="node"> +<a name="Queueing-Networks"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Contributing-Guidelines">Contributing Guidelines</a>, +Previous: <a rel="previous" accesskey="p" href="#Single-Station-Queueing-Systems">Single Station Queueing Systems</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="chapter">6 Queueing Networks</h2> + +<ul class="menu"> +<li><a accesskey="1" href="#Introduction-to-QNs">Introduction to QNs</a>: A brief introduction to Queueing Networks. +<li><a accesskey="2" href="#Generic-Algorithms">Generic Algorithms</a>: High-level functions for QN analysis +<li><a accesskey="3" href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a>: Functions to analyze product-form QNs +<li><a accesskey="4" href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a>: Functions to analyze non product-form QNs +<li><a accesskey="5" href="#Bounds-on-performance">Bounds on performance</a>: Functions to compute performance bounds +<li><a accesskey="6" href="#Utility-functions">Utility functions</a>: Utility functions to compute miscellaneous quantities +</ul> + +<p><a name="index-queueing-networks-75"></a> +<!-- INTRODUCTION --> +<div class="node"> +<a name="Introduction-to-QNs"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Generic-Algorithms">Generic Algorithms</a>, +Up: <a rel="up" accesskey="u" href="#Queueing-Networks">Queueing Networks</a> + +</div> + +<h3 class="section">6.1 Introduction to QNs</h3> + +<p>Queueing Networks (QN) are a very simple yet powerful modeling tool +which is used to analyze many kind of systems. In its simplest form, a +QN is made of K service centers. Each service center i +has a queue, which is connected to m_i (generally identical) +<em>servers</em>. Customers (or requests) arrive at the service center, +and join the queue if there is a slot available. Then, requests are +served according to a (de)queueing policy. After service completes, +the requests leave the service center. + + <p>The service centers for which m_i = \infty are called +<em>delay centers</em> or <em>infinite servers</em>. If a service center +has infinite servers, of course each new request will find one server +available, so there will never be queueing. + + <p>Requests join the queue according to a <em>queueing policy</em>, such as: + + <dl> +<dt><strong>FCFS</strong><dd>First-Come-First-Served + + <br><dt><strong>LCFS-PR</strong><dd>Last-Come-First-Served, Preemptive Resume + + <br><dt><strong>PS</strong><dd>Processor Sharing + + <br><dt><strong>IS</strong><dd>Infinite Server, there is an infinite number of identical servers so +that each request always finds a server available, and there is no +queueing + + </dl> + + <p>A population of <em>requests</em> or <em>customers</em> arrives to the +system system, requesting service to the service centers. The request +population may be <em>open</em> or <em>closed</em>. In open systems there +is an infinite population of requests. New customers arrive from +outside the system, and eventually leave the system. In closed systems +there is a fixed population of request which continuously interacts +with the system. + + <p>There might be a single class of requests, meaning that all requests +behave in the same way (e.g., they spend the same average time on each +particular server), or there might be multiple classes of requests. + +<h4 class="subsection">6.1.1 Single class models</h4> + +<p>In single class models, all requests are indistinguishable and belong to +the same class. This means that every request has the same average +service time, and all requests move through the system with the same +routing probabilities. + +<p class="noindent"><strong>Model Inputs</strong> + + <dl> +<dt>\lambda_i<dd>External arrival rate to service center i. + + <br><dt>\lambda<dd>Overall external arrival rate to the whole system: \lambda = +\sum_i \lambda_i. + + <br><dt>S_i<dd>Average service time. S_i is the average service time on service +center i. In other words, S_i is the average time from the +instant in which a request is extracted from the queue and starts being +service, and the instant at which service finishes and the request moves +to another queue (or exits the system). + + <br><dt>P_ij<dd>Routing probability matrix. \bf P = P_ij is a K \times +K matrix such that P_ij is the probability that a request +completing service at server i will move directly to server +j, The probability that a request leaves the system after service +at service center i is 1-\sum_j=1^K P_ij. + + <br><dt>V_i<dd>Average number of visits. V_i is the average number of visits to +the service center i. This quantity will be described shortly. + + </dl> + +<p class="noindent"><strong>Model Outputs</strong> + + <dl> +<dt>U_i<dd>Service center utilization. U_i is the utilization of service +center i. The utilization is defined as the fraction of time in +which the resource is busy (i.e., the server is processing requests). + + <br><dt>R_i<dd>Average response time. R_i is the average response time of +service center i. The average response time is defined as the +average time between the arrival of a customer in the queue, and the +completion of service. + + <br><dt>Q_i<dd>Average number of customers. Q_i is the average number of +requests in service center i. This includes both the requests in +the queue, and the request being served. + + <br><dt>X_i<dd>Throughput. X_i is the throughput of service center i. +The throughput is defined as the ratio of job completions (i.e., average +number of jobs completed over a fixed interval of time). + + </dl> + +<p class="noindent">Given these output parameters, additional performance measures can +be computed as follows: + + <dl> +<dt>X<dd>System throughput, X = X_1 / V_1 + + <br><dt>R<dd>System response time, R = \sum_k=1^K R_k V_k + + <br><dt>Q<dd>Average number of requests in the system, Q = N-XZ + + </dl> + + <p>For open, single-class models, the scalar \lambda denotes the +external arrival rate of requests to the system. The average number of +visits satisfy the following equation: + +<pre class="example"> V == P0 + V*P; +</pre> + <p class="noindent">where P_0 j is the probability that an external +arrival goes to service center j. If \lambda_j is the +external arrival rate to service center j, and \lambda = +\sum_j \lambda_j is the overall external arrival rate, then +P_0 j = \lambda_j / \lambda. + + <p>For closed models, the visit ratios satisfy the following equation: + +<pre class="example"> V(1) == 1 && V == V*P; +</pre> + <h4 class="subsection">6.1.2 Multiple class models</h4> + +<p>In multiple class QN models, we assume that there exist C +different classes of requests. Each request from class c spends +on average time S_ck in service at service center k. For +open models, we denote with \bf \lambda = \lambda_ck the +arrival rates, where \lambda_ck is the external arrival rate of +class c customers at service center k. For closed models, +we denote with \bf N = (N_1, N_2, \ldots N_C) the population +vector, where N_c is the number of class c requests in the +system. + + <p>The transition probability matrix for these kind of networks will be a +C \times K \times C \times K matrix \bf P = +P_risj such that P_risj is the probability that a +class r request which completes service at center i will +join server j as a class s request. + + <p>Model input and outputs can be adjusted by adding additional +indexes for the customer classes. + +<p class="noindent"><strong>Model Inputs</strong> + + <dl> +<dt>\lambda_ci<dd>External arrival rate of class-c requests to service center i + + <br><dt>\lambda<dd>Overall external arrival rate to the whole system: \lambda = \sum_c \sum_i \lambda_ci + + <br><dt>S_ci<dd>Average service time. S_ci is the average service time on service +center i for class c requests. + + <br><dt>P_risj<dd>Routing probability matrix. \bf P = P_risj is a C +\times K \times C \times K matrix such that P_risj is the +probability that a class r request which completes service at +server i will move to server j as a class s +request. + + <br><dt>V_ci<dd>Average number of visits. V_ci is the average number of visits +of class c requests to the service center i. + + </dl> + +<p class="noindent"><strong>Model Outputs</strong> + + <dl> +<dt>U_ci<dd>Utilization of service center i by class c requests. The +utilization is defined as the fraction of time in which the resource is +busy (i.e., the server is processing requests). + + <br><dt>R_ci<dd>Average response time experienced by class c requests on service +center i. The average response time is defined as the average +time between the arrival of a customer in the queue, and the completion +of service. + + <br><dt>Q_ci<dd>Average number of class c requests on service center +i. This includes both the requests in the queue, and the request +being served. + + <br><dt>X_ci<dd>Throughput of service center i for class c requests. The +throughput is defined as the rate of completion of class c +requests. + + </dl> + +<p class="noindent">It is possible to define aggregate performance measures as follows: + + <dl> +<dt>U_i<dd>Utilization of service center i: +<code>Ui = sum(U,1);</code> + + <br><dt>R_c<dd>System response time for class c requests: +<code>Rc = sum( V.*R, 1 );</code> + + <br><dt>Q_c<dd>Average number of class c requests in the system: +<code>Qc = sum( Q, 2 );</code> + + <br><dt>X_c<dd>Class c throughput: +<code>Xc = X(:,1) ./ V(:,1);</code> + + </dl> + + <p>We can define the visit ratios V_sj for class s +customers at service center j as follows: + + <p>V_sj = sum_r sum_i V_ri P_risj, for all s,j + +<p class="noindent">while for open networks: + + <p>V_sj = P_0sj + sum_r sum_i V_ri P_risj, for all s,j + +<p class="noindent">where P_0sj is the probability that an external +arrival goes to service center j as a class-s request. +If \lambda_sj is the external arrival rate of class s +requests to service center j, and \lambda = \sum_s \sum_j +\lambda_sj is the overall external arrival rate to the whole system, +then P_0sj = \lambda_sj / \lambda. + +<div class="node"> +<a name="Generic-Algorithms"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a>, +Previous: <a rel="previous" accesskey="p" href="#Introduction-to-QNs">Introduction to QNs</a>, +Up: <a rel="up" accesskey="u" href="#Queueing-Networks">Queueing Networks</a> + +</div> + +<h3 class="section">6.2 Generic Algorithms</h3> + +<p>The <code>queueing</code> package provides a couple of high-level functions +for defining and solving QN models. These functions can be used to +define a open or closed QN model (with single or multiple job +classes), with arbitrary configuration and queueing disciplines. At +the moment only product-form networks can be solved, See <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a>. + + <p>The network is defined by two parameters. The first one is the list of +nodes, encoded as an Octave <em>cell array</em>. The second parameter is +the visit ration <var>V</var>, which can be either a vector (for +single-class models) or a two-dimensional matrix (for multiple-class +models). + + <p>Individual nodes in the network are structures build using the +<code>qnmknode</code> function. + + <p><a name="doc_002dqnmknode"></a> + +<div class="defun"> +— Function File: <var>Q</var> = <b>qnmknode</b> (<var>"m/m/m-fcfs", S</var>)<var><a name="index-qnmknode-76"></a></var><br> +— Function File: <var>Q</var> = <b>qnmknode</b> (<var>"m/m/m-fcfs", S, m</var>)<var><a name="index-qnmknode-77"></a></var><br> +— Function File: <var>Q</var> = <b>qnmknode</b> (<var>"m/m/1-lcfs-pr", S</var>)<var><a name="index-qnmknode-78"></a></var><br> +— Function File: <var>Q</var> = <b>qnmknode</b> (<var>"-/g/1-ps", S</var>)<var><a name="index-qnmknode-79"></a></var><br> +— Function File: <var>Q</var> = <b>qnmknode</b> (<var>"-/g/1-ps", S, s2</var>)<var><a name="index-qnmknode-80"></a></var><br> +— Function File: <var>Q</var> = <b>qnmknode</b> (<var>"-/g/inf", S</var>)<var><a name="index-qnmknode-81"></a></var><br> +— Function File: <var>Q</var> = <b>qnmknode</b> (<var>"-/g/inf", S, s2</var>)<var><a name="index-qnmknode-82"></a></var><br> +<blockquote> + <p>Creates a node; this function can be used together with +<code>qnsolve</code>. It is possible to create either single-class nodes +(where there is only one customer class), or multiple-class nodes +(where the service time is given per-class). Furthermore, it is +possible to specify load-dependent service times. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>S</var><dd>Average service time. S can be either a scalar, a row vector, +a column vector or a two-dimensional matrix. + + <ul> +<li>If S is a scalar, +it is assumed to be a load-independent, class-independent service time. + + <li>If S is a column vector, then <var>S</var><code>(c)</code> is assumed to +the the load-independent service time for class c customers. + + <li>If S is a row vector, then <var>S</var><code>(n)</code> is assumed to be +the class-independent service time at the node, when there are n +requests. + + <li>Finally, if <var>S</var> is a two-dimensional matrix, then +<var>S</var><code>(c,n)</code> is assumed to be the class c service time +when there are n requests at the node. + + </ul> + + <br><dt><var>m</var><dd>Number of identical servers at the node. Default is <var>m</var><code>=1</code>. + + <br><dt><var>s2</var><dd>Squared coefficient of variation for the service time. Default is 1.0. + + </dl> + + <p>The returned struct <var>Q</var> should be considered opaque to the client. + + <!-- The returned struct @var{Q} has the following fields: --> + <!-- @table @var --> + <!-- @item Q.node --> + <!-- (String) type of the node; valid values are @code{"m/m/m-fcfs"}, --> + <!-- @code{"-/g/1-lcfs-pr"}, @code{"-/g/1-ps"} (Processor-Sharing) --> + <!-- and @code{"-/g/inf"} (Infinite Server, or delay center). --> + <!-- @item Q.S --> + <!-- Average service time. If @code{@var{Q}.S} is a vector, then --> + <!-- @code{@var{Q}.S(i)} is the average service time at that node --> + <!-- if there are @math{i} requests. --> + <!-- @item Q.m --> + <!-- Number of identical servers at a @code{"m/m/m-fcfs"}. Default is 1. --> + <!-- @item Q.c --> + <!-- Number of customer classes. Default is 1. --> + <!-- @end table --> + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnsolve. + + </blockquote></div> + + <p>After the network has been defined, it is possible to solve it using +the <code>qnsolve</code> function. Note that this function is somewhat less +efficient than those described in later sections, but +generally easier to use. + + <p><a name="doc_002dqnsolve"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnsolve</b> (<var>"closed", N, QQ, V</var>)<var><a name="index-qnsolve-83"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnsolve</b> (<var>"closed", N, QQ, V, Z</var>)<var><a name="index-qnsolve-84"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnsolve</b> (<var>"open", lambda, QQ, V</var>)<var><a name="index-qnsolve-85"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnsolve</b> (<var>"mixed", lambda, N, QQ, V</var>)<var><a name="index-qnsolve-86"></a></var><br> +<blockquote> + <p>General evaluator of QN models. Networks can be open, +closed or mixed; single as well as multiclass networks are supported. + + <ul> +<li>For <strong>closed</strong> networks, the following server types are +supported: M/M/m–FCFS, -/G/\infty, -/G/1–LCFS-PR, +-/G/1–PS and load-dependent variants. + + <li>For <strong>open</strong> networks, the following server types are supported: +M/M/m–FCFS, -/G/\infty and -/G/1–PS. General +load-dependent nodes are <em>not</em> supported. Multiclass open networks +do not support multiple server M/M/m nodes, but only +single server M/M/1–FCFS. + + <li>For <strong>mixed</strong> networks, the following server types are supported: +M/M/1–FCFS, -/G/\infty and -/G/1–PS. General +load-dependent nodes are <em>not</em> supported. + + </ul> + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>Number of requests in the system for closed networks. For +single-class networks, <var>N</var> must be a scalar. For multiclass +networks, <var>N</var><code>(c)</code> is the population size of closed class +c. + + <br><dt><var>lambda</var><dd>External arrival rate (scalar) for open networks. For single-class +networks, <var>lambda</var> must be a scalar. For multiclass networks, +<var>lambda</var><code>(c)</code> is the class c overall arrival rate. + + <br><dt><var>QQ</var><dd>List of queues in the network. This must be a cell array +with N elements, such that <var>QQ</var><code>{i}</code> is +a struct produced by the <code>qnmknode</code> function. + + <br><dt><var>Z</var><dd>External delay ("think time") for closed networks. Default 0. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>If i is a FCFS node, then <var>U</var><code>(i)</code> is the utilization +of service center i. If i is an IS node, then +<var>U</var><code>(i)</code> is the <em>traffic intensity</em> defined as +<var>X</var><code>(i)*</code><var>S</var><code>(i)</code>. + + <br><dt><var>R</var><dd><var>R</var><code>(i)</code> is the average response time of service center i. + + <br><dt><var>Q</var><dd><var>Q</var><code>(i)</code> is the average number of customers in service center +i. + + <br><dt><var>X</var><dd><var>X</var><code>(i)</code> is the throughput of service center i. + + </dl> + + <p>Note that for multiclass networks, the computed results are per-class +utilization, response time, number of customers and throughput: +<var>U</var><code>(c,k)</code>, <var>R</var><code>(c,k)</code>, <var>Q</var><code>(c,k)</code>, +<var>X</var><code>(c,k)</code>, + + </blockquote></div> + +<p class="noindent"><strong>EXAMPLE</strong> + + <p>Let us consider a closed, multiclass network with C=2 classes +and K=3 service center. Let the population be M=(2, 1) +(class 1 has 2 requests, and class 2 has 1 request). The nodes are as +follows: + + <ul> +<li>Node 1 is a M/M/1–FCFS node, with load-dependent service +times. Service times are class-independent, and are defined by the +matrix <code>[0.2 0.1 0.1; 0.2 0.1 0.1]</code>. Thus, <var>S</var><code>(1,2) = +0.2</code> means that service time for class 1 customers where there are 2 +requests in 0.2. Note that service times are class-independent; + + <li>Node 2 is a -/G/1–PS node, with service times +S_12 = 0.4 for class 1, and S_22 = 0.6 for class 2 +requests; + + <li>Node 3 is a -/G/\infty node (delay center), with service +times S_13=1 and S_23=2 for class 1 and 2 +respectively. + + </ul> + + <p>After defining the per-class visit count <var>V</var> such that +<var>V</var><code>(c,k)</code> is the visit count of class c requests to +service center k. We can define and solve the model as +follows: + +<pre class="example"><pre class="verbatim"> QQ = { qnmknode( "m/m/m-fcfs", [0.2 0.1 0.1; 0.2 0.1 0.1] ), \ + qnmknode( "-/g/1-ps", [0.4; 0.6] ), \ + qnmknode( "-/g/inf", [1; 2] ) }; + V = [ 1 0.6 0.4; \ + 1 0.3 0.7 ]; + N = [ 2 1 ]; + [U R Q X] = qnsolve( "closed", N, QQ, V );</pre></pre> + <div class="node"> +<a name="Algorithms-for-Product-Form-QNs"></a> +<a name="Algorithms-for-Product_002dForm-QNs"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a>, +Previous: <a rel="previous" accesskey="p" href="#Generic-Algorithms">Generic Algorithms</a>, +Up: <a rel="up" accesskey="u" href="#Queueing-Networks">Queueing Networks</a> + +</div> + +<h3 class="section">6.3 Algorithms for Product-Form QNs</h3> + +<p>Product-form queueing networks fulfill the following assumptions: + + <ul> +<li>The network can consist of open and closed job classes. + + <li>The following queueing disciplines are allowed: FCFS, PS, LCFS-PR and IS. + + <li>Service times for FCFS nodes must be exponentially distributed and +class-independent. Service centers at PS, LCFS-PR and IS nodes can +have any kind of service time distribution with a rational Laplace +transform. Furthermore, for PS, LCFS-PR and IS nodes, different +classes of customers can have different service times. + + <li>The service rate of an FCFS node is only allowed to depend on the +number of jobs at this node; in a PS, LCFS-PR and IS node the service +rate for a particular job class can also depend on the number of jobs +of that class at the node. + + <li>In open networks two kinds of arrival processes are allowed: i) the +arrival process is Poisson, with arrival rate \lambda which can +depend on the number of jobs in the network. ii) the arrival process +consists of U independent Poisson arrival streams where the +U job sources are assigned to the U chains; the arrival +rate can be load dependent. + + </ul> + +<!-- Jackson Networks --> +<h4 class="subsection">6.3.1 Jackson Networks</h4> + +<p>Jackson networks satisfy the following conditions: + + <ul> +<li>There is only one job class in the network; the overall number of jobs +in the system is unlimited. + + <li>There are N service centers in the network. Each service center +may have Poisson arrivals from outside the system. A job can leave +the system from any node. + + <li>Arrival rates as well as routing probabilities are independent from +the number of nodes in the network. + + <li>External arrivals and service times at the service centers are +exponentially distributed, and in general can be load-dependent. + + <li>Service discipline at each node is FCFS + + </ul> + + <p>We define the <em>joint probability vector</em> \pi(k_1, k_2, +\ldots k_N) as the steady-state probability that there are k_i +requests at service center i, for all i=1,2, \ldots N. +Jackson networks have the property that the joint probability is the +product of the marginal probabilities \pi_i: + +<pre class="example"> <var>joint_prob</var> = prod( <var>pi</var> ) +</pre> + <p class="noindent">where \pi_i(k_i) is the steady-state probability +that there are k_i requests at service center i. + + <p><a name="doc_002dqnjackson"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnjackson</b> (<var>lambda, S, P </var>)<var><a name="index-qnjackson-87"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnjackson</b> (<var>lambda, S, P, m </var>)<var><a name="index-qnjackson-88"></a></var><br> +— Function File: <var>pr</var> = <b>qnjackson</b> (<var>lambda, S, P, m, k</var>)<var><a name="index-qnjackson-89"></a></var><br> +<blockquote> + <p><a name="index-open-network_002c-single-class-90"></a><a name="index-Jackson-network-91"></a> +With three or four input parameters, this function computes the +steady-state occupancy probabilities for a Jackson network. With five +input parameters, this function computes the steady-state probability +<var>pi</var><code>(j)</code> that there are <var>k</var><code>(j)</code> requests at +service center j. + + <p>This function solves a subset of Jackson networks, with the +following constraints: + + <ul> +<li>External arrival rates are load-independent. + + <li>Service center i consists either of <var>m</var><code>(i) ≥ +1</code> identical servers with individual average service time +<var>S</var><code>(i)</code>, or of an Infinite Server (IS) node. + + </ul> + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd><var>lambda</var><code>(i)</code> is +the external arrival rate to service center i. <var>lambda</var> +must be a vector of length N, <var>lambda</var><code>(i) ≥ 0</code>. + + <br><dt><var>S</var><dd><var>S</var><code>(i)</code> is the average service time on service center i +<var>S</var> must be a vector of length N, <var>S</var><code>(i)>0</code>. + + <br><dt><var>P</var><dd><var>P</var><code>(i,j)</code> is the probability +that a job which completes service at service center i proceeds +to service center j. <var>P</var> must be a matrix of size +N \times N. + + <br><dt><var>m</var><dd><var>m</var><code>(i)</code> is the number of servers at service center +i. If <var>m</var><code>(i) < 1</code>, service center i is an +infinite-server node. Otherwise, it is a regular FCFS queueing center with +<var>m</var><code>(i)</code> servers. If this parameter is omitted, default is +<var>m</var><code>(i) = 1</code> for all i. If this parameter is a scalar, +it will be promoted to a vector with the same size as <var>lambda</var>. +Otherwise, <var>m</var> must be a vector of length N. + + <br><dt><var>k</var><dd>Compute the steady-state probability that there are <var>k</var><code>(i)</code> +requests at service center i. <var>k</var> must have the same length +as <var>lambda</var>, with <var>k</var><code>(i) ≥ 0</code>. + + </dl> + + <p><strong>OUTPUT</strong> + + <dl> +<dt><var>U</var><dd>If i is a FCFS node, then +<var>U</var><code>(i)</code> is the utilization of service center i. +If i is an IS node, then <var>U</var><code>(i)</code> is the +<em>traffic intensity</em> defined as <var>X</var><code>(i)*</code><var>S</var><code>(i)</code>. + + <br><dt><var>R</var><dd><var>R</var><code>(i)</code> is the average response time of service center i. + + <br><dt><var>Q</var><dd><var>Q</var><code>(i)</code> is the average number of customers in service center +i. + + <br><dt><var>X</var><dd><var>X</var><code>(i)</code> is the throughput of service center i. + + <br><dt><var>pr</var><dd><var>pr</var><code>(i)</code> is the steady state probability +that there are <var>k</var><code>(i)</code> requests at service center i. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnopen. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>This implementation is based on G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, <cite>Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications</cite>, Wiley, +1998, pp. 284–287. + + <p><a name="index-Bolch_002c-G_002e-92"></a><a name="index-Greiner_002c-S_002e-93"></a><a name="index-de-Meer_002c-H_002e-94"></a><a name="index-Trivedi_002c-K_002e-95"></a> + +<h4 class="subsection">6.3.2 The Convolution Algorithm</h4> + +<p>According to the BCMP theorem, the state probability of a closed +single class queueing network with K nodes and N requests +can be expressed as: + +<pre class="example"> k = [k1, k2, ... kn]; <span class="roman">population vector</span> + p = 1/G(N+1) \prod F(i,k); +</pre> + <p>Here \pi(k_1, k_2, \ldots k_K) is the joint probability of +having k_i requests at node i, for all i=1,2, +\ldots K. + + <p>The <em>convolution algorithms</em> computes the normalization constants +G = (G(0), G(1), \ldots G(N)) for single-class, closed networks +with N requests. The normalization constants are returned as +vector <var>G</var><code>=[</code><var>G</var><code>(1), </code><var>G</var><code>(2), ... </code><var>G</var><code>(N+1)]</code> where +<var>G</var><code>(i+1)</code> is the value of G(i) (remember that Octave +uses 1-base vectors). The normalization constant can be used to +compute all performance measures of interest (utilization, average +response time and so on). + + <p><code>queueing</code> implements the convolution algorithm, in the function +<code>qnconvolution</code> and <code>qnconvolutionld</code>. The first one +supports single-station nodes, multiple-station nodes and IS nodes. +The second one supports networks with general load-dependent service +centers. + +<!-- The Convolution Algorithm --> + <p><a name="doc_002dqnconvolution"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>G</var>] = <b>qnconvolution</b> (<var>N, S, V</var>)<var><a name="index-qnconvolution-96"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>G</var>] = <b>qnconvolution</b> (<var>N, S, V, m</var>)<var><a name="index-qnconvolution-97"></a></var><br> +<blockquote> + <p><a name="index-closed-network-98"></a><a name="index-normalization-constant-99"></a><a name="index-convolution-algorithm-100"></a> +This function implements the <em>convolution algorithm</em> for +computing steady-state performance measures of product-form, +single-class closed queueing networks. Load-independent service +centers, multiple servers (M/M/m queues) and IS nodes are +supported. For general load-dependent service centers, use the +<code>qnconvolutionld</code> function instead. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>Number of requests in the system (<var>N</var><code>>0</code>). + + <br><dt><var>S</var><dd><var>S</var><code>(k)</code> is the average service time on center k +(<var>S</var><code>(k) ≥ 0</code>). + + <br><dt><var>V</var><dd><var>V</var><code>(k)</code> is the visit count of service center k +(<var>V</var><code>(k) ≥ 0</code>). + + <br><dt><var>m</var><dd><var>m</var><code>(k)</code> is the number of servers at center +k. If <var>m</var><code>(k) < 1</code>, center k is a delay center (IS); +if <var>m</var><code>(k) ≥ 1</code>, center k +it is a regular M/M/m queueing center with <var>m</var><code>(k)</code> +identical servers. Default is <var>m</var><code>(k) = 1</code> for all k. + + </dl> + + <p><strong>OUTPUT</strong> + + <dl> +<dt><var>U</var><dd><var>U</var><code>(k)</code> is the utilization of center k. +For IS nodes, <var>U</var><code>(k)</code> is the <em>traffic intensity</em>. + + <br><dt><var>R</var><dd><var>R</var><code>(k)</code> is the average response time of center k. + + <br><dt><var>Q</var><dd><var>Q</var><code>(k)</code> is the average number of customers at center +k. + + <br><dt><var>X</var><dd><var>X</var><code>(k)</code> is the throughput of center k. + + <br><dt><var>G</var><dd>Vector of normalization constants. <var>G</var><code>(n+1)</code> contains the value of +the normalization constant with n requests +G(n), n=0, <small class="dots">...</small>, N. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnconvolutionld. + + </blockquote></div> + +<p class="noindent"><strong>EXAMPLE</strong> + + <p>The normalization constant G can be used to compute the +steady-state probabilities for a closed single class product-form +Queueing Network with K nodes. Let <var>k</var><code>=[k_1, +k_2, ... k_K]</code> be a valid population vector. Then, the +steady-state probability <var>p</var><code>(i)</code> to have <var>k</var><code>(i)</code> +requests at service center i can be computed as: + +<pre class="example"><pre class="verbatim"> k = [1 2 0]; + K = sum(k); # 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] = qnconvolution( K, S, V, m ); + p = [0 0 0]; # initialize p + # Compute the probability to have k(i) jobs at service center i + for i=1:3 + p(i) = (V(i)*S(i))^k(i) / G(K+1) * \ + (G(K-k(i)+1) - V(i)*S(i)*G(K-k(i)) ); + printf("k(%d)=%d prob=%f\n", i, k(i), p(i) ); + endfor</pre>-| k(1)=1 prob=0.17975 + -| k(2)=2 prob=0.48404 + -| k(3)=0 prob=0.52779 +</pre> + <p class="noindent"><strong>NOTE</strong> + + <p>For a network with K service centers and N requests, +this implementation of the convolution algorithm has time and space +complexity O(NK). + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Jeffrey P. Buzen, <cite>Computational Algorithms for Closed Queueing +Networks with Exponential Servers</cite>, Communications of the ACM, volume +16, number 9, september 1973, +pp. 527–531. <a href="http://doi.acm.org/10.1145/362342.362345">http://doi.acm.org/10.1145/362342.362345</a> + + <p><a name="index-Buzen_002c-J_002e-P_002e-101"></a> +This implementation is based on G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, <cite>Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications</cite>, Wiley, +1998, pp. 313–317. + + <p><a name="index-Bolch_002c-G_002e-102"></a><a name="index-Greiner_002c-S_002e-103"></a><a name="index-de-Meer_002c-H_002e-104"></a><a name="index-Trivedi_002c-K_002e-105"></a> +<!-- Convolution for load-dependent service centers --> +<a name="doc_002dqnconvolutionld"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>G</var>] = <b>qnconvolutionld</b> (<var>N, S, V</var>)<var><a name="index-qnconvolutionld-106"></a></var><br> +<blockquote> + <p><a name="index-closed-network-107"></a><a name="index-normalization-constant-108"></a><a name="index-convolution-algorithm-109"></a><a name="index-load_002ddependent-service-center-110"></a> +This function implements the <em>convolution algorithm</em> for +product-form, single-class closed queueing networks with general +load-dependent service centers. + + <p>This function computes steady-state performance measures for +single-class, closed networks with load-dependent service centers +using the convolution algorithm; the normalization constants are also +computed. The normalization constants are returned as vector +<var>G</var><code>=[</code><var>G</var><code>(1), ..., </code><var>G</var><code>(N+1)]</code> where +<var>G</var><code>(i+1)</code> is the value of G(i). + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>Number of requests in the system (<var>N</var><code>>0</code>). + + <br><dt><var>S</var><dd><var>S</var><code>(k,n)</code> is the mean service time at center k +where there are n requests, 1 ≤ n +≤ N. <var>S</var><code>(k,n)</code> = 1 / \mu_k,n, +where \mu_k,n is the service rate of center k +when there are n requests. + + <br><dt><var>V</var><dd><var>V</var><code>(k)</code> is the visit count of service center k +(<var>V</var><code>(k) ≥ 0</code>). The length of <var>V</var> is the number of +servers K in the network. + + </dl> + + <p><strong>OUTPUT</strong> + + <dl> +<dt><var>U</var><dd><var>U</var><code>(k)</code> is the utilization of center k. + + <br><dt><var>R</var><dd><var>R</var><code>(k)</code> is the average response time at center k. + + <br><dt><var>Q</var><dd><var>Q</var><code>(k)</code> is the average number of customers in center k. + + <br><dt><var>X</var><dd><var>X</var><code>(k)</code> is the throughput of center k. + + <br><dt><var>G</var><dd>Normalization constants (vector). <var>G</var><code>(n+1)</code> +corresponds to G(n), as array indexes in Octave start +from 1. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnconvolution. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Herb Schwetman, <cite>Some Computational Aspects of Queueing Network +Models</cite>, Technical Report CSD-TR-354, Department of Computer Sciences, +Purdue University, feb, 1981 (revised). +<a href="http://www.cs.purdue.edu/research/technical_reports/1980/TR%2080-354.pdf">http://www.cs.purdue.edu/research/technical_reports/1980/TR%2080-354.pdf</a> + + <p><a name="index-Schwetman_002c-H_002e-111"></a> +M. Reiser, H. Kobayashi, <cite>On The Convolution Algorithm for +Separable Queueing Networks</cite>, In Proceedings of the 1976 ACM +SIGMETRICS Conference on Computer Performance Modeling Measurement and +Evaluation (Cambridge, Massachusetts, United States, March 29–31, +1976). SIGMETRICS '76. ACM, New York, NY, +pp. 109–117. <a href="http://doi.acm.org/10.1145/800200.806187">http://doi.acm.org/10.1145/800200.806187</a> + + <p><a name="index-Reiser_002c-M_002e-112"></a><a name="index-Kobayashi_002c-H_002e-113"></a> +This implementation is based on G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, <cite>Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications</cite>, Wiley, +1998, pp. 313–317. Function <code>qnconvolutionld</code> is slightly +different from the version described in Bolch et al. because it +supports general load-dependent centers (while the version in the book +does not). The modification is in the definition of function +<code>F()</code> in <code>qnconvolutionld</code> which has been made similar to +function f_i defined in Schwetman, <code>Some Computational +Aspects of Queueing Network Models</code>. + + <p><a name="index-Bolch_002c-G_002e-114"></a><a name="index-Greiner_002c-S_002e-115"></a><a name="index-de-Meer_002c-H_002e-116"></a><a name="index-Trivedi_002c-K_002e-117"></a> + +<h4 class="subsection">6.3.3 Open networks</h4> + +<!-- Open networks with single class --> +<p><a name="doc_002dqnopensingle"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnopensingle</b> (<var>lambda, S, V</var>)<var><a name="index-qnopensingle-118"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnopensingle</b> (<var>lambda, S, V, m</var>)<var><a name="index-qnopensingle-119"></a></var><br> +<blockquote> + <p><a name="index-open-network_002c-single-class-120"></a><a name="index-BCMP-network-121"></a> +Analyze open, single class BCMP queueing networks. + + <p>This function works for a subset of BCMP single-class open networks +satisfying the following properties: + + <ul> +<li>The allowed service disciplines at network nodes are: FCFS, +PS, LCFS-PR, IS (infinite server); + + <li>Service times are exponentially distributed and +load-independent; + + <li>Service center i can consist of <var>m</var><code>(i) ≥ 1</code> +identical servers. + + <li>Routing is load-independent + + </ul> + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>Overall external arrival rate (<var>lambda</var><code>>0</code>). + + <br><dt><var>S</var><dd><var>S</var><code>(k)</code> is the average service time at center +i (<var>S</var><code>(k)>0</code>). + + <br><dt><var>V</var><dd><var>V</var><code>(k)</code> is the average number of visits to center +k (<var>V</var><code>(k) ≥ 0</code>). + + <br><dt><var>m</var><dd><var>m</var><code>(k)</code> is the number of servers at center i. If +<var>m</var><code>(k) < 1</code>, then service center k is a delay center +(IS); otherwise it is a regular queueing center with +<var>m</var><code>(k)</code> servers. Default is <var>m</var><code>(k) = 1</code> for each +k. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>If k is a queueing center, +<var>U</var><code>(k)</code> is the utilization of center k. +If k is an IS node, then <var>U</var><code>(k)</code> is the +<em>traffic intensity</em> defined as <var>X</var><code>(k)*</code><var>S</var><code>(k)</code>. + + <br><dt><var>R</var><dd><var>R</var><code>(k)</code> is the average response time of center k. + + <br><dt><var>Q</var><dd><var>Q</var><code>(k)</code> is the average number of requests at center +k. + + <br><dt><var>X</var><dd><var>X</var><code>(k)</code> is the throughput of center k. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnopen,qnclosed,qnvisits. + + </blockquote></div> + + <p>From the results computed by this function, it is possible to derive +other quantities of interest as follows: + + <ul> +<li><strong>System Response Time</strong>: The overall system response time +can be computed as +<code>R_s = dot(V,R);</code> + + <li><strong>Average number of requests</strong>: The average number of requests +in the system can be computed as: +<code>Q_s = sum(Q)</code> + + </ul> + +<p class="noindent"><strong>EXAMPLE</strong> + +<pre class="example"><pre class="verbatim"> lambda = 3; + V = [16 7 8]; + S = [0.01 0.02 0.03]; + [U R Q X] = qnopensingle( lambda, S, V ); + R_s = dot(R,V) # System response time + N = sum(Q) # Average number in system</pre>-| R_s = 1.4062 + -| N = 4.2186 +</pre> + <p class="noindent"><strong>REFERENCES</strong> + + <p>G. Bolch, S. Greiner, H. de Meer and K. Trivedi, <cite>Queueing +Networks and Markov Chains: Modeling and Performance Evaluation with +Computer Science Applications</cite>, Wiley, 1998. + + <p><a name="index-Bolch_002c-G_002e-122"></a><a name="index-Greiner_002c-S_002e-123"></a><a name="index-de-Meer_002c-H_002e-124"></a><a name="index-Trivedi_002c-K_002e-125"></a> + +<!-- Open network with multiple classes --> + <p><a name="doc_002dqnopenmulti"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnopenmulti</b> (<var>lambda, S, V</var>)<var><a name="index-qnopenmulti-126"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnopenmulti</b> (<var>lambda, S, V, m</var>)<var><a name="index-qnopenmulti-127"></a></var><br> +<blockquote> + <p><a name="index-open-network_002c-multiple-classes-128"></a> +Exact analysis of open, multiple-class BCMP networks. The network can +be made of <em>single-server</em> queueing centers (FCFS, LCFS-PR or +PS) or delay centers (IS). This function assumes a network with +K service centers and C customer classes. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd><var>lambda</var><code>(c)</code> is the external +arrival rate of class c customers (<var>lambda</var><code>(c)>0</code>). + + <br><dt><var>S</var><dd><var>S</var><code>(c,k)</code> is the mean service time of class c +customers on the service center k (<var>S</var><code>(c,k)>0</code>). +For FCFS nodes, average service times must be class-independent. + + <br><dt><var>V</var><dd><var>V</var><code>(c,k)</code> is the average number of visits of class c +customers to service center k (<var>V</var><code>(c,k) ≥ 0 </code>). + + <br><dt><var>m</var><dd><var>m</var><code>(k)</code> is the number of servers at service center +k. Valid values are <var>m</var><code>(k) < 1</code> to denote a delay +center (-/G/\infty), and <var>m</var><code>(k)==1</code> to denote +a single server queueing center (M/M/1–FCFS, +-/G/1–LCFS-PR or -/G/1–PS). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>If k is a queueing center, then <var>U</var><code>(c,k)</code> is the +class c utilization of center k. If k is +an IS node, then <var>U</var><code>(c,k)</code> is the +class c <em>traffic intensity</em> +defined as <var>X</var><code>(c,k)*</code><var>S</var><code>(c,k)</code>. + + <br><dt><var>R</var><dd><var>R</var><code>(c,k)</code> is the class c response time at +center k. The system response time for +class c requests can be computed +as <code>dot(</code><var>R</var><code>, </code><var>V</var><code>, 2)</code>. + + <br><dt><var>Q</var><dd><var>Q</var><code>(c,k)</code> is the average number of class c requests +at center k. The average number of class c requests +in the system <var>Qc</var> can be computed as <code>Qc = sum(</code><var>Q</var><code>, 2)</code> + + <br><dt><var>X</var><dd><var>X</var><code>(c,k)</code> is the class c throughput +at center k. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnopen,qnopensingle,qnvisits. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. +Sevcik, <cite>Quantitative System Performance: Computer System +Analysis Using Queueing Network Models</cite>, Prentice Hall, +1984. <a href="http://www.cs.washington.edu/homes/lazowska/qsp/">http://www.cs.washington.edu/homes/lazowska/qsp/</a>. In +particular, see section 7.4.1 ("Open Model Solution Techniques"). + + <p><a name="index-Lazowska_002c-E_002e-D_002e-129"></a><a name="index-Zahorjan_002c-J_002e-130"></a><a name="index-Graham_002c-G_002e-S_002e-131"></a><a name="index-Sevcik_002c-K_002e-C_002e-132"></a> + +<h4 class="subsection">6.3.4 Closed Networks</h4> + +<!-- MVA for single class, closed networks --> +<p><a name="doc_002dqnclosedsinglemva"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>G</var>] = <b>qnclosedsinglemva</b> (<var>N, S, V</var>)<var><a name="index-qnclosedsinglemva-133"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>G</var>] = <b>qnclosedsinglemva</b> (<var>N, S, V, m</var>)<var><a name="index-qnclosedsinglemva-134"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>, <var>G</var>] = <b>qnclosedsinglemva</b> (<var>N, S, V, m, Z</var>)<var><a name="index-qnclosedsinglemva-135"></a></var><br> +<blockquote> + <p><a name="index-Mean-Value-Analysys-_0028MVA_0029-136"></a><a name="index-closed-network_002c-single-class-137"></a><a name="index-normalization-constant-138"></a> +Analyze closed, single class queueing networks using the exact Mean +Value Analysis (MVA) algorithm. The following queueing disciplines +are supported: FCFS, LCFS-PR, PS and IS (Infinite Server). This +function supports fixed-rate service centers or multiple server +nodes. For general load-dependent service centers, use the function +<code>qnclosedsinglemvald</code> instead. + + <p>Additionally, the normalization constant G(n), n=0, +<small class="dots">...</small>, N is computed; G(n) can be used in conjunction with +the BCMP theorem to compute steady-state probabilities. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>Population size (number of requests in the system, <var>N</var><code> ≥ 0</code>). +If <var>N</var><code> == 0</code>, this function returns +<var>U</var><code> = </code><var>R</var><code> = </code><var>Q</var><code> = </code><var>X</var><code> = 0</code> + + <br><dt><var>S</var><dd><var>S</var><code>(k)</code> is the mean service time on server k +(<var>S</var><code>(k)>0</code>). + + <br><dt><var>V</var><dd><var>V</var><code>(k)</code> is the average number of visits to service center +k (<var>V</var><code>(k) ≥ 0</code>). + + <br><dt><var>Z</var><dd>External delay for customers (<var>Z</var><code> ≥ 0</code>). Default is 0. + + <br><dt><var>m</var><dd><var>m</var><code>(k)</code> is the number of servers at center k +(if <var>m</var> is a scalar, all centers have that number of servers). If +<var>m</var><code>(k) < 1</code>, center k is a delay center (IS); +otherwise it is a regular queueing center (FCFS, LCFS-PR or PS) with +<var>m</var><code>(k)</code> servers. Default is <var>m</var><code>(k) = 1</code> for all +k (each service center has a single server). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>If k is a FCFS, LCFS-PR or PS node (<var>m</var><code>(k) == 1</code>), +then <var>U</var><code>(k)</code> is the utilization of center k. If +k is an IS node (<var>m</var><code>(k) < 1</code>), then +<var>U</var><code>(k)</code> is the <em>traffic intensity</em> defined as +<var>X</var><code>(k)*</code><var>S</var><code>(k)</code>. + + <br><dt><var>R</var><dd><var>R</var><code>(k)</code> is the response time at center k. +The system response time <var>Rsys</var> +can be computed as <var>Rsys</var><code> = </code><var>N</var><code>/</code><var>Xsys</var><code> - Z</code> + + <br><dt><var>Q</var><dd><var>Q</var><code>(k)</code> is the average number of requests at center +k. The number of requests in the system can be computed +either as <code>sum(</code><var>Q</var><code>)</code>, or using the formula +<var>N</var><code>-</code><var>Xsys</var><code>*</code><var>Z</var>. + + <br><dt><var>X</var><dd><var>X</var><code>(k)</code> is the throughput of center k. The +system throughput <var>Xsys</var> can be computed as +<var>Xsys</var><code> = </code><var>X</var><code>(1) / </code><var>V</var><code>(1)</code> + + <br><dt><var>G</var><dd>Normalization constants. <var>G</var><code>(n+1)</code> corresponds to the value +of the normalization constant G(n), n=0, <small class="dots">...</small>, N as +array indexes in Octave start from 1. G(n) can be used in +conjunction with the BCMP theorem to compute steady-state +probabilities. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedsinglemvald. + + </blockquote></div> + + <p>From the results provided by this function, it is possible to derive +other quantities of interest as follows: + +<p class="noindent"><strong>EXAMPLE</strong> + +<pre class="example"><pre class="verbatim"> S = [ 0.125 0.3 0.2 ]; + V = [ 16 10 5 ]; + N = 20; + m = ones(1,3); + Z = 4; + [U R Q X] = qnclosedsinglemva(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 );</pre></pre> + <p class="noindent"><strong>REFERENCES</strong> + + <p>M. Reiser and S. S. Lavenberg, <cite>Mean-Value Analysis of Closed +Multichain Queuing Networks</cite>, Journal of the ACM, vol. 27, n. 2, April +1980, pp. 313–322. <a href="http://doi.acm.org/10.1145/322186.322195">http://doi.acm.org/10.1145/322186.322195</a> + + <p><a name="index-Reiser_002c-M_002e-139"></a><a name="index-Lavenberg_002c-S_002e-S_002e-140"></a> +This implementation is described in R. Jain , <cite>The Art of Computer +Systems Performance Analysis</cite>, Wiley, 1991, p. 577. Multi-server nodes +<!-- and the computation of @math{G(N)}, --> +are treated according to G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, <cite>Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications</cite>, Wiley, +1998, Section 8.2.1, "Single Class Queueing Networks". + + <p><a name="index-Jain_002c-R_002e-141"></a><a name="index-Bolch_002c-G_002e-142"></a><a name="index-Greiner_002c-S_002e-143"></a><a name="index-de-Meer_002c-H_002e-144"></a><a name="index-Trivedi_002c-K_002e-145"></a> +<!-- MVA for single class, closed networks with load dependent servers --> +<a name="doc_002dqnclosedsinglemvald"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedsinglemvald</b> (<var>N, S, V</var>)<var><a name="index-qnclosedsinglemvald-146"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedsinglemvald</b> (<var>N, S, V, Z</var>)<var><a name="index-qnclosedsinglemvald-147"></a></var><br> +<blockquote> + <p><a name="index-Mean-Value-Analysys-_0028MVA_0029-148"></a><a name="index-closed-network_002c-single-class-149"></a><a name="index-load_002ddependent-service-center-150"></a> +Exact MVA algorithm for closed, single class queueing networks +with load-dependent service centers. This function supports +FCFS, LCFS-PR, PS and IS nodes. For networks with only fixed-rate +service centers and multiple-server nodes, the function +<code>qnclosedsinglemva</code> is more efficient. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>Population size (number of requests in the system, <var>N</var><code> ≥ 0</code>). +If <var>N</var><code> == 0</code>, this function returns <var>U</var><code> = </code><var>R</var><code> = </code><var>Q</var><code> = </code><var>X</var><code> = 0</code> + + <br><dt><var>S</var><dd><var>S</var><code>(k,n)</code> is the mean service time at center k +where there are n requests, 1 ≤ n +≤ N. <var>S</var><code>(k,n)</code> = 1 / \mu_k,n, +where \mu_k,n is the service rate of center k +when there are n requests. + + <br><dt><var>V</var><dd><var>V</var><code>(k)</code> is the average number +of visits to service center k (<var>V</var><code>(k) ≥ 0</code>). + + <br><dt><var>Z</var><dd>external delay ("think time", <var>Z</var><code> ≥ 0</code>); default 0. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd><var>U</var><code>(k)</code> is the utilization of service center k. The +utilization is defined as the probability that service center +k is not empty, that is, U_k = 1-\pi_k(0) where +\pi_k(0) is the steady-state probability that there are 0 +jobs at service center k. + + <br><dt><var>R</var><dd><var>R</var><code>(k)</code> is the response time on service center k. + + <br><dt><var>Q</var><dd><var>Q</var><code>(k)</code> is the average number of requests in service center +k. + + <br><dt><var>X</var><dd><var>X</var><code>(k)</code> is the throughput of service center k. + + </dl> + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>M. Reiser and S. S. Lavenberg, <cite>Mean-Value Analysis of Closed +Multichain Queuing Networks</cite>, Journal of the ACM, vol. 27, n. 2, +April 1980, pp. 313–322. <a href="http://doi.acm.org/10.1145/322186.322195">http://doi.acm.org/10.1145/322186.322195</a> + + <p>This implementation is described in G. Bolch, S. Greiner, H. de Meer +and K. Trivedi, <cite>Queueing Networks and Markov Chains: Modeling +and Performance Evaluation with Computer Science Applications</cite>, Wiley, +1998, Section 8.2.4.1, “Networks with Load-Deèpendent Service: Closed +Networks”. + + <p><a name="index-Bolch_002c-G_002e-151"></a><a name="index-Greiner_002c-S_002e-152"></a><a name="index-de-Meer_002c-H_002e-153"></a><a name="index-Trivedi_002c-K_002e-154"></a> +<!-- CMVA for single class, closed networks with a single load dependent servers --> +<a name="doc_002dqncmva"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qncmva</b> (<var>N, S, Sld, V</var>)<var><a name="index-qncmva-155"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qncmva</b> (<var>N, S, Sld, V, Z</var>)<var><a name="index-qncmva-156"></a></var><br> +<blockquote> + <p><a name="index-Mean-Value-Analysys-_0028MVA_0029-157"></a><a name="index-CMVA-158"></a> +Implementation of the Conditional MVA (CMVA) algorithm, a numerically +stable variant of MVA for load-dependent servers. CMVA is described +in G. Casale, <cite>A Note on Stable Flow-Equivalent Aggregation in +Closed Networks</cite>. The network is made of M service centers and +a delay center. Servers 1, \ldots, M-1 are load-independent; +server M is load-dependent. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>Population size (number of requests in the system, <var>N</var><code> ≥ 0</code>). +If <var>N</var><code> == 0</code>, this function returns +<var>U</var><code> = </code><var>R</var><code> = </code><var>Q</var><code> = </code><var>X</var><code> = 0</code> + + <br><dt><var>S</var><dd><var>S</var><code>(k)</code> is the mean service time on server k = 1, <small class="dots">...</small>, M-1 +(<var>S</var><code>(k) > 0</code>). + + <br><dt><var>Sld</var><dd><var>Sld</var><code>(n)</code> is the mean service time on server M +when there are n requests, n=1, <small class="dots">...</small>, N. +<var>Sld</var><code>(n) = </code> 1 / \mu(n), where \mu(n) is the +service rate at center N when there are n requests. + + <br><dt><var>V</var><dd><var>V</var><code>(k)</code> is the average number of visits to service center +k= 1, <small class="dots">...</small>, M (<var>V</var><code>(k) ≥ 0</code>). + + <br><dt><var>Z</var><dd>External delay for customers (<var>Z</var><code> ≥ 0</code>). Default is 0. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd><var>U</var><code>(k)</code> is the utilization of center k=1, <small class="dots">...</small>, M + + <br><dt><var>R</var><dd><var>R</var><code>(k)</code> is the response time at center k=1, <small class="dots">...</small>, M. +The system response time <var>Rsys</var> +can be computed as <var>Rsys</var><code> = </code><var>N</var><code>/</code><var>Xsys</var><code> - Z</code> + + <br><dt><var>Q</var><dd><var>Q</var><code>(k)</code> is the average number of requests at center +k=1, <small class="dots">...</small>, M. + + <br><dt><var>X</var><dd><var>X</var><code>(k)</code> is the throughput of center k=1, <small class="dots">...</small>, M. + + </dl> + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>G. Casale. <cite>A note on stable flow-equivalent aggregation in +closed networks</cite>. Queueing Syst. Theory Appl., 60:193–202, December +2008. + + <p><a name="index-Casale_002c-G_002e-159"></a> +<!-- Approximate MVA for single class, closed networks --> + + <p><a name="doc_002dqnclosedsinglemvaapprox"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedsinglemvaapprox</b> (<var>N, S, V</var>)<var><a name="index-qnclosedsinglemvaapprox-160"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedsinglemvaapprox</b> (<var>N, S, V, m</var>)<var><a name="index-qnclosedsinglemvaapprox-161"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedsinglemvaapprox</b> (<var>N, S, V, m, Z</var>)<var><a name="index-qnclosedsinglemvaapprox-162"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedsinglemvaapprox</b> (<var>N, S, V, m, Z, tol</var>)<var><a name="index-qnclosedsinglemvaapprox-163"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedsinglemvaapprox</b> (<var>N, S, V, m, Z, tol, iter_max</var>)<var><a name="index-qnclosedsinglemvaapprox-164"></a></var><br> +<blockquote> + <p><a name="index-Mean-Value-Analysys-_0028MVA_0029_002c-approximate-165"></a><a name="index-Approximate-MVA-166"></a><a name="index-Closed-network_002c-single-class-167"></a><a name="index-Closed-network_002c-approximate-analysis-168"></a> +Analyze closed, single class queueing networks using the Approximate +Mean Value Analysis (MVA) algorithm. This function is based on +approximating the number of customers seen at center k when a +new request arrives as Q_k(N) \times (N-1)/N. This function +only handles single-server and delay centers; if your network +contains general load-dependent service centers, use the function +<code>qnclosedsinglemvald</code> instead. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>Population size (number of requests in the system, <var>N</var><code> > 0</code>). + + <br><dt><var>S</var><dd><var>S</var><code>(k)</code> is the mean service time on server k +(<var>S</var><code>(k)>0</code>). + + <br><dt><var>V</var><dd><var>V</var><code>(k)</code> is the average number of visits to service center +k (<var>V</var><code>(k) ≥ 0</code>). + + <br><dt><var>m</var><dd><var>m</var><code>(k)</code> is the number of servers at center k +(if <var>m</var> is a scalar, all centers have that number of servers). If +<var>m</var><code>(k) < 1</code>, center k is a delay center (IS); if +<var>m</var><code>(k) == 1</code>, center k is a regular queueing +center (FCFS, LCFS-PR or PS) with one server (default). This function +does not support multiple server nodes (<var>m</var><code>(k) > 1</code>). + + <br><dt><var>Z</var><dd>External delay for customers (<var>Z</var><code> ≥ 0</code>). Default is 0. + + <br><dt><var>tol</var><dd>Stopping tolerance. The algorithm stops when the maximum relative difference +between the new and old value of the queue lengths <var>Q</var> becomes +less than the tolerance. Default is 10^-5. + + <br><dt><var>iter_max</var><dd>Maximum number of iterations (<var>iter_max</var><code>>0</code>. +The function aborts if convergenge is not reached within the maximum +number of iterations. Default is 100. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>If k is a FCFS, LCFS-PR or PS node (<var>m</var><code>(k) == 1</code>), +then <var>U</var><code>(k)</code> is the utilization of center k. If +k is an IS node (<var>m</var><code>(k) < 1</code>), then +<var>U</var><code>(k)</code> is the <em>traffic intensity</em> defined as +<var>X</var><code>(k)*</code><var>S</var><code>(k)</code>. + + <br><dt><var>R</var><dd><var>R</var><code>(k)</code> is the response time at center k. +The system response time <var>Rsys</var> +can be computed as <var>Rsys</var><code> = </code><var>N</var><code>/</code><var>Xsys</var><code> - Z</code> + + <br><dt><var>Q</var><dd><var>Q</var><code>(k)</code> is the average number of requests at center +k. The number of requests in the system can be computed +either as <code>sum(</code><var>Q</var><code>)</code>, or using the formula +<var>N</var><code>-</code><var>Xsys</var><code>*</code><var>Z</var>. + + <br><dt><var>X</var><dd><var>X</var><code>(k)</code> is the throughput of center k. The +system throughput <var>Xsys</var> can be computed as +<var>Xsys</var><code> = </code><var>X</var><code>(1) / </code><var>V</var><code>(1)</code> + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedsinglemva,qnclosedsinglemvald. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>This implementation is based on Edward D. Lazowska, John Zahorjan, +G. Scott Graham, and Kenneth C. Sevcik, <cite>Quantitative System +Performance: Computer System Analysis Using Queueing Network Models</cite>, +Prentice Hall, +1984. <a href="http://www.cs.washington.edu/homes/lazowska/qsp/">http://www.cs.washington.edu/homes/lazowska/qsp/</a>. In +particular, see section 6.4.2.2 ("Approximate Solution Techniques"). + + <p><a name="index-Lazowska_002c-E_002e-D_002e-169"></a><a name="index-Zahorjan_002c-J_002e-170"></a><a name="index-Graham_002c-G_002e-S_002e-171"></a><a name="index-Sevcik_002c-K_002e-C_002e-172"></a> + +<!-- MVA for multiple class, closed networks --> + <p><a name="doc_002dqnclosedmultimva"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimva</b> (<var>N, S </var>)<var><a name="index-qnclosedmultimva-173"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimva</b> (<var>N, S, V</var>)<var><a name="index-qnclosedmultimva-174"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimva</b> (<var>N, S, V, m</var>)<var><a name="index-qnclosedmultimva-175"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimva</b> (<var>N, S, V, m, Z</var>)<var><a name="index-qnclosedmultimva-176"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimva</b> (<var>N, S, P</var>)<var><a name="index-qnclosedmultimva-177"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimva</b> (<var>N, S, P, m</var>)<var><a name="index-qnclosedmultimva-178"></a></var><br> +<blockquote> + <p><a name="index-Mean-Value-Analysys-_0028MVA_0029-179"></a><a name="index-closed-network_002c-multiple-classes-180"></a> +Analyze closed, multiclass queueing networks with K service +centers and C independent customer classes (chains) using the +Mean Value Analysys (MVA) algorithm. + + <p>Queueing policies at service centers can be any of the following: + + <dl> +<dt><strong>FCFS</strong><dd>(First-Come-First-Served) customers are served in order of arrival; +multiple servers are allowed. For this kind of queueing discipline, +average service times must be class-independent. + + <br><dt><strong>PS</strong><dd>(Processor Sharing) customers are served in parallel by a single +server, each customer receiving an equal share of the service rate. + + <br><dt><strong>LCFS-PR</strong><dd>(Last-Come-First-Served, Preemptive Resume) customers are served in +reverse order of arrival by a single server and the last arrival +preempts the customer in service who will later resume service at the +point of interruption. + + <br><dt><strong>IS</strong><dd>(Infinite Server) customers are delayed independently of other +customers at the service center (there is effectively an infinite +number of servers). + + </dl> + + <blockquote> +<b>Note:</b> If this function is called specifying the visit ratios +<var>V</var>, class switching is <strong>not</strong> allowed. + + <p>If this function is called specifying the routing probability matrix +<var>P</var>, then class switching <strong>is</strong> allowed; however, in this +case all nodes are restricted to be fixed rate service centers or +delay centers: multiple-server and general load-dependent +centers are not supported.</blockquote> + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd><var>N</var><code>(c)</code> is the number of class c requests in the +system; <var>N</var><code>(c) ≥ 0</code>. If class c has +no requests (<var>N</var><code>(c) = 0</code>), then +<var>U</var><code>(c,k) = </code><var>R</var><code>(c,k) = </code><var>Q</var><code>(c,k) = </code><var>X</var><code>(c,k) = 0</code> +for all <var>k</var>. + + <br><dt><var>S</var><dd><var>S</var><code>(c,k)</code> is the mean service time for class c +customers at center k (<var>S</var><code>(c,k) ≥ 0</code>). +If service time at center k is class-dependent, +then center #mathk is assumed to be of type -/G/1–PS +(Processor Sharing). +If center k is a FCFS node (<var>m</var><code>(k)>1</code>), then the +service times <strong>must</strong> be class-independent. + + <br><dt><var>V</var><dd><var>V</var><code>(c,k)</code> is the average number of visits of class c +customers to service center k; <var>V</var><code>(c,k) ≥ 0</code>, +default is 1. +<strong>If you pass this parameter, no class switching is not +allowed</strong> + + <br><dt><var>P</var><dd><var>P</var><code>(r,i,s,j)</code> is the probability that a class r +job completing service at center i is routed to center j +as a class s job. <strong>If you pass this parameter, +class switching is allowed</strong>. + + <br><dt><var>m</var><dd>If <var>m</var><code>(k)<1</code>, then center k is assumed to be a delay +center (IS node -/G/\infty). If <var>m</var><code>(k)==1</code>, then +service center k is a regular queueing center +(M/M/1–FCFS, -/G/1–LCFS-PR or -/G/1–PS). +Finally, if <var>m</var><code>(k)>1</code>, center k is a +M/M/m–FCFS center with <var>m</var><code>(k)</code> identical servers. +Default is <var>m</var><code>(k)=1</code> for each k. + + <br><dt><var>Z</var><dd><var>Z</var><code>(c)</code> is the class c external delay (think time); +<var>Z</var><code>(c) ≥ 0</code>. Default is 0. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>If k is a FCFS, LCFS-PR or PS node, then <var>U</var><code>(c,k)</code> +is the class c utilization at center +k. If k is an IS node, then <var>U</var><code>(c,k)</code> is the +class c <em>traffic intensity</em> at center k, +defined as <var>U</var><code>(c,k) = </code><var>X</var><code>(c,k)*</code><var>S</var><code>(c,k)</code>. + + <br><dt><var>R</var><dd><var>R</var><code>(c,k)</code> is the class c response time at +center k. The total class c system response time +can be computed as <code>dot(</code><var>R</var><code>, </code><var>V</var><code>, 2)</code>. + + <br><dt><var>Q</var><dd><var>Q</var><code>(c,k)</code> is the average number of +class c requests at center k. The total number of +requests at center k is <code>sum(</code><var>Q</var><code>(:,k))</code>. +The total number of class c requests in the system +is <code>sum(</code><var>Q</var><code>(c,:))</code>. + + <br><dt><var>X</var><dd><var>X</var><code>(c,k)</code> is the class c throughput at +center k. The class c system throughput can be computed +as <var>X</var><code>(c,1) / </code><var>V</var><code>(c,1)</code>. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosed, qnclosedmultimvaapprox. + + </blockquote></div> + +<p class="noindent"><strong>NOTE</strong> + + <p>Given a network with K service centers, C job classes and +population vector \bf N=(N_1, N_2, \ldots N_C), the MVA +algorithm requires space O(C \prod_i (N_i + 1)). The time +complexity is O(CK\prod_i (N_i + 1)). This implementation is +slightly more space-efficient (see details in the code). While the space +requirement can be mitigated by using some optimizations, the time +complexity can not. If you need to analyze large closed networks you +should consider the <samp><span class="command">qnclosedmultimvaapprox</span></samp> function, which +implements the approximate MVA algorithm. Note however that +<samp><span class="command">qnclosedmultimvaapprox</span></samp> will only provide approximate results. + +<p class="noindent"><strong>REFERENCES</strong> + + <p>M. Reiser and S. S. Lavenberg, <cite>Mean-Value Analysis of Closed +Multichain Queuing Networks</cite>, Journal of the ACM, vol. 27, n. 2, April +1980, pp. 313–322. <a href="http://doi.acm.org/10.1145/322186.322195">http://doi.acm.org/10.1145/322186.322195</a> + + <p><a name="index-Reiser_002c-M_002e-181"></a><a name="index-Lavenberg_002c-S_002e-S_002e-182"></a> +This implementation is based on G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, <cite>Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications</cite>, Wiley, +1998 and Edward D. Lazowska, John Zahorjan, G. Scott Graham, and +Kenneth C. Sevcik, <cite>Quantitative System Performance: Computer +System Analysis Using Queueing Network Models</cite>, Prentice Hall, +1984. <a href="http://www.cs.washington.edu/homes/lazowska/qsp/">http://www.cs.washington.edu/homes/lazowska/qsp/</a>. In +particular, see section 7.4.2.1 ("Exact Solution Techniques"). + + <p><a name="index-Bolch_002c-G_002e-183"></a><a name="index-Greiner_002c-S_002e-184"></a><a name="index-de-Meer_002c-H_002e-185"></a><a name="index-Trivedi_002c-K_002e-186"></a><a name="index-Lazowska_002c-E_002e-D_002e-187"></a><a name="index-Zahorjan_002c-J_002e-188"></a><a name="index-Graham_002c-G_002e-S_002e-189"></a><a name="index-Sevcik_002c-K_002e-C_002e-190"></a> +<!-- Approximate MVA, with Bard-Schweitzer approximation --> +<a name="doc_002dqnclosedmultimvaapprox"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimvaapprox</b> (<var>N, S, V</var>)<var><a name="index-qnclosedmultimvaapprox-191"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimvaapprox</b> (<var>N, S, V, m</var>)<var><a name="index-qnclosedmultimvaapprox-192"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimvaapprox</b> (<var>N, S, V, m, Z</var>)<var><a name="index-qnclosedmultimvaapprox-193"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimvaapprox</b> (<var>N, S, V, m, Z, tol</var>)<var><a name="index-qnclosedmultimvaapprox-194"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosedmultimvaapprox</b> (<var>N, S, V, m, Z, tol, iter_max</var>)<var><a name="index-qnclosedmultimvaapprox-195"></a></var><br> +<blockquote> + <p><a name="index-Mean-Value-Analysys-_0028MVA_0029_002c-approximate-196"></a><a name="index-Approximate-MVA-197"></a><a name="index-Closed-network_002c-multiple-classes-198"></a><a name="index-Closed-network_002c-approximate-analysis-199"></a> +Analyze closed, multiclass queueing networks with K service +centers and C customer classes using the approximate Mean +Value Analysys (MVA) algorithm. + + <p>This implementation uses Bard and Schweitzer approximation. It is based +on the assumption that +the queue length at service center k with population +set \bf N-\bf 1_c is approximately equal to the queue length +with population set \bf N, times (n-1)/n: + + <pre class="example"> Q_i(N-1c) ~ (n-1)/n Q_i(N) +</pre> + <p>where \bf N is a valid population mix, \bf N-\bf 1_c +is the population mix \bf N with one class c customer +removed, and n = \sum_c N_c is the total number of requests. + + <p>This implementation works for networks made of infinite server (IS) +nodes and single-server nodes only. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd><var>N</var><code>(c)</code> is the number of +class c requests in the system (<var>N</var><code>(c)>0</code>). + + <br><dt><var>S</var><dd><var>S</var><code>(c,k)</code> is the mean service time for class c +customers at center k (<var>S</var><code>(c,k) ≥ 0</code>). + + <br><dt><var>V</var><dd><var>V</var><code>(c,k)</code> is the average number of visits of class c +requests to center k (<var>V</var><code>(c,k) ≥ 0</code>). + + <br><dt><var>m</var><dd><var>m</var><code>(k)</code> is the number of servers at service center +k. If <var>m</var><code>(k) < 1</code>, then the service center k +is assumed to be a delay center (IS). If <var>m</var><code>(k) == 1</code>, +service center k is a regular queueing center (FCFS, LCFS-PR +or PS) with a single server node. If omitted, each service center has +a single server. Note that multiple server nodes are not supported. + + <br><dt><var>Z</var><dd><var>Z</var><code>(c)</code> is the class c external delay. Default +is 0. + + <br><dt><var>tol</var><dd>Stopping tolerance (<var>tol</var><code>>0</code>). The algorithm stops if +the queue length computed on two subsequent iterations are less than +<var>tol</var>. Default is 10^-5. + + <br><dt><var>iter_max</var><dd>Maximum number of iterations (<var>iter_max</var><code>>0</code>. +The function aborts if convergenge is not reached within the maximum +number of iterations. Default is 100. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd>If k is a FCFS, LCFS-PR or PS node, then <var>U</var><code>(c,k)</code> +is the utilization of class c requests on service center +k. If k is an IS node, then <var>U</var><code>(c,k)</code> is the +class c <em>traffic intensity</em> at device k, +defined as <var>U</var><code>(c,k) = </code><var>X</var><code>(c)*</code><var>S</var><code>(c,k)</code> + + <br><dt><var>R</var><dd><var>R</var><code>(c,k)</code> is the response +time of class c requests at service center k. + + <br><dt><var>Q</var><dd><var>Q</var><code>(c,k)</code> is the average number of +class c requests at service center k. + + <br><dt><var>X</var><dd><var>X</var><code>(c,k)</code> is the class c +throughput at service center k. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosed. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Y. Bard, <cite>Some Extensions to Multiclass Queueing Network Analysis</cite>, +proc. 4th Int. Symp. on Modelling and Performance Evaluation of +Computer Systems, feb. 1979, pp. 51–62. + + <p><a name="index-Bard_002c-Y_002e-200"></a> +P. Schweitzer, <cite>Approximate Analysis of Multiclass Closed +Networks of Queues</cite>, Proc. Int. Conf. on Stochastic Control and +Optimization, jun 1979, pp. 25–29. + + <p><a name="index-Schweitzer_002c-P_002e-201"></a> +This implementation is based on Edward D. Lazowska, John Zahorjan, G. +Scott Graham, and Kenneth C. Sevcik, <cite>Quantitative System +Performance: Computer System Analysis Using Queueing Network Models</cite>, +Prentice Hall, +1984. <a href="http://www.cs.washington.edu/homes/lazowska/qsp/">http://www.cs.washington.edu/homes/lazowska/qsp/</a>. In +particular, see section 7.4.2.2 ("Approximate Solution +Techniques"). This implementation is slightly different from the one +described above, as it computes the average response times R +instead of the residence times. + + <p><a name="index-Lazowska_002c-E_002e-D_002e-202"></a><a name="index-Zahorjan_002c-J_002e-203"></a><a name="index-Graham_002c-G_002e-S_002e-204"></a><a name="index-Sevcik_002c-K_002e-C_002e-205"></a> + +<h4 class="subsection">6.3.5 Mixed Networks</h4> + +<!-- MVA for mixed networks --> +<p><a name="doc_002dqnmix"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnmix</b> (<var>lambda, N, S, V, m</var>)<var><a name="index-qnmix-206"></a></var><br> +<blockquote> + <p><a name="index-Mean-Value-Analysys-_0028MVA_0029-207"></a><a name="index-mixed-network-208"></a> +Solution of mixed queueing networks through MVA. The network consists +of K service centers (single-server or delay centers) and +C independent customer chains. Both open and closed chains +are possible. <var>lambda</var> is the vector of per-chain +arrival rates (open classes); <var>N</var> is the vector of populations +for closed chains. + + <blockquote> +<b>Note:</b> In this implementation class switching is <strong>not</strong> allowed. Each +customer class <em>must</em> correspond to an independent chain. +</blockquote> + + <p>If the network is made of open or closed classes only, then this +function calls <code>qnopenmulti</code> or <code>qnclosedmultimva</code> +respectively, and prints a warning message. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dt><var>N</var><dd>For each customer chain c: + + <ul> +<li>if c is a closed chain, then <var>N</var><code>(c)>0</code> is the +number of class c requests and <var>lambda</var><code>(c)</code> must be +zero; + + <li>If c is an open chain, +<var>lambda</var><code>(c)>0</code> is the arrival rate of class c +requests and <var>N</var><code>(c)</code> must be zero; + + </ul> + + <p class="noindent">For each c, the following must hold: + + <pre class="example"> (<var>lambda</var>(c)>0 && <var>N</var>(c)==0) || (<var>lambda</var>(c)==0 && <var>N</var>(c)>0) +</pre> + <p>which means that either <var>lambda</var><code>(c)</code> is nonzero and +<var>N</var><code>(n)</code> is zero, or the other way around. If for some +c, <var>lambda</var>(c) \neq 0 and <var>N</var>(c) \neq 0, an +error is reported and this function aborts. + + <br><dt><var>S</var><dd><var>S</var><code>(c,k)</code> is the mean service time for class c +customers on service center k, <var>S</var><code>(c,k) ≥ 0</code>. +For FCFS nodes, service times must be class-independent. + + <br><dt><var>V</var><dd><var>V</var><code>(c,k)</code> is the average number of visits of class c +customers to service center k (<var>V</var><code>(c,k) ≥ 0</code>). + + <br><dt><var>m</var><dd><var>m</var><code>(k)</code> is the number of servers at service center +k. Only single-server (<var>m</var><code>(k)==1</code>) or IS (Infinite +Server) nodes (<var>m</var><code>(k)<1</code>) are supported. If omitted, each +service center is assumed to have a single server. Queueing discipline +for single-server nodes can be FCFS, PS or LCFS-PR. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd><var>U</var><code>(c,k)</code> is the +utilization of class c requests on service center k. + + <br><dt><var>R</var><dd><var>R</var><code>(c,k)</code> is the response +time of class c requests on service center k. + + <br><dt><var>Q</var><dd><var>Q</var><code>(c,k)</code> is the average number of +class c requests on service center k. + + <br><dt><var>X</var><dd><var>X</var><code>(c,k)</code> is the class c +throughput on service center k. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedmultimva, qnopenmulti. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. +Sevcik, <cite>Quantitative System Performance: Computer System +Analysis Using Queueing Network Models</cite>, Prentice Hall, +1984. <a href="http://www.cs.washington.edu/homes/lazowska/qsp/">http://www.cs.washington.edu/homes/lazowska/qsp/</a>. In +particular, see section 7.4.3 ("Mixed Model Solution Techniques"). +Note that in this function we compute the mean response time R +instead of the mean residence time as in the reference. + + <p><a name="index-Lazowska_002c-E_002e-D_002e-209"></a><a name="index-Zahorjan_002c-J_002e-210"></a><a name="index-Graham_002c-G_002e-S_002e-211"></a><a name="index-Sevcik_002c-K_002e-C_002e-212"></a> +Herb Schwetman, <cite>Implementing the Mean Value Algorithm for the +Solution of Queueing Network Models</cite>, Technical Report CSD-TR-355, +Department of Computer Sciences, Purdue University, feb 15, 1982, +available at +<a href="http://www.cs.purdue.edu/research/technical_reports/1980/TR%2080-355.pdf">http://www.cs.purdue.edu/research/technical_reports/1980/TR%2080-355.pdf</a> + + <p><a name="index-Schwetman_002c-H_002e-213"></a> + +<div class="node"> +<a name="Algorithms-for-non-Product-form-QNs"></a> +<a name="Algorithms-for-non-Product_002dform-QNs"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Bounds-on-performance">Bounds on performance</a>, +Previous: <a rel="previous" accesskey="p" href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a>, +Up: <a rel="up" accesskey="u" href="#Queueing-Networks">Queueing Networks</a> + +</div> + +<h3 class="section">6.4 Algorithms for non Product-Form QNs</h3> + +<!-- MVABLO algorithm for approximate analysis of closed, single class --> +<!-- QN with blocking --> +<p><a name="doc_002dqnmvablo"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnmvablo</b> (<var>N, S, M, P</var>)<var><a name="index-qnmvablo-214"></a></var><br> +<blockquote> + <p><a name="index-queueing-network-with-blocking-215"></a><a name="index-blocking-queueing-network-216"></a><a name="index-closed-network_002c-finite-capacity-217"></a> +MVA algorithm for closed queueing networks with blocking. <samp><span class="command">qnmvablo</span></samp> +computes approximate utilization, response time and mean queue length +for closed, single class queueing networks with blocking. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>population size, i.e., number of requests in the system. <var>N</var> must +be strictly greater than zero, and less than the overall network capacity: +<code>0 < </code><var>N</var><code> < sum(</code><var>M</var><code>)</code>. + + <br><dt><var>S</var><dd>Average service time. <var>S</var><code>(i)</code> is the average service time +requested on server i (<var>S</var><code>(i) > 0</code>). + + <br><dt><var>M</var><dd>Server capacity. <var>M</var><code>(i)</code> is the capacity of service center +i. The capacity is the maximum number of requests in a service +center, including the request currently in service (<var>M</var><code>(i) ≥ 1</code>). + + <br><dt><var>P</var><dd><var>P</var><code>(i,j)</code> is the probability that a request which completes +service at server i will be transferred to server j. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd><var>U</var><code>(i)</code> is the utilization of +service center i. + + <br><dt><var>R</var><dd><var>R</var><code>(i)</code> is the average response time +of service center i. + + <br><dt><var>Q</var><dd><var>Q</var><code>(i)</code> is +the average number of requests in service center i (including +the request in service). + + <br><dt><var>X</var><dd><var>X</var><code>(i)</code> is the throughput of +service center i. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnopen, qnclosed. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Ian F. Akyildiz, <cite>Mean Value Analysis for Blocking Queueing +Networks</cite>, IEEE Transactions on Software Engineering, vol. 14, n. 2, +april 1988, pp. 418–428. <a href="http://dx.doi.org/10.1109/32.4663">http://dx.doi.org/10.1109/32.4663</a> + + <p><a name="index-Akyildiz_002c-I_002e-F_002e-218"></a> +<a name="doc_002dqnmarkov"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnmarkov</b> (<var>lambda, S, C, P</var>)<var><a name="index-qnmarkov-219"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnmarkov</b> (<var>lambda, S, C, P, m</var>)<var><a name="index-qnmarkov-220"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnmarkov</b> (<var>N, S, C, P</var>)<var><a name="index-qnmarkov-221"></a></var><br> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnmarkov</b> (<var>N, S, C, P, m</var>)<var><a name="index-qnmarkov-222"></a></var><br> +<blockquote> + <p><a name="index-closed-network_002c-multiple-classes-223"></a><a name="index-closed-network_002c-finite-capacity-224"></a><a name="index-blocking-queueing-network-225"></a><a name="index-RS-blocking-226"></a> +Compute utilization, response time, average queue length and +throughput for open or closed queueing networks with finite capacity. +Blocking type is Repetitive-Service (RS). This function explicitly +generates and solve the underlying Markov chain, and thus might +require a large amount of memory. + + <p>More specifically, networks which can me analyzed by this +function have the following properties: + + <ul> +<li>There exists only a single class of customers. + + <li>The network has K service centers. Center +i has m_i > 0 servers, and has a total (finite) capacity of +C_i \geq m_i which includes both buffer space and servers. +The buffer space at service center i is therefore +C_i - m_i. + + <li>The network can be open, with external arrival rate to +center i equal to +\lambda_i, or closed with fixed +population size N. For closed networks, the population size +N must be strictly less than the network capacity: N < \sum_i C_i. + + <li>Average service times are load-independent. + + <li>P_ij is the probability that requests completing +execution at center i are transferred to +center j, i \neq j. For open networks, a request may leave the system +from any node i with probability 1-\sum_j P_ij. + + <li>Blocking type is Repetitive-Service (RS). Service +center j is <em>saturated</em> if the number of requests is equal +to its capacity <code>C_j</code>. Under the RS blocking discipline, +a request completing service at center i which is being +transferred to a saturated server j is put back at the end of +the queue of i and will receive service again. Center i +then processes the next request in queue. External arrivals to a +saturated servers are dropped. + + </ul> + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dt><var>N</var><dd>If the first argument is a vector <var>lambda</var>, it is considered to be +the external arrival rate <var>lambda</var><code>(i) ≥ 0</code> to service center +i of an open network. If the first argument is a scalar, it is +considered as the population size <var>N</var> of a closed network; in this case +<var>N</var> must be strictly +less than the network capacity: <var>N</var><code> < sum(</code><var>C</var><code>)</code>. + + <br><dt><var>S</var><dd><var>S</var><code>(i)</code> is the average service time at service center +i + + <br><dt><var>C</var><dd><var>C</var><code>(i)</code> is the Capacity of service center i. The capacity includes both +the buffer and server space <var>m</var><code>(i)</code>. Thus the buffer space is +<var>C</var><code>(i)-</code><var>m</var><code>(i)</code>. + + <br><dt><var>P</var><dd><var>P</var><code>(i,j)</code> is the transition probability from service center +i to service center j. + + <br><dt><var>m</var><dd><var>m</var><code>(i)</code> is the number of servers at service center +i. Note that <var>m</var><code>(i) ≥ </code><var>C</var><code>(i)</code> for each <var>i</var>. +If <var>m</var> is omitted, all service centers are assumed to have a +single server (<var>m</var><code>(i) = 1</code> for all i). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>U</var><dd><var>U</var><code>(i)</code> is the utilization of service center i. + + <br><dt><var>R</var><dd><var>R</var><code>(i)</code> is the response time on service center i. + + <br><dt><var>Q</var><dd><var>Q</var><code>(i)</code> is the average number of customers in the +service center i, <em>including</em> the request in service. + + <br><dt><var>X</var><dd><var>X</var><code>(i)</code> is the throughput of service center i. + + </dl> + + <blockquote> +<b>Note:</b> +The space complexity of this implementation is +O( \prod_i=1^K (C_i + 1)^2). The time complexity is dominated +by the time needed to solve a linear system with +\prod_i=1^K (C_i + 1) +unknowns. + + </blockquote> + + </blockquote></div> + +<div class="node"> +<a name="Bounds-on-performance"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Utility-functions">Utility functions</a>, +Previous: <a rel="previous" accesskey="p" href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a>, +Up: <a rel="up" accesskey="u" href="#Queueing-Networks">Queueing Networks</a> + +</div> + +<h3 class="section">6.5 Bounds on performance</h3> + +<p><a name="doc_002dqnopenab"></a> + +<div class="defun"> +— Function File: [<var>Xu</var>, <var>Rl</var>] = <b>qnopenab</b> (<var>lambda, D</var>)<var><a name="index-qnopenab-227"></a></var><br> +<blockquote> + <p><a name="index-bounds_002c-asymptotic-228"></a><a name="index-open-network-229"></a> +Compute Asymptotic Bounds for single-class, open Queueing Networks +with K service centers. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>overall arrival rate to the system (scalar). Abort if +<var>lambda</var><code> ≤ 0</code> + + <br><dt><var>D</var><dd><var>D</var><code>(k)</code> is the service demand at center k. +The service demand vector <var>D</var> must be nonempty, and all demands +must be nonnegative (<var>D</var><code>(k) ≥ 0</code> for all k). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>Xu</var><dd>Upper bound on the system throughput. + + <br><dt><var>Rl</var><dd>Lower bound on the system response time. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnopenbsb. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth +C. Sevcik, <cite>Quantitative System Performance: Computer System +Analysis Using Queueing Network Models</cite>, Prentice Hall, +1984. <a href="http://www.cs.washington.edu/homes/lazowska/qsp/">http://www.cs.washington.edu/homes/lazowska/qsp/</a>. In +particular, see section 5.2 ("Asymptotic Bounds"). + + <p><a name="index-Lazowska_002c-E_002e-D_002e-230"></a><a name="index-Zahorjan_002c-J_002e-231"></a><a name="index-Graham_002c-G_002e-S_002e-232"></a><a name="index-Sevcik_002c-K_002e-C_002e-233"></a> +<a name="doc_002dqnclosedab"></a> + +<div class="defun"> +— Function File: [<var>Xl</var>, <var>Xu</var>, <var>Rl</var>, <var>Ru</var>] = <b>qnclosedab</b> (<var>N, D</var>)<var><a name="index-qnclosedab-234"></a></var><br> +— Function File: [<var>Xl</var>, <var>Xu</var>, <var>Rl</var>, <var>Ru</var>] = <b>qnclosedab</b> (<var>N, D, Z</var>)<var><a name="index-qnclosedab-235"></a></var><br> +<blockquote> + <p><a name="index-bounds_002c-asymptotic-236"></a><a name="index-closed-network-237"></a> +Compute Asymptotic Bounds for single-class, closed Queueing Networks +with K service centers. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>number of requests in the system (scalar, <var>N</var><code>>0</code>). + + <br><dt><var>D</var><dd><var>D</var><code>(k)</code> is the service demand of service center k, +<var>D</var><code>(k) ≥ 0</code>. + + <br><dt><var>Z</var><dd>external delay (think time, scalar, <var>Z</var><code> ≥ 0</code>). If +omitted, it is assumed to be zero. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>Xl</var><dt><var>Xu</var><dd>Lower and upper bound on the system throughput. + + <br><dt><var>Rl</var><dt><var>Ru</var><dd>Lower and upper bound on the system response time. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedbsb, qnclosedgb, qnclosedpb. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + +<p class="noindent">Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth +C. Sevcik, <cite>Quantitative System Performance: Computer System +Analysis Using Queueing Network Models</cite>, Prentice Hall, +1984. <a href="http://www.cs.washington.edu/homes/lazowska/qsp/">http://www.cs.washington.edu/homes/lazowska/qsp/</a>. In +particular, see section 5.2 ("Asymptotic Bounds"). + + <p><a name="index-Lazowska_002c-E_002e-D_002e-238"></a><a name="index-Zahorjan_002c-J_002e-239"></a><a name="index-Graham_002c-G_002e-S_002e-240"></a><a name="index-Sevcik_002c-K_002e-C_002e-241"></a> + + <p><a name="doc_002dqnopenbsb"></a> + +<div class="defun"> +— Function File: [<var>Xu</var>, <var>Rl</var>, <var>Ru</var>] = <b>qnopenbsb</b> (<var>lambda, D</var>)<var><a name="index-qnopenbsb-242"></a></var><br> +<blockquote> + <p><a name="index-bounds_002c-balanced-system-243"></a><a name="index-open-network-244"></a> +Compute Balanced System Bounds for single-class, open Queueing Networks +with K service centers. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>lambda</var><dd>overall arrival rate to the system (scalar). Abort if +<var>lambda</var><code> < 0 </code> + + <br><dt><var>D</var><dd><var>D</var><code>(k)</code> is the service demand at center k. +The service demand vector <var>D</var> must be nonempty, and all demands +must be nonnegative (<var>D</var><code>(k) ≥ 0</code> for all k). + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>Xl</var><dd>Lower bound on the system throughput. + + <br><dt><var>Rl</var><dt><var>Ru</var><dd>Lower and upper bound on the system response time. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnopenab. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth +C. Sevcik, <cite>Quantitative System Performance: Computer System +Analysis Using Queueing Network Models</cite>, Prentice Hall, +1984. <a href="http://www.cs.washington.edu/homes/lazowska/qsp/">http://www.cs.washington.edu/homes/lazowska/qsp/</a>. In +particular, see section 5.4 ("Balanced Systems Bounds"). + + <p><a name="index-Lazowska_002c-E_002e-D_002e-245"></a><a name="index-Zahorjan_002c-J_002e-246"></a><a name="index-Graham_002c-G_002e-S_002e-247"></a><a name="index-Sevcik_002c-K_002e-C_002e-248"></a> +<a name="doc_002dqnclosedbsb"></a> + +<div class="defun"> +— Function File: [<var>Xl</var>, <var>Xu</var>, <var>Rl</var>, <var>Ru</var>] = <b>qnclosedbsb</b> (<var>N, D</var>)<var><a name="index-qnclosedbsb-249"></a></var><br> +— Function File: [<var>Xl</var>, <var>Xu</var>, <var>Rl</var>, <var>Ru</var>] = <b>qnclosedbsb</b> (<var>N, D, Z</var>)<var><a name="index-qnclosedbsb-250"></a></var><br> +<blockquote> + <p><a name="index-bounds_002c-balanced-system-251"></a><a name="index-closed-network-252"></a> +Compute Balanced System Bounds for single-class, closed Queueing Networks +with K service centers. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>number of requests in the system (scalar). + + <br><dt><var>D</var><dd><var>D</var><code>(k)</code> is the service demand at center k; +<var>K</var><code>(k) ≥ 0</code>. + + <br><dt><var>Z</var><dd>external delay (think time, scalar, <var>Z</var><code> ≥ 0</code>). If +omitted, it is assumed to be zero. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>Xl</var><dt><var>Xu</var><dd>Lower and upper bound on the system throughput. + + <br><dt><var>Rl</var><dt><var>Ru</var><dd>Lower and upper bound on the system response time. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedab, qnclosedgb, qnclosedpb. + + </blockquote></div> + + <p><a name="doc_002dqnclosedpb"></a> + +<div class="defun"> +— Function File: [<var>Xl</var>, <var>Xu</var>] = <b>qnclosedpb</b> (<var>N, D </var>)<var><a name="index-qnclosedpb-253"></a></var><br> +<blockquote> + <p>Compute PB Bounds (C. H. Hsieh and S. Lam, 1987) +for single-class, closed Queueing Networks +with K service centers. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>number of requests in the system (scalar). Must be <var>N</var><code> > 0</code>. + + <br><dt><var>D</var><dd><var>D</var><code>(k)</code> is the service demand of service center k. Must be +<var>D</var><code>(k) ≥ 0</code> for all k. + + <br><dt><var>Z</var><dd>external delay (think time, scalar). If omitted, it is assumed to be zero. +Must be <var>Z</var><code> ≥ 0</code>. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>Xl</var><dt><var>Xu</var><dd>Lower and upper bounds on the system throughput. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedab, qbclosedbsb, qnclosedgb. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>The original paper describing PB Bounds is C. H. Hsieh and S. Lam, +<cite>Two classes of performance bounds for closed queueing networks</cite>, +PEVA, vol. 7, n. 1, pp. 3–30, 1987 + + <p>This function implements the non-iterative variant described in G. +Casale, R. R. Muntz, G. Serazzi, <cite>Geometric Bounds: a +Non-Iterative Analysis Technique for Closed Queueing Networks</cite>, IEEE +Transactions on Computers, 57(6):780-794, June 2008. + + <p><a name="index-Hsieh_002c-C_002e-H-254"></a><a name="index-Lam_002c-S_002e-255"></a><a name="index-Casale_002c-G_002e-256"></a><a name="index-Muntz_002c-R_002e-R_002e-257"></a><a name="index-Serazzi_002c-G_002e-258"></a> +<a name="doc_002dqnclosedgb"></a> + +<div class="defun"> +— Function File: [<var>Xl</var>, <var>Xu</var>, <var>Ql</var>, <var>Qu</var>] = <b>qnclosedgb</b> (<var>N, D, Z</var>)<var><a name="index-qnclosedgb-259"></a></var><br> +<blockquote> + <p><a name="index-bounds_002c-geometric-260"></a><a name="index-closed-network-261"></a> +Compute Geometric Bounds (GB) for single-class, closed Queueing Networks. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>number of requests in the system (scalar, <var>N</var><code> > 0</code>). + + <br><dt><var>D</var><dd><var>D</var><code>(k)</code> is the service demand of service center k +(<var>D</var><code>(k) ≥ 0</code>). + + <br><dt><var>Z</var><dd>external delay (think time, scalar). If omitted, it is assumed to be zero. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>Xl</var><dt><var>Xu</var><dd>Lower and upper bound on the system throughput. If <var>Z</var><code>>0</code>, +these bounds are computed using <em>Geometric Square-root Bounds</em> +(GSB). If <var>Z</var><code>==0</code>, these bounds are computed using <em>Geometric Bounds</em> (GB) + + <br><dt><var>Ql</var><dt><var>Qu</var><dd><var>Ql</var><code>(i)</code> and <var>Qu</var><code>(i)</code> are the lower and upper +bounds respectively of the queue length for service center i. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedab. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>G. Casale, R. R. Muntz, G. Serazzi, +<cite>Geometric Bounds: a Non-Iterative Analysis Technique for Closed +Queueing Networks</cite>, IEEE Transactions on Computers, 57(6):780-794, +June 2008. <a href="http://doi.ieeecomputersociety.org/10.1109/TC.2008.37">http://doi.ieeecomputersociety.org/10.1109/TC.2008.37</a> + + <p><a name="index-Casale_002c-G_002e-262"></a><a name="index-Muntz_002c-R_002e-R_002e-263"></a><a name="index-Serazzi_002c-G_002e-264"></a> +In this implementation we set X^+ and X^- as the upper +and lower Asymptotic Bounds as computed by the <code>qnclosedab</code> +function, respectively. + +<div class="node"> +<a name="Utility-functions"></a> +<p><hr> +Previous: <a rel="previous" accesskey="p" href="#Bounds-on-performance">Bounds on performance</a>, +Up: <a rel="up" accesskey="u" href="#Queueing-Networks">Queueing Networks</a> + +</div> + +<h3 class="section">6.6 Utility functions</h3> + +<h4 class="subsection">6.6.1 Open or closed networks</h4> + +<p><a name="doc_002dqnclosed"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnclosed</b> (<var>N, S, V, <small class="dots">...</small></var>)<var><a name="index-qnclosed-265"></a></var><br> +<blockquote> + <p><a name="index-closed-network-266"></a> +This function computes steady-state performance measures of closed +queueing networks using the Mean Value Analysis (MVA) algorithm. The +qneneing network is allowed to contain fixed-capacity centers, delay +centers or general load-dependent centers. Multiple request +classes are supported. + + <p>This function dispatches the computation to one of +<code>qnclosedsinglemva</code>, <code>qnclosedsinglemvald</code> or +<code>qnclosedmultimva</code>. + + <ul> +<li>If <var>N</var> is a scalar, the network is assumed to have a single +class of requests; in this case, the exact MVA algorithm is used to +analyze the network. If <var>S</var> is a vector, then <var>S</var><code>(k)</code> +is the average service time of center k, and this function +calls <code>qnclosedsinglemva</code> which supports load-independent +service centers. If <var>S</var> is a matrix, <var>S</var><code>(k,i)</code> is the +average service time at service center k when i ≥ +1 jobs are present; in this case, the network is analyzed with the +<code>qnclosedsinglemvald</code> function. + + <li>If <var>N</var> is a vector, the network is assumed to have multiple +classes of requests, and is analyzed using the exact multiclass +MVA algorithm as implemented in the <code>qnclosedmultimva</code> function. + + </ul> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedsinglemva, qnclosedsinglemvald, qnclosedmultimva. + + </blockquote></div> + +<p class="noindent"><strong>EXAMPLE</strong> + +<pre class="example"><pre class="verbatim"> P = [0 0.3 0.7; 1 0 0; 1 0 0]; # Transition probability matrix + S = [1 0.6 0.2]; # Average service times + m = ones(1,3); # All centers are single-server + Z = 2; # External delay + N = 15; # Maximum population to consider + + V = qnvisits(P); # Compute number of visits from P + D = V .* S; # Compute service demand from S and V + X_bsb_lower = X_bsb_upper = zeros(1,N); + X_ab_lower = X_ab_upper = zeros(1,N); + X_mva = zeros(1,N); + for n=1:N + [X_bsb_lower(n) X_bsb_upper(n)] = qnclosedbsb(n, D, Z); + [X_ab_lower(n) X_ab_upper(n)] = qnclosedab(n, D, Z); + [U R Q X] = qnclosed( n, S, V, m, Z ); + X_mva(n) = X(1)/V(1); + endfor + close all; + plot(1:N, X_ab_lower,"g;Asymptotic Bounds;", \ + 1:N, X_bsb_lower,"k;Balanced System Bounds;", \ + 1:N, X_mva,"b;MVA;", "linewidth", 2, \ + 1:N, X_bsb_upper,"k", \ + 1:N, X_ab_upper,"g" ); + axis([1,N,0,1]); + xlabel("Number of Requests n"); + ylabel("System Throughput X(n)"); + legend("location","southeast");</pre></pre> + <p><a name="doc_002dqnopen"></a> + +<div class="defun"> +— Function File: [<var>U</var>, <var>R</var>, <var>Q</var>, <var>X</var>] = <b>qnopen</b> (<var>lambda, S, V, <small class="dots">...</small></var>)<var><a name="index-qnopen-267"></a></var><br> +<blockquote> + <p><a name="index-open-network-268"></a> +Compute utilization, response time, average number of requests in the +system, and throughput for open queueing networks. If <var>lambda</var> is +a scalar, the network is considered a single-class QN and is solved +using <code>qnopensingle</code>. If <var>lambda</var> is a vector, the network +is considered as a multiclass QN and solved using <code>qnopenmulti</code>. + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnopensingle, qnopenmulti. + + </blockquote></div> + +<!-- Compute the visit counts --> +<h4 class="subsection">6.6.2 Computation of the visit counts</h4> + +<p>For single-class networks the average number of visits satisfy the +following equation: + +<pre class="example"> V == P0 + V*P; +</pre> + <p class="noindent">where P_0 j is the probability that an external +arrival goes to service center j. If \lambda_j is the +external arrival rate to service center j, and \lambda = +\sum_j \lambda_j is the overall external arrival rate, then +P_0 j = \lambda_j / \lambda. + + <p>For closed networks, the visit ratios satisfy the following equation: + +<pre class="example"> V(1) == 1 && V == V*P; +</pre> + <p>The definitions above can be extended to multiple class networks as +follows. We define the visit ratios V_sj for class s +customers at service center j as follows: + + <p>V_sj = sum_r sum_i V_ri P_risj, for all s,j +V_s1 = 1, for all s + +<p class="noindent">while for open networks: + + <p>V_sj = P_0sj + sum_r sum_i V_ri P_risj, for all s,j + +<p class="noindent">where P_0sj is the probability that an external +arrival goes to service center j as a class-s request. +If \lambda_sj is the external arrival rate of class s +requests to service center j, and \lambda = \sum_s \sum_j +\lambda_sj is the overall external arrival rate to the whole system, +then P_0sj = \lambda_sj / \lambda. + + <p><a name="doc_002dqnvisits"></a> + +<div class="defun"> +— Function File: [<var>V</var> <var>ch</var>] = <b>qnvisits</b> (<var>P</var>)<var><a name="index-qnvisits-269"></a></var><br> +— Function File: <var>V</var> = <b>qnvisits</b> (<var>P, lambda</var>)<var><a name="index-qnvisits-270"></a></var><br> +<blockquote> + <p>Compute the average number of visits to the service centers of a +single class, open or closed Queueing Network with N service +centers. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>P</var><dd>Routing probability matrix. For single class networks, +<var>P</var><code>(i,j)</code> is the probability that a request which completed +service at center i is routed to center j. For closed +networks it must hold that <code>sum(</code><var>P</var><code>,2)==1</code>. The routing +graph myst be strongly connected, meaning that it must be possible to +eventually reach each node starting from each node. For multiple +class networks, <var>P</var><code>(r,i,s,j)</code> is the probability that a +class r request which completed service at center i is +routed to center j as a class s request. Class switching +is supported. + + <br><dt><var>lambda</var><dd>(open networks only) vector of external arrivals. For single class +networks, <var>lambda</var><code>(i)</code> is the external arrival rate to +center i. For multiple class networks, +<var>lambda</var><code>(r,i)</code> is the arrival rate of class r +requests to center i. If this parameter is omitted, the +network is assumed to be closed. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>V</var><dd>For single class networks, <var>V</var><code>(i)</code> is the average number of +visits to server i. For multiple class networks, +<var>V</var><code>(r,i)</code> is the class r visit ratio at center +i. + + <br><dt><var>ch</var><dd>(For closed networks only). <var>ch</var><code>(c,k)</code> is the +number of the chain that class c at center k belongs to. +The total number of chains is <code>max(</code><var>ch</var><code>)</code>. + + </dl> + + </blockquote></div> + +<p class="noindent"><strong>EXAMPLE</strong> + +<pre class="example"><pre class="verbatim"> P = [ 0 0.4 0.6 0; \ + 0.2 0 0.2 0.6; \ + 0 0 0 1; \ + 0 0 0 0 ]; + lambda = [0.1 0 0 0.3]; + V = qnvisits(P,lambda); + S = [2 1 2 1.8]; + m = [3 1 1 2]; + [U R Q X] = qnopensingle( sum(lambda), S, V, m );</pre></pre> + <h4 class="subsection">6.6.3 Other utility functions</h4> + +<p><a name="doc_002dpopulation_005fmix"></a> + +<div class="defun"> +— Function File: pop_mix = <b>population_mix</b> (<var>k, N</var>)<var><a name="index-population_005fmix-271"></a></var><br> +<blockquote> + <p><a name="index-population-mix-272"></a><a name="index-closed-network_002c-multiple-classes-273"></a> +Return the set of valid population mixes with exactly <var>k</var> +customers, for a closed multiclass Queueing Network with population +vector <var>N</var>. More specifically, given a multiclass Queueing +Network with C customer classes, such that there are +<var>N</var><code>(i)</code> requests of class i, a +k-mix <var>mix</var> is a C-dimensional vector with the +following properties: + + <pre class="example"> all( mix >= 0 ); + all( mix <= N ); + sum( mix ) == k; +</pre> + <p class="noindent">This function enumerates all valid k-mixes, such that +<var>pop_mix</var><code>(i)</code> is a C dimensional row vector representing +a valid population mix, for all i. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>k</var><dd>Total population size of the requested mix. <var>k</var> must be a nonnegative integer + + <br><dt><var>N</var><dd><var>N</var><code>(i)</code> is the number of class i requests. +The condition <var>k</var><code> ≤ sum(</code><var>N</var><code>)</code> must hold. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>pop_mix</var><dd><var>pop_mix</var><code>(i,j)</code> is the number of class j requests +in the i-th population mix. The number of +population mixes is <code>rows( </code><var>pop_mix</var><code> ) </code>. + + </dl> + + <p>Note that if you are interested in the number of k-mixes +and you don't care to enumerate them, you can use the funcion +<code>qnmvapop</code>. + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnmvapop. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Herb Schwetman, <cite>Implementing the Mean Value Algorithm for the +Solution of Queueing Network Models</cite>, Technical Report CSD-TR-355, +Department of Computer Sciences, Purdue University, feb 15, 1982, +available at +<a href="http://www.cs.purdue.edu/research/technical_reports/1980/TR 80-355.pdf">http://www.cs.purdue.edu/research/technical_reports/1980/TR 80-355.pdf</a> + + <p>Note that the slightly different problem of generating all tuples +k_1, k_2, \ldots k_N such that \sum_i k_i = k and +k_i are nonnegative integers, for some fixed integer k +≥ 0 has been described in S. Santini, <cite>Computing the +Indices for a Complex Summation</cite>, unpublished report, available at +<a href="http://arantxa.ii.uam.es/~ssantini/writing/notes/s668_summation.pdf">http://arantxa.ii.uam.es/~ssantini/writing/notes/s668_summation.pdf</a> + + <p><a name="index-Schwetman_002c-H_002e-274"></a><a name="index-Santini_002c-S_002e-275"></a> +<a name="doc_002dqnmvapop"></a> + +<div class="defun"> +— Function File: <var>H</var> = <b>qnmvapop</b> (<var>N</var>)<var><a name="index-qnmvapop-276"></a></var><br> +<blockquote> + <p><a name="index-population-mix-277"></a><a name="index-closed-network_002c-multiple-classes-278"></a> +Given a network with C customer classes, this function +computes the number of valid population mixes <var>H</var><code>(r,n)</code> that can +be constructed by the multiclass MVA algorithm by allocating n +customers to the first r classes. + + <p><strong>INPUTS</strong> + + <dl> +<dt><var>N</var><dd>Population vector. <var>N</var><code>(c)</code> is the number of class-c +requests in the system. The total number of requests in the network +is <code>sum(</code><var>N</var><code>)</code>. + + </dl> + + <p><strong>OUTPUTS</strong> + + <dl> +<dt><var>H</var><dd><var>H</var><code>(r,n)</code> is the number of valid populations that can be +constructed allocating n customers to the first r classes. + + </dl> + + <pre class="sp"> + + </pre> + <strong>See also:</strong> qnclosedmultimva,population_mix. + + </blockquote></div> + +<p class="noindent"><strong>REFERENCES</strong> + + <p>Zahorjan, J. and Wong, E. <cite>The solution of separable queueing +network models using mean value analysis</cite>. SIGMETRICS +Perform. Eval. Rev. 10, 3 (Sep. 1981), 80-85. DOI +<a href="http://doi.acm.org/10.1145/1010629.805477">http://doi.acm.org/10.1145/1010629.805477</a> + + <p><a name="index-Zahorjan_002c-J_002e-279"></a><a name="index-Wong_002c-E_002e-280"></a> + +<!-- Appendix starts here --> +<!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<!-- *- texinfo -*- --> +<!-- Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla --> +<!-- This file is part of the queueing toolbox, a Queueing Networks --> +<!-- analysis package for GNU Octave. --> +<!-- The queueing toolbox is free software; you can redistribute it --> +<!-- and/or modify it under the terms of the GNU General Public License --> +<!-- as published by the Free Software Foundation; either version 3 of --> +<!-- the License, or (at your option) any later version. --> +<!-- The queueing toolbox is distributed in the hope that it will be --> +<!-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty --> +<!-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with the queueing toolbox; see the file COPYING. If not, see --> +<!-- <http://www.gnu.org/licenses/>. --> +<div class="node"> +<a name="Contributing-Guidelines"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Acknowledgements">Acknowledgements</a>, +Previous: <a rel="previous" accesskey="p" href="#Queueing-Networks">Queueing Networks</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="appendix">Appendix A Contributing Guidelines</h2> + +<p>Contributions and bug reports are <em>always</em> welcome. If you want +to contribute to the <code>queueing</code> package, here are some +guidelines: + + <ul> +<li>If you are contributing a new function, please embed proper +documentation within the function itself. The documentation must be in +<code>texinfo</code> format, so that it will be extracted and formatted into +the printable manual. See the existing functions of the +<code>queueing</code> package for the documentation style. + + <li>The documentation should be as precise as possible. In particular, +always state what the valid ranges of the parameters are. + + <li>If you are contributing a new function, ensure that the function +properly checks the validity of its input parameters. For example, +each function accepting vectors should check whether the dimensions +match. + + <li>Always provide bibliographic references for each algorithm you +contribute. If your implementation differs in some way from the +reference you give, please describe how and why your implementation +differs. + + <li>Include Octave test and demo blocks with your code. +Test blocks are particularly important, because Queueing Network +algorithms tend to be quite complex to implement correctly, and we +must ensure that the implementations provided with the +<code>queueing</code> package are (mostly) correct. + + </ul> + + <p>Send your contribution to Moreno Marzolla +(<a href="mailto:marzolla@cs.unibo.it">marzolla@cs.unibo.it</a>). Even if you are just a user of +<code>queueing</code>, and find this package useful, let me know by +dropping me a line. Thanks. + +<!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<!-- *- texinfo -*- --> +<!-- Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla --> +<!-- This file is part of the queueing toolbox, a Queueing Networks --> +<!-- analysis package for GNU Octave. --> +<!-- The queueing toolbox is free software; you can redistribute it --> +<!-- and/or modify it under the terms of the GNU General Public License --> +<!-- as published by the Free Software Foundation; either version 3 of --> +<!-- the License, or (at your option) any later version. --> +<!-- The queueing toolbox is distributed in the hope that it will be --> +<!-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty --> +<!-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --> +<!-- GNU General Public License for more details. --> +<!-- You should have received a copy of the GNU General Public License --> +<!-- along with the queueing toolbox; see the file COPYING. If not, see --> +<!-- <http://www.gnu.org/licenses/>. --> +<div class="node"> +<a name="Acknowledgements"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Copying">Copying</a>, +Previous: <a rel="previous" accesskey="p" href="#Contributing-Guidelines">Contributing Guidelines</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="appendix">Appendix B Acknowledgements</h2> + +<p>The following people (listed in alphabetical order) contributed to the +<code>queueing</code> package, either by providing feedback, reporting bugs +or contributing code: Philip Carinhas, Phil Colbourn, Yves Durand, +Marco Guazzone, Dmitry Kolesnikov. + +<!-- DO NOT EDIT! Generated automatically by munge-texi. --> +<div class="node"> +<a name="Copying"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Concept-Index">Concept Index</a>, +Previous: <a rel="previous" accesskey="p" href="#Acknowledgements">Acknowledgements</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="appendix">Appendix C GNU GENERAL PUBLIC LICENSE</h2> + +<p><a name="index-warranty-281"></a><a name="index-copyright-282"></a> +<div align="center">Version 3, 29 June 2007</div> + +<pre class="display"> Copyright © 2007 Free Software Foundation, Inc. <a href="http://fsf.org/">http://fsf.org/</a> + + Everyone is permitted to copy and distribute verbatim copies of this + license document, but changing it is not allowed. +</pre> +<h3 class="heading">Preamble</h3> + +<p>The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + <p>The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom +to share and change all versions of a program—to make sure it remains +free software for all its users. We, the Free Software Foundation, +use the GNU General Public License for most of our software; it +applies also to any other work released this way by its authors. You +can apply it to your programs, too. + + <p>When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + <p>To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you +have certain responsibilities if you distribute copies of the +software, or if you modify it: responsibilities to respect the freedom +of others. + + <p>For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, +receive or can get the source code. And you must show them these +terms so they know their rights. + + <p>Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + <p>For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + <p>Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the +manufacturer can do so. This is fundamentally incompatible with the +aim of protecting users' freedom to change the software. The +systematic pattern of such abuse occurs in the area of products for +individuals to use, which is precisely where it is most unacceptable. +Therefore, we have designed this version of the GPL to prohibit the +practice for those products. If such problems arise substantially in +other domains, we stand ready to extend this provision to those +domains in future versions of the GPL, as needed to protect the +freedom of users. + + <p>Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish +to avoid the special danger that patents applied to a free program +could make it effectively proprietary. To prevent this, the GPL +assures that patents cannot be used to render the program non-free. + + <p>The precise terms and conditions for copying, distribution and +modification follow. + +<h3 class="heading">TERMS AND CONDITIONS</h3> + + <ol type=1 start=0> +<li>Definitions. + + <p>“This License” refers to version 3 of the GNU General Public License. + + <p>“Copyright” also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + + <p>“The Program” refers to any copyrightable work licensed under this +License. Each licensee is addressed as “you”. “Licensees” and +“recipients” may be individuals or organizations. + + <p>To “modify” a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a “modified version” of +the earlier work or a work “based on” the earlier work. + + <p>A “covered work” means either the unmodified Program or a work based +on the Program. + + <p>To “propagate” a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + <p>To “convey” a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + + <p>An interactive user interface displays “Appropriate Legal Notices” to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + <li>Source Code. + + <p>The “source code” for a work means the preferred form of the work for +making modifications to it. “Object code” means any non-source form +of a work. + + <p>A “Standard Interface” means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + <p>The “System Libraries” of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +“Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + <p>The “Corresponding Source” for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + <p>The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + + <p>The Corresponding Source for a work in source code form is that same +work. + + <li>Basic Permissions. + + <p>All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + <p>You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + + <p>Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + <li>Protecting Users' Legal Rights From Anti-Circumvention Law. + + <p>No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + <p>When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + + <li>Conveying Verbatim Copies. + + <p>You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + <p>You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + <li>Conveying Modified Source Versions. + + <p>You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + + <ol type=a start=1> +<li>The work must carry prominent notices stating that you modified it, +and giving a relevant date. + + <li>The work must carry prominent notices stating that it is released +under this License and any conditions added under section 7. This +requirement modifies the requirement in section 4 to “keep intact all +notices”. + + <li>You must license the entire work, as a whole, under this License to +anyone who comes into possession of a copy. This License will +therefore apply, along with any applicable section 7 additional terms, +to the whole of the work, and all its parts, regardless of how they +are packaged. This License gives no permission to license the work in +any other way, but it does not invalidate such permission if you have +separately received it. + + <li>If the work has interactive user interfaces, each must display +Appropriate Legal Notices; however, if the Program has interactive +interfaces that do not display Appropriate Legal Notices, your work +need not make them do so. + </ol> + + <p>A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +“aggregate” if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + <li>Conveying Non-Source Forms. + + <p>You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + + <ol type=a start=1> +<li>Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by the +Corresponding Source fixed on a durable physical medium customarily +used for software interchange. + + <li>Convey the object code in, or embodied in, a physical product +(including a physical distribution medium), accompanied by a written +offer, valid for at least three years and valid for as long as you +offer spare parts or customer support for that product model, to give +anyone who possesses the object code either (1) a copy of the +Corresponding Source for all the software in the product that is +covered by this License, on a durable physical medium customarily used +for software interchange, for a price no more than your reasonable +cost of physically performing this conveying of source, or (2) access +to copy the Corresponding Source from a network server at no charge. + + <li>Convey individual copies of the object code with a copy of the written +offer to provide the Corresponding Source. This alternative is +allowed only occasionally and noncommercially, and only if you +received the object code with such an offer, in accord with subsection +6b. + + <li>Convey the object code by offering access from a designated place +(gratis or for a charge), and offer equivalent access to the +Corresponding Source in the same way through the same place at no +further charge. You need not require recipients to copy the +Corresponding Source along with the object code. If the place to copy +the object code is a network server, the Corresponding Source may be +on a different server (operated by you or a third party) that supports +equivalent copying facilities, provided you maintain clear directions +next to the object code saying where to find the Corresponding Source. +Regardless of what server hosts the Corresponding Source, you remain +obligated to ensure that it is available for as long as needed to +satisfy these requirements. + + <li>Convey the object code using peer-to-peer transmission, provided you +inform other peers where the object code and Corresponding Source of +the work are being offered to the general public at no charge under +subsection 6d. + + </ol> + + <p>A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + <p>A “User Product” is either (1) a “consumer product”, which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +“normally used” refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + + <p>“Installation Information” for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + + <p>If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + <p>The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + + <p>Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + <li>Additional Terms. + + <p>“Additional permissions” are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + <p>When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + <p>Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + + <ol type=a start=1> +<li>Disclaiming warranty or limiting liability differently from the terms +of sections 15 and 16 of this License; or + + <li>Requiring preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices +displayed by works containing it; or + + <li>Prohibiting misrepresentation of the origin of that material, or +requiring that modified versions of such material be marked in +reasonable ways as different from the original version; or + + <li>Limiting the use for publicity purposes of names of licensors or +authors of the material; or + + <li>Declining to grant rights under trademark law for use of some trade +names, trademarks, or service marks; or + + <li>Requiring indemnification of licensors and authors of that material by +anyone who conveys the material (or modified versions of it) with +contractual assumptions of liability to the recipient, for any +liability that these contractual assumptions directly impose on those +licensors and authors. + </ol> + + <p>All other non-permissive additional terms are considered “further +restrictions” within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + <p>If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + <p>Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + + <li>Termination. + + <p>You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + <p>However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + + <p>Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + <p>Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + <li>Acceptance Not Required for Having Copies. + + <p>You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + <li>Automatic Licensing of Downstream Recipients. + + <p>Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + <p>An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + <p>You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + <li>Patents. + + <p>A “contributor” is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's “contributor version”. + + <p>A contributor's “essential patent claims” are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + <p>Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + <p>In the following three paragraphs, a “patent license” is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To “grant” such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + <p>If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. “Knowingly relying” means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + <p>If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + <p>A patent license is “discriminatory” if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + + <p>Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + <li>No Surrender of Others' Freedom. + + <p>If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey +a covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree +to terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + + <li>Use with the GNU Affero General Public License. + + <p>Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + <li>Revised Versions of this License. + + <p>The Free Software Foundation may publish revised and/or new versions +of the GNU General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + <p>Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU General Public +License “or any later version” applies to it, you have the option of +following the terms and conditions either of that numbered version or +of any later version published by the Free Software Foundation. If +the Program does not specify a version number of the GNU General +Public License, you may choose any version ever published by the Free +Software Foundation. + + <p>If the Program specifies that a proxy can decide which future versions +of the GNU General Public License can be used, that proxy's public +statement of acceptance of a version permanently authorizes you to +choose that version for the Program. + + <p>Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + <li>Disclaimer of Warranty. + + <p>THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + + <li>Limitation of Liability. + + <p>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + <li>Interpretation of Sections 15 and 16. + + <p>If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + </ol> + +<h3 class="heading">END OF TERMS AND CONDITIONS</h3> + +<h3 class="heading">How to Apply These Terms to Your New Programs</h3> + +<p>If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + <p>To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the “copyright” line and a pointer to where the full notice is found. + +<pre class="smallexample"> <var>one line to give the program's name and a brief idea of what it does.</var> + Copyright (C) <var>year</var> <var>name of author</var> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>. +</pre> + <p>Also add information on how to contact you by electronic and paper mail. + + <p>If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +<pre class="smallexample"> <var>program</var> Copyright (C) <var>year</var> <var>name of author</var> + This program comes with ABSOLUTELY NO WARRANTY; for details type ‘<samp><span class="samp">show w</span></samp>’. + This is free software, and you are welcome to redistribute it + under certain conditions; type ‘<samp><span class="samp">show c</span></samp>’ for details. +</pre> + <p>The hypothetical commands ‘<samp><span class="samp">show w</span></samp>’ and ‘<samp><span class="samp">show c</span></samp>’ should show +the appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an “about box”. + + <p>You should also get your employer (if you work as a programmer) or school, +if any, to sign a “copyright disclaimer” for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>. + + <p>The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use +the GNU Lesser General Public License instead of this License. But +first, please read <a href="http://www.gnu.org/philosophy/why-not-lgpl.html">http://www.gnu.org/philosophy/why-not-lgpl.html</a>. + +<!-- INDEX --> +<div class="node"> +<a name="Concept-Index"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Function-Index">Function Index</a>, +Previous: <a rel="previous" accesskey="p" href="#Copying">Copying</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="unnumbered">Concept Index</h2> + +<ul class="index-cp" compact> +<li><a href="#index-Approximate-MVA-166">Approximate MVA</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Asymmetric-_0040math_007bM_002fM_002fm_007d-system-66">Asymmetric M/M/m system</a>: <a href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a></li> +<li><a href="#index-BCMP-network-121">BCMP network</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Birth_002ddeath-process-19">Birth-death process</a>: <a href="#Birth_002dDeath-process">Birth-Death process</a></li> +<li><a href="#index-blocking-queueing-network-216">blocking queueing network</a>: <a href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a></li> +<li><a href="#index-bounds_002c-asymptotic-228">bounds, asymptotic</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-bounds_002c-balanced-system-243">bounds, balanced system</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-bounds_002c-geometric-260">bounds, geometric</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-closed-network-266">closed network</a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-closed-network-237">closed network</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-closed-network-98">closed network</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Closed-network_002c-approximate-analysis-168">Closed network, approximate analysis</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-closed-network_002c-finite-capacity-217">closed network, finite capacity</a>: <a href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a></li> +<li><a href="#index-closed-network_002c-multiple-classes-273">closed network, multiple classes</a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-closed-network_002c-multiple-classes-223">closed network, multiple classes</a>: <a href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a></li> +<li><a href="#index-Closed-network_002c-multiple-classes-198">Closed network, multiple classes</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-closed-network_002c-multiple-classes-180">closed network, multiple classes</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Closed-network_002c-single-class-167">Closed network, single class</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-closed-network_002c-single-class-137">closed network, single class</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-CMVA-158">CMVA</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Continuous-time-Markov-chain-14">Continuous time Markov chain</a>: <a href="#CTMC-Stationary-Probability">CTMC Stationary Probability</a></li> +<li><a href="#index-convolution-algorithm-100">convolution algorithm</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-copyright-282">copyright</a>: <a href="#Copying">Copying</a></li> +<li><a href="#index-Discrete-time-Markov-chain-4">Discrete time Markov chain</a>: <a href="#DTMC-Stationary-Probability">DTMC Stationary Probability</a></li> +<li><a href="#index-Expected-sojourn-time-22">Expected sojourn time</a>: <a href="#Expected-Sojourn-Time">Expected Sojourn Time</a></li> +<li><a href="#index-First-passage-times-36">First passage times</a>: <a href="#CTMC-First-Passage-Times">CTMC First Passage Times</a></li> +<li><a href="#index-First-passage-times-10">First passage times</a>: <a href="#DTMC-First-Passage-Times">DTMC First Passage Times</a></li> +<li><a href="#index-Jackson-network-91">Jackson network</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-load_002ddependent-service-center-110">load-dependent service center</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-g_t_0040math_007bM_002fG_002f1_007d-system-72">M/G/1 system</a>: <a href="#The-M_002fG_002f1-System">The M/G/1 System</a></li> +<li><a href="#index-g_t_0040math_007bM_002fH_005fm_002f1_007d-system-74">M/H_m/1 system</a>: <a href="#The-M_002fHm_002f1-System">The M/Hm/1 System</a></li> +<li><a href="#index-g_t_0040math_007bM_002fM_002f1_007d-system-38">M/M/1 system</a>: <a href="#The-M_002fM_002f1-System">The M/M/1 System</a></li> +<li><a href="#index-g_t_0040math_007bM_002fM_002f1_002fK_007d-system-58">M/M/1/K system</a>: <a href="#The-M_002fM_002f1_002fK-System">The M/M/1/K System</a></li> +<li><a href="#index-g_t_0040math_007bM_002fM_002f_007dinf-system-51">M/M/inf system</a>: <a href="#The-M_002fM_002finf-System">The M/M/inf System</a></li> +<li><a href="#index-g_t_0040math_007bM_002fM_002fm_007d-system-45">M/M/m system</a>: <a href="#The-M_002fM_002fm-System">The M/M/m System</a></li> +<li><a href="#index-g_t_0040math_007bM_002fM_002fm_002fK_007d-system-60">M/M/m/K system</a>: <a href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a></li> +<li><a href="#index-Markov-chain_002c-continuous-time-35">Markov chain, continuous time</a>: <a href="#CTMC-First-Passage-Times">CTMC First Passage Times</a></li> +<li><a href="#index-Markov-chain_002c-continuous-time-27">Markov chain, continuous time</a>: <a href="#Expected-Time-to-Absorption">Expected Time to Absorption</a></li> +<li><a href="#index-Markov-chain_002c-continuous-time-24">Markov chain, continuous time</a>: <a href="#Time_002dAveraged-Expected-Sojourn-Time">Time-Averaged Expected Sojourn Time</a></li> +<li><a href="#index-Markov-chain_002c-continuous-time-21">Markov chain, continuous time</a>: <a href="#Expected-Sojourn-Time">Expected Sojourn Time</a></li> +<li><a href="#index-Markov-chain_002c-continuous-time-18">Markov chain, continuous time</a>: <a href="#Birth_002dDeath-process">Birth-Death process</a></li> +<li><a href="#index-Markov-chain_002c-continuous-time-13">Markov chain, continuous time</a>: <a href="#CTMC-Stationary-Probability">CTMC Stationary Probability</a></li> +<li><a href="#index-Markov-chain_002c-discrete-time-9">Markov chain, discrete time</a>: <a href="#DTMC-First-Passage-Times">DTMC First Passage Times</a></li> +<li><a href="#index-Markov-chain_002c-discrete-time-3">Markov chain, discrete time</a>: <a href="#DTMC-Stationary-Probability">DTMC Stationary Probability</a></li> +<li><a href="#index-Markov-chain_002c-state-occupancy-probabilities-15">Markov chain, state occupancy probabilities</a>: <a href="#CTMC-Stationary-Probability">CTMC Stationary Probability</a></li> +<li><a href="#index-Markov-chain_002c-stationary-probabilities-5">Markov chain, stationary probabilities</a>: <a href="#DTMC-Stationary-Probability">DTMC Stationary Probability</a></li> +<li><a href="#index-Mean-time-to-absorption-28">Mean time to absorption</a>: <a href="#Expected-Time-to-Absorption">Expected Time to Absorption</a></li> +<li><a href="#index-Mean-Value-Analysys-_0028MVA_0029-136">Mean Value Analysys (MVA)</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Mean-Value-Analysys-_0028MVA_0029_002c-approximate-165">Mean Value Analysys (MVA), approximate</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-mixed-network-208">mixed network</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-normalization-constant-99">normalization constant</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-open-network-268">open network</a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-open-network-229">open network</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-open-network_002c-multiple-classes-128">open network, multiple classes</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-open-network_002c-single-class-90">open network, single class</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-population-mix-272">population mix</a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-queueing-network-with-blocking-215">queueing network with blocking</a>: <a href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a></li> +<li><a href="#index-queueing-networks-75">queueing networks</a>: <a href="#Queueing-Networks">Queueing Networks</a></li> +<li><a href="#index-RS-blocking-226">RS blocking</a>: <a href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a></li> +<li><a href="#index-Stationary-probabilities-16">Stationary probabilities</a>: <a href="#CTMC-Stationary-Probability">CTMC Stationary Probability</a></li> +<li><a href="#index-Stationary-probabilities-6">Stationary probabilities</a>: <a href="#DTMC-Stationary-Probability">DTMC Stationary Probability</a></li> +<li><a href="#index-Time_002dalveraged-sojourn-time-25">Time-alveraged sojourn time</a>: <a href="#Time_002dAveraged-Expected-Sojourn-Time">Time-Averaged Expected Sojourn Time</a></li> +<li><a href="#index-traffic-intensity-52">traffic intensity</a>: <a href="#The-M_002fM_002finf-System">The M/M/inf System</a></li> +<li><a href="#index-warranty-281">warranty</a>: <a href="#Copying">Copying</a></li> + </ul><div class="node"> +<a name="Function-Index"></a> +<p><hr> +Next: <a rel="next" accesskey="n" href="#Author-Index">Author Index</a>, +Previous: <a rel="previous" accesskey="p" href="#Concept-Index">Concept Index</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="unnumbered">Function Index</h2> + + + +<ul class="index-fn" compact> +<li><a href="#index-ctmc-11"><code>ctmc</code></a>: <a href="#CTMC-Stationary-Probability">CTMC Stationary Probability</a></li> +<li><a href="#index-ctmc_005fbd-17"><code>ctmc_bd</code></a>: <a href="#Birth_002dDeath-process">Birth-Death process</a></li> +<li><a href="#index-ctmc_005fexps-20"><code>ctmc_exps</code></a>: <a href="#Expected-Sojourn-Time">Expected Sojourn Time</a></li> +<li><a href="#index-ctmc_005ffpt-33"><code>ctmc_fpt</code></a>: <a href="#CTMC-First-Passage-Times">CTMC First Passage Times</a></li> +<li><a href="#index-ctmc_005fmtta-26"><code>ctmc_mtta</code></a>: <a href="#Expected-Time-to-Absorption">Expected Time to Absorption</a></li> +<li><a href="#index-ctmc_005ftaexps-23"><code>ctmc_taexps</code></a>: <a href="#Time_002dAveraged-Expected-Sojourn-Time">Time-Averaged Expected Sojourn Time</a></li> +<li><a href="#index-dtmc-1"><code>dtmc</code></a>: <a href="#DTMC-Stationary-Probability">DTMC Stationary Probability</a></li> +<li><a href="#index-dtmc_005ffpt-7"><code>dtmc_fpt</code></a>: <a href="#DTMC-First-Passage-Times">DTMC First Passage Times</a></li> +<li><a href="#index-population_005fmix-271"><code>population_mix</code></a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-qnammm-65"><code>qnammm</code></a>: <a href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a></li> +<li><a href="#index-qnclosed-265"><code>qnclosed</code></a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-qnclosedab-234"><code>qnclosedab</code></a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-qnclosedbsb-249"><code>qnclosedbsb</code></a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-qnclosedgb-259"><code>qnclosedgb</code></a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-qnclosedmultimva-173"><code>qnclosedmultimva</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnclosedmultimvaapprox-191"><code>qnclosedmultimvaapprox</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnclosedpb-253"><code>qnclosedpb</code></a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-qnclosedsinglemva-133"><code>qnclosedsinglemva</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnclosedsinglemvaapprox-160"><code>qnclosedsinglemvaapprox</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnclosedsinglemvald-146"><code>qnclosedsinglemvald</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qncmva-155"><code>qncmva</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnconvolution-96"><code>qnconvolution</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnconvolutionld-106"><code>qnconvolutionld</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnjackson-87"><code>qnjackson</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnmarkov-219"><code>qnmarkov</code></a>: <a href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a></li> +<li><a href="#index-qnmg1-71"><code>qnmg1</code></a>: <a href="#The-M_002fG_002f1-System">The M/G/1 System</a></li> +<li><a href="#index-qnmh1-73"><code>qnmh1</code></a>: <a href="#The-M_002fHm_002f1-System">The M/Hm/1 System</a></li> +<li><a href="#index-qnmix-206"><code>qnmix</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnmknode-76"><code>qnmknode</code></a>: <a href="#Generic-Algorithms">Generic Algorithms</a></li> +<li><a href="#index-qnmm1-37"><code>qnmm1</code></a>: <a href="#The-M_002fM_002f1-System">The M/M/1 System</a></li> +<li><a href="#index-qnmm1k-57"><code>qnmm1k</code></a>: <a href="#The-M_002fM_002f1_002fK-System">The M/M/1/K System</a></li> +<li><a href="#index-qnmminf-50"><code>qnmminf</code></a>: <a href="#The-M_002fM_002finf-System">The M/M/inf System</a></li> +<li><a href="#index-qnmmm-43"><code>qnmmm</code></a>: <a href="#The-M_002fM_002fm-System">The M/M/m System</a></li> +<li><a href="#index-qnmmmk-59"><code>qnmmmk</code></a>: <a href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a></li> +<li><a href="#index-qnmvablo-214"><code>qnmvablo</code></a>: <a href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a></li> +<li><a href="#index-qnmvapop-276"><code>qnmvapop</code></a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-qnopen-267"><code>qnopen</code></a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-qnopenab-227"><code>qnopenab</code></a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-qnopenbsb-242"><code>qnopenbsb</code></a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-qnopenmulti-126"><code>qnopenmulti</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnopensingle-118"><code>qnopensingle</code></a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-qnsolve-83"><code>qnsolve</code></a>: <a href="#Generic-Algorithms">Generic Algorithms</a></li> +<li><a href="#index-qnvisits-269"><code>qnvisits</code></a>: <a href="#Utility-functions">Utility functions</a></li> + </ul><div class="node"> +<a name="Author-Index"></a> +<p><hr> +Previous: <a rel="previous" accesskey="p" href="#Function-Index">Function Index</a>, +Up: <a rel="up" accesskey="u" href="#Top">Top</a> + +</div> + +<h2 class="unnumbered">Author Index</h2> + + + +<ul class="index-au" compact> +<li><a href="#index-Akyildiz_002c-I_002e-F_002e-218">Akyildiz, I. F.</a>: <a href="#Algorithms-for-non-Product_002dform-QNs">Algorithms for non Product-form QNs</a></li> +<li><a href="#index-Bard_002c-Y_002e-200">Bard, Y.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Bolch_002c-G_002e-92">Bolch, G.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Bolch_002c-G_002e-67">Bolch, G.</a>: <a href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a></li> +<li><a href="#index-Bolch_002c-G_002e-61">Bolch, G.</a>: <a href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a></li> +<li><a href="#index-Bolch_002c-G_002e-53">Bolch, G.</a>: <a href="#The-M_002fM_002finf-System">The M/M/inf System</a></li> +<li><a href="#index-Bolch_002c-G_002e-46">Bolch, G.</a>: <a href="#The-M_002fM_002fm-System">The M/M/m System</a></li> +<li><a href="#index-Bolch_002c-G_002e-39">Bolch, G.</a>: <a href="#The-M_002fM_002f1-System">The M/M/1 System</a></li> +<li><a href="#index-Bolch_002c-G_002e-29">Bolch, G.</a>: <a href="#Expected-Time-to-Absorption">Expected Time to Absorption</a></li> +<li><a href="#index-Buzen_002c-J_002e-P_002e-101">Buzen, J. P.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Casale_002c-G_002e-256">Casale, G.</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Casale_002c-G_002e-159">Casale, G.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-de-Meer_002c-H_002e-94">de Meer, H.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-de-Meer_002c-H_002e-69">de Meer, H.</a>: <a href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a></li> +<li><a href="#index-de-Meer_002c-H_002e-63">de Meer, H.</a>: <a href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a></li> +<li><a href="#index-de-Meer_002c-H_002e-55">de Meer, H.</a>: <a href="#The-M_002fM_002finf-System">The M/M/inf System</a></li> +<li><a href="#index-de-Meer_002c-H_002e-48">de Meer, H.</a>: <a href="#The-M_002fM_002fm-System">The M/M/m System</a></li> +<li><a href="#index-de-Meer_002c-H_002e-41">de Meer, H.</a>: <a href="#The-M_002fM_002f1-System">The M/M/1 System</a></li> +<li><a href="#index-de-Meer_002c-H_002e-31">de Meer, H.</a>: <a href="#Expected-Time-to-Absorption">Expected Time to Absorption</a></li> +<li><a href="#index-Graham_002c-G_002e-S_002e-232">Graham, G. S.</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Graham_002c-G_002e-S_002e-131">Graham, G. S.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Greiner_002c-S_002e-93">Greiner, S.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Greiner_002c-S_002e-68">Greiner, S.</a>: <a href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a></li> +<li><a href="#index-Greiner_002c-S_002e-62">Greiner, S.</a>: <a href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a></li> +<li><a href="#index-Greiner_002c-S_002e-54">Greiner, S.</a>: <a href="#The-M_002fM_002finf-System">The M/M/inf System</a></li> +<li><a href="#index-Greiner_002c-S_002e-47">Greiner, S.</a>: <a href="#The-M_002fM_002fm-System">The M/M/m System</a></li> +<li><a href="#index-Greiner_002c-S_002e-40">Greiner, S.</a>: <a href="#The-M_002fM_002f1-System">The M/M/1 System</a></li> +<li><a href="#index-Greiner_002c-S_002e-30">Greiner, S.</a>: <a href="#Expected-Time-to-Absorption">Expected Time to Absorption</a></li> +<li><a href="#index-Hsieh_002c-C_002e-H-254">Hsieh, C. H</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Jain_002c-R_002e-141">Jain, R.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Kobayashi_002c-H_002e-113">Kobayashi, H.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Lam_002c-S_002e-255">Lam, S.</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Lavenberg_002c-S_002e-S_002e-140">Lavenberg, S. S.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Lazowska_002c-E_002e-D_002e-230">Lazowska, E. D.</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Lazowska_002c-E_002e-D_002e-129">Lazowska, E. D.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Muntz_002c-R_002e-R_002e-257">Muntz, R. R.</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Reiser_002c-M_002e-112">Reiser, M.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Santini_002c-S_002e-275">Santini, S.</a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-Schweitzer_002c-P_002e-201">Schweitzer, P.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Schwetman_002c-H_002e-274">Schwetman, H.</a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-Schwetman_002c-H_002e-111">Schwetman, H.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Serazzi_002c-G_002e-258">Serazzi, G.</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Sevcik_002c-K_002e-C_002e-233">Sevcik, K. C.</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Sevcik_002c-K_002e-C_002e-132">Sevcik, K. C.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Trivedi_002c-K_002e-95">Trivedi, K.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> +<li><a href="#index-Trivedi_002c-K_002e-70">Trivedi, K.</a>: <a href="#The-Asymmetric-M_002fM_002fm-System">The Asymmetric M/M/m System</a></li> +<li><a href="#index-Trivedi_002c-K_002e-64">Trivedi, K.</a>: <a href="#The-M_002fM_002fm_002fK-System">The M/M/m/K System</a></li> +<li><a href="#index-Trivedi_002c-K_002e-56">Trivedi, K.</a>: <a href="#The-M_002fM_002finf-System">The M/M/inf System</a></li> +<li><a href="#index-Trivedi_002c-K_002e-49">Trivedi, K.</a>: <a href="#The-M_002fM_002fm-System">The M/M/m System</a></li> +<li><a href="#index-Trivedi_002c-K_002e-42">Trivedi, K.</a>: <a href="#The-M_002fM_002f1-System">The M/M/1 System</a></li> +<li><a href="#index-Trivedi_002c-K_002e-32">Trivedi, K.</a>: <a href="#Expected-Time-to-Absorption">Expected Time to Absorption</a></li> +<li><a href="#index-Wong_002c-E_002e-280">Wong, E.</a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-Zahorjan_002c-J_002e-279">Zahorjan, J.</a>: <a href="#Utility-functions">Utility functions</a></li> +<li><a href="#index-Zahorjan_002c-J_002e-231">Zahorjan, J.</a>: <a href="#Bounds-on-performance">Bounds on performance</a></li> +<li><a href="#index-Zahorjan_002c-J_002e-130">Zahorjan, J.</a>: <a href="#Algorithms-for-Product_002dForm-QNs">Algorithms for Product-Form QNs</a></li> + </ul></body></html> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/queueing.texi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,203 @@ +% Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +% +% This file is part of the queueing toolbox, a Queueing Networks analysis +% package for GNU Octave +% +% The queueing toolbox is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the +% Free Software Foundation; either version 3 of the License, or (at +% your option) any later version. +% +% The queueing toolbox is distributed in the hope that it will be useful, but +% WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +% for more details. +% +% You should have received a copy of the GNU General Public License +% along with the queueing toolbox; see the file COPYING. If not, see +% <http://www.gnu.org/licenses/>. + +% This info file is take from the GNU Octave info file + +\input texinfo +@setfilename queueing.info + +@c The following macro is used for the on-line help system, but we don't +@c want lots of `See also: foo, bar, and baz' strings cluttering the +@c printed manual (that information should be in the supporting text for +@c each group of functions and variables). + +@macro seealso {args} +@iftex +@vskip 2pt +@end iftex +@ifnottex +@sp 1 +@end ifnottex +@noindent +@strong{See also:} \args\. +@end macro + +@macro examplefile{file} +@example +@group +@verbatiminclude @value{top_srcdir}/examples/\file\ +@end group +@end example +@end macro + +@ifinfo +@format +START-INFO-DIR-ENTRY +* queueing: (octave). Queueing Networks and Markov chains analysis package. +END-INFO-DIR-ENTRY +@end format +@end ifinfo + +@c Settings for printing on 8-1/2 by 11 inch paper: +@c ----------------------------------------------- + +@setchapternewpage odd + +@c Settings for small book format: +@c ------------------------------ + +@ignore +@smallbook +@setchapternewpage odd +@finalout +@iftex +@cropmarks +@end iftex +@end ignore + +@defindex op +@defindex au + +@c Things like the Octave version number are defined in conf.texi. +@c This file doesn't include a chapter, so it must not be included +@c if you want to run the Emacs function texinfo-multiple-files-update. + +@include conf.texi + +@settitle queueing +@documentdescription +User manual for the queueing toolbox, a GNU Octave package for queueing networks and Markov chains analysis. This package supports single-station queueing systems, queueing networks and Markov chains. The queueing toolbox implements, among others, the Mean Value Analysis (MVA) and convolution algorithms for product-form queueing networks. Transient and steady-state analysis of Markov chains is also implemented. +@end documentdescription + +@ifnottex + +Copyright @copyright{} 2008, 2009, 2010, 2011, 2012 Moreno Marzolla. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through Tex and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of +this manual under the conditions for verbatim copying, provided that +the entire resulting derived work is distributed under the terms of +a permission notice identical to this one. + +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for +modified versions. +@end ifnottex + +@titlepage +@title The Octave Queueing Toolbox +@subtitle User's Guide, Edition 1 for release @value{VERSION} +@subtitle @value{VERSIONDATE} +@author Moreno Marzolla +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 2008, 2009, 2010, 2011, 2012 Moreno Marzolla (@email{marzolla@@cs.unibo.it}). + +This is the first edition of the Queueing Toolbox documentation, and +is consistent with version @value{VERSION} of the package. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the same conditions as for modified versions. + +Portions of this document have been adapted from the @code{octave} +manual, Copyright @copyright{} John W. Eaton. +@end titlepage + +@contents + +@ifnottex +@node Top +@top + +This manual documents how to install and run the Queueing Toolbox. +It corresponds to version @value{VERSION} of the package. +@end ifnottex + +@c ------------------------------------------------------------------------ + +@menu +* Summary:: +* Installation:: Installation of the queueing toolbox. +* Getting Started:: Getting started with the queueing toolbox. +* Markov Chains:: Functions for Markov Chains. +* Single Station Queueing Systems:: Functions for single-station queueing systems. +* Queueing Networks:: Functions for queueing networks. +* Contributing Guidelines:: How to contribute. +* Acknowledgements:: People who contributed to the queueing toolbox. +* Copying:: The GNU General Public License. +* Concept Index:: An item for each concept. +* Function Index:: An item for each function. +* Author Index:: An item for each author. +@end menu + +@c ------------------------------------------------------------------------ + +@include summary.texi +@include installation.texi +@include gettingstarted.texi +@include markovchains.texi +@include singlestation.texi +@include queueingnetworks.texi + +@c +@c Appendix starts here +@c +@include contributing.texi +@include ack.texi +@include gpl.texi + +@c +@c INDEX +@c + +@node Concept Index +@unnumbered Concept Index + +@printindex cp + +@node Function Index +@unnumbered Function Index + +@printindex fn + +@node Author Index +@unnumbered Author Index + +@printindex au + +@bye
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/queueingnetworks.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,1196 @@ +@c -*- texinfo -*- + +@c Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +@c +@c This file is part of the queueing toolbox, a Queueing Networks +@c analysis package for GNU Octave. +@c +@c The queueing toolbox is free software; you can redistribute it +@c and/or modify it under the terms of the GNU General Public License +@c as published by the Free Software Foundation; either version 3 of +@c the License, or (at your option) any later version. +@c +@c The queueing toolbox is distributed in the hope that it will be +@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty +@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with the queueing toolbox; see the file COPYING. If not, see +@c <http://www.gnu.org/licenses/>. + +@node Queueing Networks +@chapter Queueing Networks + +@menu +* Introduction to QNs:: A brief introduction to Queueing Networks. +* Generic Algorithms:: High-level functions for QN analysis +* Algorithms for Product-Form QNs:: Functions to analyze product-form QNs +* Algorithms for non Product-form QNs:: Functions to analyze non product-form QNs +* Bounds on performance:: Functions to compute performance bounds +* Utility functions:: Utility functions to compute miscellaneous quantities +@end menu + +@cindex queueing networks + +@c +@c INTRODUCTION +@c +@node Introduction to QNs +@section Introduction to QNs + +Queueing Networks (QN) are a very simple yet powerful modeling tool +which is used to analyze many kind of systems. In its simplest form, a +QN is made of @math{K} service centers. Each service center @math{i} +has a queue, which is connected to @math{m_i} (generally identical) +@emph{servers}. Customers (or requests) arrive at the service center, +and join the queue if there is a slot available. Then, requests are +served according to a (de)queueing policy. After service completes, +the requests leave the service center. + +The service centers for which @math{m_i = \infty} are called +@emph{delay centers} or @emph{infinite servers}. If a service center +has infinite servers, of course each new request will find one server +available, so there will never be queueing. + +Requests join the queue according to a @emph{queueing policy}, such as: + +@table @strong + +@item FCFS +First-Come-First-Served + +@item LCFS-PR +Last-Come-First-Served, Preemptive Resume + +@item PS +Processor Sharing + +@item IS +Infinite Server, there is an infinite number of identical servers so +that each request always finds a server available, and there is no +queueing + +@end table + +A population of @emph{requests} or @emph{customers} arrives to the +system system, requesting service to the service centers. The request +population may be @emph{open} or @emph{closed}. In open systems there +is an infinite population of requests. New customers arrive from +outside the system, and eventually leave the system. In closed systems +there is a fixed population of request which continuously interacts +with the system. + +There might be a single class of requests, meaning that all requests +behave in the same way (e.g., they spend the same average time on each +particular server), or there might be multiple classes of requests. + +@subsection Single class models + +In single class models, all requests are indistinguishable and belong to +the same class. This means that every request has the same average +service time, and all requests move through the system with the same +routing probabilities. + +@noindent @strong{Model Inputs} + +@table @math + +@item \lambda_i +External arrival rate to service center @math{i}. + +@item \lambda +Overall external arrival rate to the whole system: @math{\lambda = +\sum_i \lambda_i}. + +@item S_i +Average service time. @math{S_i} is the average service time on service +center @math{i}. In other words, @math{S_i} is the average time from the +instant in which a request is extracted from the queue and starts being +service, and the instant at which service finishes and the request moves +to another queue (or exits the system). + +@item P_{ij} +Routing probability matrix. @math{{\bf P} = P_{ij}} is a @math{K \times +K} matrix such that @math{P_{ij}} is the probability that a request +completing service at server @math{i} will move directly to server +@math{j}, The probability that a request leaves the system after service +at service center @math{i} is @math{1-\sum_{j=1}^K P_{ij}}. + +@item V_i +Average number of visits. @math{V_i} is the average number of visits to +the service center @math{i}. This quantity will be described shortly. + +@end table + +@noindent @strong{Model Outputs} + +@table @math + +@item U_i +Service center utilization. @math{U_i} is the utilization of service +center @math{i}. The utilization is defined as the fraction of time in +which the resource is busy (i.e., the server is processing requests). + +@item R_i +Average response time. @math{R_i} is the average response time of +service center @math{i}. The average response time is defined as the +average time between the arrival of a customer in the queue, and the +completion of service. + +@item Q_i +Average number of customers. @math{Q_i} is the average number of +requests in service center @math{i}. This includes both the requests in +the queue, and the request being served. + +@item X_i +Throughput. @math{X_i} is the throughput of service center @math{i}. +The throughput is defined as the ratio of job completions (i.e., average +number of jobs completed over a fixed interval of time). + +@end table + +@noindent Given these output parameters, additional performance measures can +be computed as follows: + +@table @math + +@item X +System throughput, @math{X = X_1 / V_1} + +@item R +System response time, @math{R = \sum_{k=1}^K R_k V_k} + +@item Q +Average number of requests in the system, @math{Q = N-XZ} + +@end table + +For open, single-class models, the scalar @math{\lambda} denotes the +external arrival rate of requests to the system. The average number of +visits satisfy the following equation: + +@iftex +@tex +$V_j = P_{0 j} + \sum_{i=1}^K V_i P_{i j}$ +@end tex +@end iftex +@ifnottex +@example +V == P0 + V*P; +@end example +@end ifnottex + +@noindent where @math{P_{0 j}} is the probability that an external +arrival goes to service center @math{j}. If @math{\lambda_j} is the +external arrival rate to service center @math{j}, and @math{\lambda = +\sum_j \lambda_j} is the overall external arrival rate, then +@math{P_{0 j} = \lambda_j / \lambda}. + +For closed models, the visit ratios satisfy the following equation: + +@iftex +@tex +$V_j = \sum_{i=1}^K V_i P_{i j}$ +@end tex +@end iftex +@ifnottex +@example +V(1) == 1 && V == V*P; +@end example +@end ifnottex + +@subsection Multiple class models + +In multiple class QN models, we assume that there exist @math{C} +different classes of requests. Each request from class @math{c} spends +on average time @math{S_{ck}} in service at service center @math{k}. For +open models, we denote with @math{{\bf \lambda} = \lambda_{ck}} the +arrival rates, where @math{\lambda_{ck}} is the external arrival rate of +class @math{c} customers at service center @math{k}. For closed models, +we denote with @math{{\bf N} = (N_1, N_2, \ldots N_C)} the population +vector, where @math{N_c} is the number of class @math{c} requests in the +system. + +The transition probability matrix for these kind of networks will be a +@math{C \times K \times C \times K} matrix @math{{\bf P} = +P_{risj}} such that @math{P_{risj}} is the probability that a +class @math{r} request which completes service at center @math{i} will +join server @math{j} as a class @math{s} request. + +Model input and outputs can be adjusted by adding additional +indexes for the customer classes. + +@noindent @strong{Model Inputs} + +@table @math + +@item \lambda_{ci} +External arrival rate of class-@math{c} requests to service center @math{i} + +@item \lambda +Overall external arrival rate to the whole system: @math{\lambda = \sum_c \sum_i \lambda_{ci}} + +@item S_{ci} +Average service time. @math{S_{ci}} is the average service time on service +center @math{i} for class @math{c} requests. + +@item P_{risj} +Routing probability matrix. @math{{\bf P} = P_{risj}} is a @math{C +\times K \times C \times K} matrix such that @math{P_{risj}} is the +probability that a class @math{r} request which completes service at +server @math{i} will move to server @math{j} as a class @math{s} +request. + +@item V_{ci} +Average number of visits. @math{V_{ci}} is the average number of visits +of class @math{c} requests to the service center @math{i}. + +@end table + +@noindent @strong{Model Outputs} + +@table @math + +@item U_{ci} +Utilization of service center @math{i} by class @math{c} requests. The +utilization is defined as the fraction of time in which the resource is +busy (i.e., the server is processing requests). + +@item R_{ci} +Average response time experienced by class @math{c} requests on service +center @math{i}. The average response time is defined as the average +time between the arrival of a customer in the queue, and the completion +of service. + +@item Q_{ci} +Average number of class @math{c} requests on service center +@math{i}. This includes both the requests in the queue, and the request +being served. + +@item X_{ci} +Throughput of service center @math{i} for class @math{c} requests. The +throughput is defined as the rate of completion of class @math{c} +requests. + +@end table + +@noindent It is possible to define aggregate performance measures as follows: + +@table @math + +@item U_i +Utilization of service center @math{i}: +@iftex +@tex +$U_i = \sum_{c=1}^C U_{ci}$ +@end tex +@end iftex +@ifnottex +@code{Ui = sum(U,1);} +@end ifnottex + +@item R_c +System response time for class @math{c} requests: +@iftex +@tex +$R_c = \sum_{i=1}^K R_{ci} V_{ci}$ +@end tex +@end iftex +@ifnottex +@code{Rc = sum( V.*R, 1 );} +@end ifnottex + +@item Q_c +Average number of class @math{c} requests in the system: +@iftex +@tex +$Q_c = \sum_{i=1}^K Q_{ci}$ +@end tex +@end iftex +@ifnottex +@code{Qc = sum( Q, 2 );} +@end ifnottex + +@item X_c +Class @math{c} throughput: +@iftex +@tex +$X_c = X_{c1} / V_{c1}$ +@end tex +@end iftex +@ifnottex +@code{Xc = X(:,1) ./ V(:,1);} +@end ifnottex + +@end table + +We can define the visit ratios @math{V_{sj}} for class @math{s} +customers at service center @math{j} as follows: + +@iftex +@tex +$V_{sj} = \sum_{r=1}^C \sum_{i=1}^K V_{ri} P_{risj},\ V_{s1} = 1$ +@end tex +@end iftex +@ifnottex +@group +V_sj = sum_r sum_i V_ri P_risj, for all s,j +@end group +@end ifnottex + +@noindent while for open networks: + +@iftex +@tex +$V_{sj} = P_{0sj} + \sum_{r=1}^C \sum_{i=1}^K V_{ri} P_{risj}$ +@end tex +@end iftex +@ifnottex +@group +V_sj = P_0sj + sum_r sum_i V_ri P_risj, for all s,j +@end group +@end ifnottex + +@noindent where @math{P_{0sj}} is the probability that an external +arrival goes to service center @math{j} as a class-@math{s} request. +If @math{\lambda_{sj}} is the external arrival rate of class @math{s} +requests to service center @math{j}, and @math{\lambda = \sum_s \sum_j +\lambda_{sj}} is the overall external arrival rate to the whole system, +then @math{P_{0sj} = \lambda_{sj} / \lambda}. + +@c +@c +@c +@node Generic Algorithms +@section Generic Algorithms + +The @code{queueing} package provides a couple of high-level functions +for defining and solving QN models. These functions can be used to +define a open or closed QN model (with single or multiple job +classes), with arbitrary configuration and queueing disciplines. At +the moment only product-form networks can be solved, @xref{Algorithms for Product-Form QNs}. + +The network is defined by two parameters. The first one is the list of +nodes, encoded as an Octave @emph{cell array}. The second parameter is +the visit ration @var{V}, which can be either a vector (for +single-class models) or a two-dimensional matrix (for multiple-class +models). + +Individual nodes in the network are structures build using the +@code{qnmknode} function. + +@DOCSTRING(qnmknode) + +After the network has been defined, it is possible to solve it using +the @code{qnsolve} function. Note that this function is somewhat less +efficient than those described in later sections, but +generally easier to use. + +@DOCSTRING(qnsolve) + +@noindent @strong{EXAMPLE} + +Let us consider a closed, multiclass network with @math{C=2} classes +and @math{K=3} service center. Let the population be @math{M=(2, 1)} +(class 1 has 2 requests, and class 2 has 1 request). The nodes are as +follows: + +@itemize + +@item Node 1 is a @math{M/M/1}--FCFS node, with load-dependent service +times. Service times are class-independent, and are defined by the +matrix @code{[0.2 0.1 0.1; 0.2 0.1 0.1]}. Thus, @code{@var{S}(1,2) = +0.2} means that service time for class 1 customers where there are 2 +requests in 0.2. Note that service times are class-independent; + +@item Node 2 is a @math{-/G/1}--PS node, with service times +@math{S_{12} = 0.4} for class 1, and @math{S_{22} = 0.6} for class 2 +requests; + +@item Node 3 is a @math{-/G/\infty} node (delay center), with service +times @math{S_{13}=1} and @math{S_{23}=2} for class 1 and 2 +respectively. + +@end itemize + +After defining the per-class visit count @var{V} such that +@code{@var{V}(c,k)} is the visit count of class @math{c} requests to +service center @math{k}. We can define and solve the model as +follows: + +@example +@verbatiminclude @value{top_srcdir}/examples/demo_1_qnsolve.m +@end example + + +@c +@c +@c +@node Algorithms for Product-Form QNs +@section Algorithms for Product-Form QNs + +Product-form queueing networks fulfill the following assumptions: + +@itemize + +@item The network can consist of open and closed job classes. + +@item The following queueing disciplines are allowed: FCFS, PS, LCFS-PR and IS. + +@item Service times for FCFS nodes must be exponentially distributed and +class-independent. Service centers at PS, LCFS-PR and IS nodes can +have any kind of service time distribution with a rational Laplace +transform. Furthermore, for PS, LCFS-PR and IS nodes, different +classes of customers can have different service times. + +@item The service rate of an FCFS node is only allowed to depend on the +number of jobs at this node; in a PS, LCFS-PR and IS node the service +rate for a particular job class can also depend on the number of jobs +of that class at the node. + +@item In open networks two kinds of arrival processes are allowed: i) the +arrival process is Poisson, with arrival rate @math{\lambda} which can +depend on the number of jobs in the network. ii) the arrival process +consists of @math{U} independent Poisson arrival streams where the +@math{U} job sources are assigned to the @math{U} chains; the arrival +rate can be load dependent. + +@end itemize + +@c +@c Jackson Networks +@c + +@subsection Jackson Networks + +Jackson networks satisfy the following conditions: + +@itemize + +@item +There is only one job class in the network; the overall number of jobs +in the system is unlimited. + +@item +There are @math{N} service centers in the network. Each service center +may have Poisson arrivals from outside the system. A job can leave +the system from any node. + +@item +Arrival rates as well as routing probabilities are independent from +the number of nodes in the network. + +@item +External arrivals and service times at the service centers are +exponentially distributed, and in general can be load-dependent. + +@item +Service discipline at each node is FCFS + +@end itemize + +We define the @emph{joint probability vector} @math{\pi(k_1, k_2, +\ldots k_N)} as the steady-state probability that there are @math{k_i} +requests at service center @math{i}, for all @math{i=1,2, \ldots N}. +Jackson networks have the property that the joint probability is the +product of the marginal probabilities @math{\pi_i}: + +@iftex +@tex +$$ \pi(k_1, k_2, \ldots k_N) = \prod_{i=1}^N \pi_i(k_i) $$ +@end tex +@end iftex +@ifnottex +@example +@var{joint_prob} = prod( @var{pi} ) +@end example +@end ifnottex + +@noindent where @math{\pi_i(k_i)} is the steady-state probability +that there are @math{k_i} requests at service center @math{i}. + +@DOCSTRING(qnjackson) + +@noindent @strong{REFERENCES} + +This implementation is based on G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications}, Wiley, +1998, pp. 284--287. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@subsection The Convolution Algorithm + +According to the BCMP theorem, the state probability of a closed +single class queueing network with @math{K} nodes and @math{N} requests +can be expressed as: + +@iftex +@tex +$$ \pi(k_1, k_2, \ldots k_K) = {1 \over G(N)} \prod_{i=1}^N F_i(k_i) $$ +@end tex +@end iftex +@ifnottex +@example +@group +k = [k1, k2, @dots{} kn]; @r{population vector} +p = 1/G(N+1) \prod F(i,k); +@end group +@end example +@end ifnottex + +Here @math{\pi(k_1, k_2, \ldots k_K)} is the joint probability of +having @math{k_i} requests at node @math{i}, for all @math{i=1,2, +\ldots K}. + +The @emph{convolution algorithms} computes the normalization constants +@math{G = (G(0), G(1), \ldots G(N))} for single-class, closed networks +with @math{N} requests. The normalization constants are returned as +vector @code{@var{G}=[@var{G}(1), @var{G}(2), ... @var{G}(N+1)]} where +@code{@var{G}(i+1)} is the value of @math{G(i)} (remember that Octave +uses 1-base vectors). The normalization constant can be used to +compute all performance measures of interest (utilization, average +response time and so on). + +@code{queueing} implements the convolution algorithm, in the function +@code{qnconvolution} and @code{qnconvolutionld}. The first one +supports single-station nodes, multiple-station nodes and IS nodes. +The second one supports networks with general load-dependent service +centers. + +@c +@c The Convolution Algorithm +@c + +@DOCSTRING(qnconvolution) + +@noindent @strong{EXAMPLE} + +The normalization constant @math{G} can be used to compute the +steady-state probabilities for a closed single class product-form +Queueing Network with @math{K} nodes. Let @code{@var{k}=[@math{k_1, +k_2, @dots{} k_K}]} be a valid population vector. Then, the +steady-state probability @code{@var{p}(i)} to have @code{@var{k}(i)} +requests at service center @math{i} can be computed as: + +@iftex +@tex +$$ +p_i(k_i) = {(V_i S_i)^{k_i} \over G(K)} \left(G(K-k_i) - V_i S_i G(K-k_i-1)\right), \quad i=1,2, \ldots K +$$ +@end tex +@end iftex + +@example +@verbatiminclude @value{top_srcdir}/examples/demo_1_qnconvolution.m +@print{} k(1)=1 prob=0.17975 +@print{} k(2)=2 prob=0.48404 +@print{} k(3)=0 prob=0.52779 +@end example + +@noindent @strong{NOTE} + +For a network with @math{K} service centers and @math{N} requests, +this implementation of the convolution algorithm has time and space +complexity @math{O(NK)}. + +@noindent @strong{REFERENCES} + +Jeffrey P. Buzen, @cite{Computational Algorithms for Closed Queueing +Networks with Exponential Servers}, Communications of the ACM, volume +16, number 9, september 1973, +pp. 527--531. @url{http://doi.acm.org/10.1145/362342.362345} + +@auindex Buzen, J. P. + +This implementation is based on G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications}, Wiley, +1998, pp. 313--317. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@c +@c Convolution for load-dependent service centers +@c +@DOCSTRING(qnconvolutionld) + +@noindent @strong{REFERENCES} + +Herb Schwetman, @cite{Some Computational Aspects of Queueing Network +Models}, Technical Report CSD-TR-354, Department of Computer Sciences, +Purdue University, feb, 1981 (revised). +@url{http://www.cs.purdue.edu/research/technical_reports/1980/TR%2080-354.pdf} + +@auindex Schwetman, H. + +M. Reiser, H. Kobayashi, @cite{On The Convolution Algorithm for +Separable Queueing Networks}, In Proceedings of the 1976 ACM +SIGMETRICS Conference on Computer Performance Modeling Measurement and +Evaluation (Cambridge, Massachusetts, United States, March 29--31, +1976). SIGMETRICS '76. ACM, New York, NY, +pp. 109--117. @url{http://doi.acm.org/10.1145/800200.806187} + +@auindex Reiser, M. +@auindex Kobayashi, H. + +This implementation is based on G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications}, Wiley, +1998, pp. 313--317. Function @code{qnconvolutionld} is slightly +different from the version described in Bolch et al. because it +supports general load-dependent centers (while the version in the book +does not). The modification is in the definition of function +@code{F()} in @code{qnconvolutionld} which has been made similar to +function @math{f_i} defined in Schwetman, @code{Some Computational +Aspects of Queueing Network Models}. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + + +@subsection Open networks + +@c +@c Open networks with single class +@c +@DOCSTRING(qnopensingle) + +From the results computed by this function, it is possible to derive +other quantities of interest as follows: + +@itemize + +@item +@strong{System Response Time}: The overall system response time +can be computed as +@iftex +@tex +$R_s = \sum_{i=1}^K V_i R_i$ +@end tex +@end iftex +@ifnottex +@code{R_s = dot(V,R);} +@end ifnottex + +@item +@strong{Average number of requests}: The average number of requests +in the system can be computed as: +@iftex +@tex +$Q_s = \sum_{i=1}^K Q(i)$ +@end tex +@end iftex +@ifnottex +@code{Q_s = sum(Q)} +@end ifnottex + +@end itemize + +@noindent @strong{EXAMPLE} + +@example +@verbatiminclude @value{top_srcdir}/examples/demo_1_qnopensingle.m +@print{} R_s = 1.4062 +@print{} N = 4.2186 +@end example + +@noindent @strong{REFERENCES} + +G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing +Networks and Markov Chains: Modeling and Performance Evaluation with +Computer Science Applications}, Wiley, 1998. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + + +@c +@c Open network with multiple classes +@c +@DOCSTRING(qnopenmulti) + +@noindent @strong{REFERENCES} + +Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. +Sevcik, @cite{Quantitative System Performance: Computer System +Analysis Using Queueing Network Models}, Prentice Hall, +1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In +particular, see section 7.4.1 ("Open Model Solution Techniques"). + +@auindex Lazowska, E. D. +@auindex Zahorjan, J. +@auindex Graham, G. S. +@auindex Sevcik, K. C. + + +@subsection Closed Networks + +@c +@c MVA for single class, closed networks +@c + +@DOCSTRING(qnclosedsinglemva) + +From the results provided by this function, it is possible to derive +other quantities of interest as follows: + +@noindent @strong{EXAMPLE} + +@example +@verbatiminclude @value{top_srcdir}/examples/demo_1_qnclosedsinglemva.m +@end example + + +@noindent @strong{REFERENCES} + +M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed +Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, April +1980, pp. 313--322. @url{http://doi.acm.org/10.1145/322186.322195} + +@auindex Reiser, M. +@auindex Lavenberg, S. S. + +This implementation is described in R. Jain , @cite{The Art of Computer +Systems Performance Analysis}, Wiley, 1991, p. 577. Multi-server nodes +@c and the computation of @math{G(N)}, +are treated according to G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications}, Wiley, +1998, Section 8.2.1, "Single Class Queueing Networks". + +@auindex Jain, R. +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@c +@c MVA for single class, closed networks with load dependent servers +@c +@DOCSTRING(qnclosedsinglemvald) + +@noindent @strong{REFERENCES} + +M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed +Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, +April 1980, pp. 313--322. @url{http://doi.acm.org/10.1145/322186.322195} + +This implementation is described in G. Bolch, S. Greiner, H. de Meer +and K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling +and Performance Evaluation with Computer Science Applications}, Wiley, +1998, Section 8.2.4.1, ``Networks with Load-Deèpendent Service: Closed +Networks''. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@c +@c CMVA for single class, closed networks with a single load dependent servers +@c +@DOCSTRING(qncmva) + +@noindent @strong{REFERENCES} + +G. Casale. @cite{A note on stable flow-equivalent aggregation in +closed networks}. Queueing Syst. Theory Appl., 60:193–202, December +2008. + +@auindex Casale, G. + +@c +@c Approximate MVA for single class, closed networks +@c + +@DOCSTRING(qnclosedsinglemvaapprox) + +@noindent @strong{REFERENCES} + +This implementation is based on Edward D. Lazowska, John Zahorjan, +G. Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System +Performance: Computer System Analysis Using Queueing Network Models}, +Prentice Hall, +1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In +particular, see section 6.4.2.2 ("Approximate Solution Techniques"). + +@auindex Lazowska, E. D. +@auindex Zahorjan, J. +@auindex Graham, G. S. +@auindex Sevcik, K. C. + + +@c +@c MVA for multiple class, closed networks +@c +@DOCSTRING(qnclosedmultimva) + +@noindent @strong{NOTE} + +Given a network with @math{K} service centers, @math{C} job classes and +population vector @math{{\bf N}=(N_1, N_2, \ldots N_C)}, the MVA +algorithm requires space @math{O(C \prod_i (N_i + 1))}. The time +complexity is @math{O(CK\prod_i (N_i + 1))}. This implementation is +slightly more space-efficient (see details in the code). While the space +requirement can be mitigated by using some optimizations, the time +complexity can not. If you need to analyze large closed networks you +should consider the @command{qnclosedmultimvaapprox} function, which +implements the approximate MVA algorithm. Note however that +@command{qnclosedmultimvaapprox} will only provide approximate results. + + +@noindent @strong{REFERENCES} + +M. Reiser and S. S. Lavenberg, @cite{Mean-Value Analysis of Closed +Multichain Queuing Networks}, Journal of the ACM, vol. 27, n. 2, April +1980, pp. 313--322. @url{http://doi.acm.org/10.1145/322186.322195} + +@auindex Reiser, M. +@auindex Lavenberg, S. S. + +This implementation is based on G. Bolch, S. Greiner, H. de Meer and +K. Trivedi, @cite{Queueing Networks and Markov Chains: Modeling and +Performance Evaluation with Computer Science Applications}, Wiley, +1998 and Edward D. Lazowska, John Zahorjan, G. Scott Graham, and +Kenneth C. Sevcik, @cite{Quantitative System Performance: Computer +System Analysis Using Queueing Network Models}, Prentice Hall, +1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In +particular, see section 7.4.2.1 ("Exact Solution Techniques"). + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. +@auindex Lazowska, E. D. +@auindex Zahorjan, J. +@auindex Graham, G. S. +@auindex Sevcik, K. C. + +@c +@c Approximate MVA, with Bard-Schweitzer approximation +@c +@DOCSTRING(qnclosedmultimvaapprox) + +@noindent @strong{REFERENCES} + +Y. Bard, @cite{Some Extensions to Multiclass Queueing Network Analysis}, +proc. 4th Int. Symp. on Modelling and Performance Evaluation of +Computer Systems, feb. 1979, pp. 51--62. + +@auindex Bard, Y. + +P. Schweitzer, @cite{Approximate Analysis of Multiclass Closed +Networks of Queues}, Proc. Int. Conf. on Stochastic Control and +Optimization, jun 1979, pp. 25--29. + +@auindex Schweitzer, P. + +This implementation is based on Edward D. Lazowska, John Zahorjan, G. +Scott Graham, and Kenneth C. Sevcik, @cite{Quantitative System +Performance: Computer System Analysis Using Queueing Network Models}, +Prentice Hall, +1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In +particular, see section 7.4.2.2 ("Approximate Solution +Techniques"). This implementation is slightly different from the one +described above, as it computes the average response times @math{R} +instead of the residence times. + +@auindex Lazowska, E. D. +@auindex Zahorjan, J. +@auindex Graham, G. S. +@auindex Sevcik, K. C. + +@subsection Mixed Networks + +@c +@c MVA for mixed networks +@c +@DOCSTRING(qnmix) + +@noindent @strong{REFERENCES} + +Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth C. +Sevcik, @cite{Quantitative System Performance: Computer System +Analysis Using Queueing Network Models}, Prentice Hall, +1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In +particular, see section 7.4.3 ("Mixed Model Solution Techniques"). +Note that in this function we compute the mean response time @math{R} +instead of the mean residence time as in the reference. + +@auindex Lazowska, E. D. +@auindex Zahorjan, J. +@auindex Graham, G. S. +@auindex Sevcik, K. C. + +Herb Schwetman, @cite{Implementing the Mean Value Algorithm for the +Solution of Queueing Network Models}, Technical Report CSD-TR-355, +Department of Computer Sciences, Purdue University, feb 15, 1982, +available at +@url{http://www.cs.purdue.edu/research/technical_reports/1980/TR%2080-355.pdf} + +@auindex Schwetman, H. + + +@node Algorithms for non Product-form QNs +@section Algorithms for non Product-Form QNs + +@c +@c MVABLO algorithm for approximate analysis of closed, single class +@c QN with blocking +@c +@DOCSTRING(qnmvablo) + +@noindent @strong{REFERENCES} + +Ian F. Akyildiz, @cite{Mean Value Analysis for Blocking Queueing +Networks}, IEEE Transactions on Software Engineering, vol. 14, n. 2, +april 1988, pp. 418--428. @url{http://dx.doi.org/10.1109/32.4663} + +@auindex Akyildiz, I. F. + +@DOCSTRING(qnmarkov) + +@c +@c +@c +@node Bounds on performance +@section Bounds on performance + +@c +@DOCSTRING(qnopenab) + +@noindent @strong{REFERENCES} + +Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth +C. Sevcik, @cite{Quantitative System Performance: Computer System +Analysis Using Queueing Network Models}, Prentice Hall, +1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In +particular, see section 5.2 ("Asymptotic Bounds"). + +@auindex Lazowska, E. D. +@auindex Zahorjan, J. +@auindex Graham, G. S. +@auindex Sevcik, K. C. + +@c +@DOCSTRING(qnclosedab) + +@noindent @strong{REFERENCES} + +@noindent Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth +C. Sevcik, @cite{Quantitative System Performance: Computer System +Analysis Using Queueing Network Models}, Prentice Hall, +1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In +particular, see section 5.2 ("Asymptotic Bounds"). + +@auindex Lazowska, E. D. +@auindex Zahorjan, J. +@auindex Graham, G. S. +@auindex Sevcik, K. C. + + +@c +@DOCSTRING(qnopenbsb) + +@noindent @strong{REFERENCES} + +Edward D. Lazowska, John Zahorjan, G. Scott Graham, and Kenneth +C. Sevcik, @cite{Quantitative System Performance: Computer System +Analysis Using Queueing Network Models}, Prentice Hall, +1984. @url{http://www.cs.washington.edu/homes/lazowska/qsp/}. In +particular, see section 5.4 ("Balanced Systems Bounds"). + +@auindex Lazowska, E. D. +@auindex Zahorjan, J. +@auindex Graham, G. S. +@auindex Sevcik, K. C. + +@c +@DOCSTRING(qnclosedbsb) + +@c +@DOCSTRING(qnclosedpb) + +@noindent @strong{REFERENCES} + +The original paper describing PB Bounds is C. H. Hsieh and S. Lam, +@cite{Two classes of performance bounds for closed queueing networks}, +PEVA, vol. 7, n. 1, pp. 3--30, 1987 + +This function implements the non-iterative variant described in G. +Casale, R. R. Muntz, G. Serazzi, @cite{Geometric Bounds: a +Non-Iterative Analysis Technique for Closed Queueing Networks}, IEEE +Transactions on Computers, 57(6):780-794, June 2008. + +@auindex Hsieh, C. H +@auindex Lam, S. +@auindex Casale, G. +@auindex Muntz, R. R. +@auindex Serazzi, G. + +@c +@DOCSTRING(qnclosedgb) + +@noindent @strong{REFERENCES} + +G. Casale, R. R. Muntz, G. Serazzi, +@cite{Geometric Bounds: a Non-Iterative Analysis Technique for Closed +Queueing Networks}, IEEE Transactions on Computers, 57(6):780-794, +June 2008. @url{http://doi.ieeecomputersociety.org/10.1109/TC.2008.37} + +@auindex Casale, G. +@auindex Muntz, R. R. +@auindex Serazzi, G. + +In this implementation we set @math{X^+} and @math{X^-} as the upper +and lower Asymptotic Bounds as computed by the @code{qnclosedab} +function, respectively. + +@node Utility functions +@section Utility functions + +@subsection Open or closed networks + +@DOCSTRING(qnclosed) + +@noindent @strong{EXAMPLE} + +@example +@verbatiminclude @value{top_srcdir}/examples/demo_1_qnclosed.m +@end example + +@DOCSTRING(qnopen) + +@c +@c Compute the visit counts +@c + +@subsection Computation of the visit counts + +For single-class networks the average number of visits satisfy the +following equation: + +@iftex +@tex +$V_j = P_{0 j} + \sum_{i=1}^K V_i P_{i j}$ +@end tex +@end iftex +@ifnottex +@example +V == P0 + V*P; +@end example +@end ifnottex + +@noindent where @math{P_{0 j}} is the probability that an external +arrival goes to service center @math{j}. If @math{\lambda_j} is the +external arrival rate to service center @math{j}, and @math{\lambda = +\sum_j \lambda_j} is the overall external arrival rate, then +@math{P_{0 j} = \lambda_j / \lambda}. + +For closed networks, the visit ratios satisfy the following equation: + +@iftex +@tex +$V_j = \sum_{i=1}^K V_i P_{i j},\ V_1 = 1$ +@end tex +@end iftex +@ifnottex +@example +V(1) == 1 && V == V*P; +@end example +@end ifnottex + +The definitions above can be extended to multiple class networks as +follows. We define the visit ratios @math{V_{sj}} for class @math{s} +customers at service center @math{j} as follows: + +@iftex +@tex +$V_{sj} = \sum_{r=1}^C \sum_{i=1}^K V_{ri} P_{risj},\ V_{s1} = 1$ +@end tex +@end iftex +@ifnottex +@group +V_sj = sum_r sum_i V_ri P_risj, for all s,j +V_s1 = 1, for all s +@end group +@end ifnottex + +@noindent while for open networks: + +@iftex +@tex +$V_{sj} = P_{0sj} + \sum_{r=1}^C \sum_{i=1}^K V_{ri} P_{risj}$ +@end tex +@end iftex +@ifnottex +@group +V_sj = P_0sj + sum_r sum_i V_ri P_risj, for all s,j +@end group +@end ifnottex + +@noindent where @math{P_{0sj}} is the probability that an external +arrival goes to service center @math{j} as a class-@math{s} request. +If @math{\lambda_{sj}} is the external arrival rate of class @math{s} +requests to service center @math{j}, and @math{\lambda = \sum_s \sum_j +\lambda_{sj}} is the overall external arrival rate to the whole system, +then @math{P_{0sj} = \lambda_{sj} / \lambda}. + +@DOCSTRING(qnvisits) + +@noindent @strong{EXAMPLE} + +@example +@verbatiminclude @value{top_srcdir}/examples/demo_1_qnvisits.m +@end example + +@subsection Other utility functions + +@c +@DOCSTRING(population_mix) + +@noindent @strong{REFERENCES} + +Herb Schwetman, @cite{Implementing the Mean Value Algorithm for the +Solution of Queueing Network Models}, Technical Report CSD-TR-355, +Department of Computer Sciences, Purdue University, feb 15, 1982, +available at +@url{http://www.cs.purdue.edu/research/technical_reports/1980/TR +80-355.pdf} + +Note that the slightly different problem of generating all tuples +@math{k_1, k_2, \ldots k_N} such that @math{\sum_i k_i = k} and +@math{k_i} are nonnegative integers, for some fixed integer @math{k +@geq{} 0} has been described in S. Santini, @cite{Computing the +Indices for a Complex Summation}, unpublished report, available at +@url{http://arantxa.ii.uam.es/~ssantini/writing/notes/s668_summation.pdf} + +@auindex Schwetman, H. +@auindex Santini, S. + +@c +@DOCSTRING(qnmvapop) + +@noindent @strong{REFERENCES} + +Zahorjan, J. and Wong, E. @cite{The solution of separable queueing +network models using mean value analysis}. SIGMETRICS +Perform. Eval. Rev. 10, 3 (Sep. 1981), 80-85. DOI +@url{http://doi.acm.org/10.1145/1010629.805477} + +@auindex Zahorjan, J. +@auindex Wong, E. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/singlestation.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,228 @@ +@c -*- texinfo -*- + +@c Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +@c +@c This file is part of the queueing toolbox, a Queueing Networks +@c analysis package for GNU Octave. +@c +@c The queueing toolbox is free software; you can redistribute it +@c and/or modify it under the terms of the GNU General Public License +@c as published by the Free Software Foundation; either version 3 of +@c the License, or (at your option) any later version. +@c +@c The queueing toolbox is distributed in the hope that it will be +@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty +@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with the queueing toolbox; see the file COPYING. If not, see +@c <http://www.gnu.org/licenses/>. + +@node Single Station Queueing Systems +@chapter Single Station Queueing Systems + +Single Station Queueing Systems contain a single station, and are thus +quite easy to analyze. The @code{queueing} package contains functions +for handling the following types of queues: + +@ifnottex +@menu +* The M/M/1 System:: Single-server queueing station. +* The M/M/m System:: Multiple-server queueing station. +* The M/M/inf System:: Infinite-server (delay center) station. +* The M/M/1/K System:: Single-server, finite-capacity queueing station. +* The M/M/m/K System:: Multiple-server, finite-capacity queueing station. +* The Asymmetric M/M/m System:: Asymmetric multiple-server queueing station. +* The M/G/1 System:: Single-server with general service time distribution. +* The M/Hm/1 System:: Single-server with hyperexponential service time distribution. +@end menu +@end ifnottex +@iftex +@itemize + +@item @math{M/M/1} single-server queueing station; + +@item @math{M/M/m} multiple-server queueing station; + +@item Asymmetric @math{M/M/m}; + +@item @math{M/M/\infty} infinite-server station (delay center); + +@item @math{M/M/1/K} single-server, finite-capacity queueing station; + +@item @math{M/M/m/K} multiple-server, finite-capacity queueing station; + +@item @math{M/G/1} single-server with general service time distribution; + +@item @math{M/H_m/1} single-server with hyperexponential service time distribution. + +@end itemize + +@end iftex + +The functions which analyze the queues above can be used as building +blocks for analyzing Queueing Networks. For example, Jackson networks +can be solved by computing the aggregate arrival rates to each node, +and then solving each node in isolation as if it were a single station +queueing system. + +@c +@c M/M/1 +@c +@node The M/M/1 System +@section The @math{M/M/1} System + +The @math{M/M/1} system is made of a single server connected to an +unlimited FCFS queue. The mean arrival rate is Poisson with arrival +rate @math{\lambda}; the service time is exponentially distributed +with average service rate @math{\mu}. The system is stable if +@math{\lambda < \mu}. + +@DOCSTRING(qnmm1) + +@noindent @strong{REFERENCES} + +@noindent G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications}, Wiley, 1998, Section 6.3. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@c +@c M/M/m +@c +@node The M/M/m System +@section The @math{M/M/m} System + +The @math{M/M/m} system is similar to the @math{M/M/1} system, except +that there are @math{m \geq 1} identical servers connected to a single +queue. Thus, at most @math{m} requests can be served at the same +time. The @math{M/M/m} system can be seen as a single server with +load-dependent service rate @math{\mu(n)}, which is a function of the +number @math{n} of nodes in the center: + +@example +@code{mu(n) = min(m,n)*mu} +@end example + +@DOCSTRING(qnmmm) + +@noindent @strong{REFERENCES} + +@noindent G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications}, Wiley, 1998, Section 6.5. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@c +@c M/M/inf +@c +@node The M/M/inf System +@section The @math{M/M/}inf System + +The @math{M/M/\infty} system is similar to the @math{M/M/m} system, +except that there are infinitely many identical servers (that is, +@math{m = \infty}). Each new request is assigned to a new server, so +that queueing never occurs. The @math{M/M/\infty} system is always +stable. + +@DOCSTRING(qnmminf) + +@noindent @strong{REFERENCES} + +@noindent G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications}, Wiley, 1998, Section 6.4. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@c +@c M/M/1/k +@c +@node The M/M/1/K System +@section The @math{M/M/1/K} System + +In a @math{M/M/1/K} finite capacity system there can be at most +@math{k} jobs at any time. If a new request tries to join the system +when there are already @math{K} other requests, the arriving request +is lost. The queue has @math{K-1} slots. The @math{M/M/1/K} system is +always stable, regardless of the arrival and service rates +@math{\lambda} and @math{\mu}. + +@DOCSTRING(qnmm1k) + +@c +@c M/M/m/k +@c +@node The M/M/m/K System +@section The @math{M/M/m/K} System + +The @math{M/M/m/K} finite capacity system is similar to the +@math{M/M/1/k} system except that the number of servers is @math{m}, +where @math{1 \leq m \leq K}. The queue is made of @math{K-m} +slots. The @math{M/M/m/K} system is always stable. + +@DOCSTRING(qnmmmk) + +@noindent @strong{REFERENCES} + +@noindent G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications}, Wiley, 1998, Section 6.6. + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@DOCSTRING(qnmmmk_alt) + +@c +@c Approximate M/M/m +@c +@node The Asymmetric M/M/m System +@section The Asymmetric @math{M/M/m} System + +The Asymmetric @math{M/M/m} system contains @math{m} servers connected +to a single queue. Differently from the @math{M/M/m} system, in the +asymmetric @math{M/M/m} each server may have a different service time. + +@DOCSTRING(qnammm) + +@noindent @strong{REFERENCES} + +@noindent G. Bolch, S. Greiner, H. de Meer and K. Trivedi, @cite{Queueing Networks +and Markov Chains: Modeling and Performance Evaluation with Computer +Science Applications}, Wiley, 1998 + +@auindex Bolch, G. +@auindex Greiner, S. +@auindex de Meer, H. +@auindex Trivedi, K. + +@c +@c +@c +@node The M/G/1 System +@section The @math{M/G/1} System + +@DOCSTRING(qnmg1) + +@c +@c +@c +@node The M/Hm/1 System +@section The @math{M/H_m/1} System +@DOCSTRING(qnmh1) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/doc/summary.txi Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,126 @@ +@c -*- texinfo -*- + +@c Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +@c +@c This file is part of the queueing toolbox, a Queueing Networks +@c analysis package for GNU Octave. +@c +@c The queueing toolbox is free software; you can redistribute it +@c and/or modify it under the terms of the GNU General Public License +@c as published by the Free Software Foundation; either version 3 of +@c the License, or (at your option) any later version. +@c +@c The queueing toolbox is distributed in the hope that it will be +@c useful, but WITHOUT ANY WARRANTY; without even the implied warranty +@c of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@c GNU General Public License for more details. +@c +@c You should have received a copy of the GNU General Public License +@c along with the queueing toolbox; see the file COPYING. If not, see +@c <http://www.gnu.org/licenses/>. + +@node Summary +@chapter Summary + +This document describes the @code{queueing} toolbox for GNU Octave +(@code{queueing} in short). The @code{queueing} toolbox, previously +known as @code{qnetworks}, is a collection of functions written in GNU +Octave for analyzing queueing networks and Markov +chains. Specifically, @code{queueing} contains functions for analyzing +Jackson networks, open, closed or mixed product-form BCMP networks, +and computation of performance bounds. The following algorithms have +been implemented + +@itemize + +@item Convolution for closed, single-class product-form networks +with load-dependent service centers; + +@item Exact and approximate Mean Value Analysis (MVA) for single and +multiple class product-form closed networks; + +@item MVA for mixed, multiple class product-form networks +with load-independent service centers; + +@item Approximate MVA for closed, single-class networks with blocking +(MVABLO algorithm by F. Akyildiz); + +@item Computation of Asymptotic Bounds, Balanced System Bounds +and Geometric Bounds; + +@end itemize + +@noindent @code{queueing} +provides functions for analyzing the following kind of single-station +queueing systems: + +@itemize + +@item @math{M/M/1} +@item @math{M/M/m} +@item @math{M/M/\infty} +@item @math{M/M/1/k} single-server, finite capacity system +@item @math{M/M/m/k} multiple-server, finite capacity system +@item Asymmetric @math{M/M/m} +@item @math{M/G/1} (general service time distribution) +@item @math{M/H_m/1} (Hyperexponential service time distribution) +@end itemize + +Functions for Markov chain analysis are also provided (discrete and +continuous time Markov chains are supported): + +@itemize + +@item Birth-death process; +@item Computation of transient and steady-state occupancy probabilities; +@item Computation of mean time to absorption; +@item Computation of time-averages sojourn time. +@item Computation of mean passage times + +@end itemize + +The @code{queueing} toolbox is distributed under the terms of the GNU +General Public License (GPL), version 3 or later +(@pxref{Copying}). You are encouraged to share this software with +others, and make this package more useful by contributing additional +functions and reporting problems. @xref{Contributing Guidelines}. + +If you use the @code{queueing} toolbox in a technical paper, please +cite it as: + +@quotation +Moreno Marzolla, @emph{The qnetworks Toolbox: A Software Package for +Queueing Networks Analysis}. Khalid Al-Begain, Dieter Fiems and +William J. Knottenbelt, Editors, Proceedings 17th International +Conference on Analytical and Stochastic Modeling Techniques and +Applications (ASMTA 2010) Cardiff, UK, June 14--16, 2010, volume 6148 +of Lecture Notes in Computer Science, Springer, pp. 102--116, ISBN +978-3-642-13567-5 +@end quotation + +If you use BibTeX, this is the citation block: + +@verbatim +@inproceedings{queueing, + author = {Moreno Marzolla}, + title = {The qnetworks Toolbox: A Software Package for Queueing + Networks Analysis}, + booktitle = {Analytical and Stochastic Modeling Techniques and + Applications, 17th International Conference, + ASMTA 2010, Cardiff, UK, June 14-16, 2010. Proceedings}, + editor = {Khalid Al-Begain and Dieter Fiems and William J. Knottenbelt}, + year = {2010}, + publisher = {Springer}, + series = {Lecture Notes in Computer Science}, + volume = {6148}, + pages = {102--116}, + ee = {http://dx.doi.org/10.1007/978-3-642-13568-2_8}, + isbn = {978-3-642-13567-5} +} +@end verbatim + +An early draft of the paper above is available as Technical Report +@uref{http://www.informatica.unibo.it/ricerca/ublcs/2010/UBLCS-2010-04, +UBLCS-2010-04}, February 2010, Department of Computer Science, +University of Bologna, Italy. +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/Makefile Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,18 @@ +DISTFILES=$(wildcard *.m) Makefile + +.PHONY: clean distclean check + +ALL: done + +done: + octave -q grabdemo.m && touch done + +dist: + ln $(DISTFILES) ../`cat ../fname`/examples/ + +clean: + \rm -f demo_*.m *~ done + +distclean: clean + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_ctmc.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,3 @@ + Q = [ -1 1; \ + 1 -1 ]; + q = ctmc(Q) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_ctmc_exps.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,16 @@ + 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)); + tt = linspace(0,10,100); + p0 = zeros(1,N); p0(1)=1; + L = ctmc_exps(Q,tt,p0); + plot( tt, L(:,1), ";State 1;", "linewidth", 2, \ + tt, L(:,2), ";State 2;", "linewidth", 2, \ + tt, L(:,3), ";State 3;", "linewidth", 2, \ + tt, L(:,4), ";State 4 (absorbing);", "linewidth", 2); + legend("location","northwest"); + xlabel("Time"); + ylabel("Expected sojourn time"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_ctmc_fpt.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,5 @@ + Q = [ -1.0 0.9 0.1; \ + 0.1 -1.0 0.9; \ + 0.9 0.1 -1.0 ]; + M = ctmc_fpt(Q) + m = ctmc_fpt(Q,1,3) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_ctmc_mtta.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,5 @@ + mu = 0.01; + death = [ 3 4 5 ] * mu; + Q = diag(death,-1); + Q -= diag(sum(Q,2)); + t = ctmc_mtta(Q,[0 0 0 1]) \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_ctmc_taexps.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,16 @@ + 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-3,50,500); + p = zeros(1,N); p(1)=1; + M = ctmc_taexps(Q,t,p); + 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"); + xlabel("Time"); + ylabel("Time-averaged Expected sojourn time"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_dtmc.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,14 @@ + a = 0.2; + b = 0.15; + P = [ 1-a a; b 1-b]; + T = 0:14; + pp = zeros(2,length(T)); + for i=1:length(T) + pp(:,i) = dtmc(P,T(i),[1 0]); + endfor + ss = dtmc(P); # 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 Step"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_dtmc_fpt.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,4 @@ + P = [ 0.0 0.9 0.1; \ + 0.1 0.0 0.9; \ + 0.9 0.1 0.0 ]; + M = dtmc_fpt(P); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnclosed.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,27 @@ + P = [0 0.3 0.7; 1 0 0; 1 0 0]; # Transition probability matrix + S = [1 0.6 0.2]; # Average service times + m = ones(1,3); # All centers are single-server + Z = 2; # External delay + N = 15; # Maximum population to consider + + V = qnvisits(P); # Compute number of visits from P + D = V .* S; # Compute service demand from S and V + X_bsb_lower = X_bsb_upper = zeros(1,N); + X_ab_lower = X_ab_upper = zeros(1,N); + X_mva = zeros(1,N); + for n=1:N + [X_bsb_lower(n) X_bsb_upper(n)] = qnclosedbsb(n, D, Z); + [X_ab_lower(n) X_ab_upper(n)] = qnclosedab(n, D, Z); + [U R Q X] = qnclosed( n, S, V, m, Z ); + X_mva(n) = X(1)/V(1); + endfor + close all; + plot(1:N, X_ab_lower,"g;Asymptotic Bounds;", \ + 1:N, X_bsb_lower,"k;Balanced System Bounds;", \ + 1:N, X_mva,"b;MVA;", "linewidth", 2, \ + 1:N, X_bsb_upper,"k", \ + 1:N, X_ab_upper,"g" ); + axis([1,N,0,1]); + xlabel("Number of Requests n"); + ylabel("System Throughput X(n)"); + legend("location","southeast"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnclosedmultimva.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,31 @@ + 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] = qnclosedmultimva( 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, "linewidth", 2, \ + b, X2, "linewidth", 2, \ + b, XX, "linewidth", 2 ); + legend("location","south"); + 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"); + xlabel("Population mix \\beta for Class 1"); + ylabel("Resp. Time"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnclosedmultimvaapprox.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,5 @@ + 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] = qnclosedmultimvaapprox(N,S,V,m); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnclosedsinglemva.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,14 @@ + S = [ 0.125 0.3 0.2 ]; + V = [ 16 10 5 ]; + N = 20; + m = ones(1,3); + Z = 4; + [U R Q X] = qnclosedsinglemva(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 ); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnclosedsinglemvaapprox.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,23 @@ + 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] = qnclosedsinglemva(n,S,V,m,Z); + Xmva(n) = X(1)/V(1); + Rmva(n) = dot(R,V); + [U R Q X] = qnclosedsinglemvaapprox(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"); + 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"); + ylabel("Response Time R(n)"); + xlabel("Number of Requests n"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnconvolution.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,13 @@ + k = [1 2 0]; + K = sum(k); # 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] = qnconvolution( K, S, V, m ); + p = [0 0 0]; # initialize p + # Compute the probability to have k(i) jobs at service center i + for i=1:3 + p(i) = (V(i)*S(i))^k(i) / G(K+1) * \ + (G(K-k(i)+1) - V(i)*S(i)*G(K-k(i)) ); + printf("k(%d)=%d prob=%f\n", i, k(i), p(i) ); + endfor \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnmmm.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,13 @@ + disp("This is figure 6.4 on p. 220 Bolch et al."); + rho = 0.9; + ntics = 21; + lambda = 0.9; + m = linspace(1,ntics,ntics); + mu = lambda./(rho .* m); + [U R Q X] = qnmmm(lambda, mu, m); + qlen = X.*(R-1./mu); + plot(m,Q,"o",qlen,"*"); + axis([0,ntics,0,25]); + legend("Jobs in the system","Queue Length","location","northwest"); + xlabel("Number of servers (m)"); + title("\lambda = 0.9, \mu = 0.9"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnopensingle.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,6 @@ + lambda = 3; + V = [16 7 8]; + S = [0.01 0.02 0.03]; + [U R Q X] = qnopensingle( lambda, S, V ); + R_s = dot(R,V) # System response time + N = sum(Q) # Average number in system \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnsolve.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,7 @@ + QQ = { qnmknode( "m/m/m-fcfs", [0.2 0.1 0.1; 0.2 0.1 0.1] ), \ + qnmknode( "-/g/1-ps", [0.4; 0.6] ), \ + qnmknode( "-/g/inf", [1; 2] ) }; + V = [ 1 0.6 0.4; \ + 1 0.3 0.7 ]; + N = [ 2 1 ]; + [U R Q X] = qnsolve( "closed", N, QQ, V ); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_1_qnvisits.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,9 @@ + P = [ 0 0.4 0.6 0; \ + 0.2 0 0.2 0.6; \ + 0 0 0 1; \ + 0 0 0 0 ]; + lambda = [0.1 0 0 0.3]; + V = qnvisits(P,lambda); + S = [2 1 2 1.8]; + m = [3 1 1 2]; + [U R Q X] = qnopensingle( sum(lambda), S, V, m ); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_2_ctmc.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,14 @@ + 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"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_2_ctmc_mtta.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,13 @@ + 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) = ctmc_mtta(Q,p); + endfor + plot(initial_state,t,"+"); + xlabel("Initial state"); + ylabel("MTTA"); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_2_ctmc_taexps.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,34 @@ + 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(1e-5,1*day,101); + PP = ctmc_taexps(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 + semilogy(TT,A,";Steady-state;", \ + TT,At,";Instantaneous;", \ + TT,Abart,";Interval base;"); + ax = axis(); + ax(3) = 1-1e-5; + axis(ax); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/demo_3_ctmc.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,26 @@ + sec = 1; + min = 60*sec; + hour = 60*min; + day = 24*hour; + year = 365*day; + # 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); + A = p(1) + p(4); + printf("System availability %9.2f min/year\n",A*year/min); + printf("Mean time in RB state %9.2f min/year\n",p(3)*year/min); + printf("Mean time in RC state %9.2f min/year\n",p(2)*year/min); + printf("Mean time in 0 state %9.2f min/year\n",p(5)*year/min); + Q(3,:) = Q(5,:) = 0; # make states 3 and 5 absorbing + p0 = [1 0 0 0 0]; + MTBF = ctmc_mtta(Q, p0) / hour; + printf("System MTBF %.2f hours\n",MTBF); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/examples/grabdemo.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,76 @@ +## Copyright (C) 2005, 2006, 2007 David Bateman +## Modifications Copyright (C) 2009 Moreno Marzolla +## +## This file is part of qnetworks. It is based on the fntests.m +## script included in GNU Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +clear all; + +global fundirs; + +if (nargin == 1) + xdir = argv(){1}; +else + xdir = "../inst/"; +endif + +srcdir = canonicalize_file_name (xdir); +fundirs = {srcdir}; + +function print_file_name (nm) + filler = repmat (".", 1, 55-length (nm)); + printf (" %s %s", nm, filler); +endfunction + +function y = hasdemo (f) + fid = fopen (f); + str = fscanf (fid, "%s"); + fclose (fid); + y = findstr (str, "%!demo"); +endfunction + +function dump_demo( fname, code, idx ) + if ( !idx) + return; + endif + printf("%d demos found\n", length(idx)-1 ); + for i=2:length(idx) + demoname = [ "demo_" num2str(i-1) "_" fname ]; + fid = fopen( demoname, "wt" ); + fprintf(fid,"%s",code(idx(i-1)+1:idx(i)-1)); + fclose(fid); + endfor +endfunction + +for j=1:length(fundirs) + d = fundirs{j}; + lst = dir (d); + for i = 1:length (lst) + nm = lst(i).name; + if ((length (nm) > 3 && strcmp (nm((end-2):end), ".cc")) + || (length (nm) > 2 && strcmp (nm((end-1):end), ".m"))) + f = fullfile (d, nm); + ## Only run if it contains %!demo + if (hasdemo (f)) + tmp = strrep (f, [srcdir, "/"], ""); + print_file_name (tmp); + [code, idx] = test (f, "grabdemo" ); + dump_demo( nm, code, idx ); + endif + endif + endfor +endfor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/Makefile Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,12 @@ +.PHONY: clean check dist +DISTFILES=$(wildcard *.m) Makefile + +ALL: + +clean: + \rm -f *~ fntests.log + +distclean: clean + +dist: + ln $(DISTFILES) ../`cat ../fname`/inst/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/ctmc.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,281 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{p} =} ctmc (@var{Q}) +## @deftypefnx {Function File} {@var{p} =} ctmc (@var{Q}, @var{t}. @var{q0}) +## +## @cindex Markov chain, continuous time +## @cindex Continuous time Markov chain +## @cindex Markov chain, state occupancy probabilities +## @cindex Stationary probabilities +## +## With a single argument, compute the stationary state occupancy +## probability vector @var{p}(1), @dots{}, @var{p}(N) for a +## Continuous-Time Markov Chain with infinitesimal generator matrix +## @var{Q} of size @math{N \times N}. With three arguments, compute the +## state occupancy probabilities @var{p}(1), @dots{}, @var{p}(N) at time +## @var{t}, given initial state occupancy probabilities @var{p0} at time +## 0. +## +## @strong{INPUTS} +## +## @table @var +## +## @item Q +## Infinitesimal generator matrix. @var{Q} is a @math{N \times N} square +## matrix where @code{@var{Q}(i,j)} is the transition rate from state +## @math{i} to state @math{j}, for @math{1 @leq{} i \neq j @leq{} N}. +## Transition rates must be nonnegative, and @math{\sum_{j=1}^N Q_{i j} = 0} +## +## @item t +## Time at which to compute the transient probability +## +## @item p0 +## @code{@var{p0}(i)} is the probability that the system +## is in state @math{i} at time 0 . +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item p +## If this function is invoked with a single argument, +## @code{@var{p}(i)} is the steady-state probability that the system is +## in state @math{i}, @math{i = 1, @dots{}, N}. The vector @var{p} +## satisfies the equation @math{p{\bf Q} = 0} and @math{\sum_{i=1}^N p_i = 1}. +## If this function is invoked with three arguments, @code{@var{p}(i)} +## is the probability that the system is in state @math{i} at time @var{t}, +## given the initial occupancy probabilities @var{q0}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function q = ctmc( Q, t, q0 ) + + persistent epsilon = 10*eps; + + if ( nargin < 1 || nargin > 3 ) + print_usage(); + endif + + issquare(Q) || \ + usage( "Q must be a square matrix" ); + + N = rows(Q); + + ( norm( sum(Q,2), "inf" ) < epsilon ) || \ + usage( "Q is not an infinitesimal generator matrix" ); + + if ( nargin > 1 ) + ( isscalar(t) && t>=0 ) || \ + usage("t must be nonnegative"); + endif + + if ( nargin > 2 ) + ( isvector(q0) && length(q0) == N && all(q0>=0) && abs(sum(q0)-1.0)<epsilon ) || \ + usage( "q0 must be a probability vector" ); + q0 = q0(:)'; # make q0 a row vector + else + q0 = ones(1,N) / N; + endif + + if ( nargin == 1 ) + q = __ctmc_steady_state( Q ); + else + q = __ctmc_transient(Q, t, q0 ); + endif + +endfunction + +## Helper function, compute steady state probability +function q = __ctmc_steady_state( Q ) + persistent epsilon = 10*eps; + N = rows(Q); + + ## non zero columns + nonzero=find( any(abs(Q)>epsilon,1 ) ); + if ( length(nonzero) == 0 ) + error( "Q is the zero matrix" ); + endif + + normcol = nonzero(1); # normalization condition column + + ## force probability of unvisited states to zero + for i=find( all(abs(Q)<epsilon,1) ) + Q(i,i) = 1; + endfor + + ## assert( rank(Q) == N-1 ); + + Q(:,normcol) = 1; # add normalization condition + b = zeros(1,N); b(normcol)=1; + q = b/Q; # qQ = b; +endfunction + +## Helper function, compute transient probability +function q = __ctmc_transient( Q, t, q0 ) + q = q0*expm(Q*t); +endfunction + +%!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 failure patterns +%!test +%! fail( "ctmc([1 1; 1 1])", "infinitesimal" ); +%! fail( "ctmc([1 1 1; 1 1 1])", "square" ); + +## test unvisited state. +%!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 ); + +## Example 3.1 p. 123 Bolch et al. +%!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 ); + +## Example 3.4 p. 138 Bolch et al. +%!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 ); + +## Example 3.2 p. 128 Bolch et al. +%!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 ); + +%!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"); + +## This example is from: David I. Heimann, Nitin Mittal, Kishor S. Trivedi, +## "Availability and Reliability Modeling for Computer Systems", sep 1989, +## section 2.4. +## **NOTE** the value of \pi_0 reported in the paper appears to be wrong +## (it is written as 0.00000012779, but probably should be 0.0000012779). +%!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 = ctmc_mtta(Q, p0) / hour; +%! assert( fix(MTBF), 24857); + +## This example is from: David I. Heimann, Nitin Mittal, Kishor S. Trivedi, +## "Availability and Reliability Modeling for Computer Systems", sep 1989, +## section 2.5 +%!demo +%! sec = 1; +%! min = 60*sec; +%! hour = 60*min; +%! day = 24*hour; +%! year = 365*day; +%! # 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); +%! A = p(1) + p(4); +%! printf("System availability %9.2f min/year\n",A*year/min); +%! printf("Mean time in RB state %9.2f min/year\n",p(3)*year/min); +%! printf("Mean time in RC state %9.2f min/year\n",p(2)*year/min); +%! printf("Mean time in 0 state %9.2f min/year\n",p(5)*year/min); +%! Q(3,:) = Q(5,:) = 0; # make states 3 and 5 absorbing +%! p0 = [1 0 0 0 0]; +%! MTBF = ctmc_mtta(Q, p0) / hour; +%! printf("System MTBF %.2f hours\n",MTBF); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/ctmc_bd.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,85 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{p} =} ctmc_bd (@var{birth}, @var{death}) +## +## @cindex Markov chain, continuous time +## @cindex Birth-death process +## +## Compute the steady-state solution of a birth-death process with state +## space @math{(1, @dots{}, N)}. +## +## @strong{INPUTS} +## +## @table @var +## +## @item birth +## Vector with @math{N-1} elements, where @code{@var{birth}(i)} is the +## transition rate from state @math{i} to state @math{i+1}. +## +## @item death +## Vector with @math{N-1} elements, where @code{@var{death}(i)} is the +## transition rate from state @math{i+1} to state @math{i}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item p +## @code{@var{p}(i)} is the steady-state probability that the system is +## in state @math{i}, @math{i=1, @dots{}, N}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function p = ctmc_bd( birth, death ) + + if ( nargin != 2 ) + print_usage(); + endif + + ( isvector( birth ) && isvector( death ) ) || \ + usage( "birth and death must be vectors" ); + birth = birth(:); # make birth a column vector + death = death(:); # make death a column vector + size_equal( birth, death ) || \ + usage( "birth and death must have the same length" ); + all( birth >= 0 ) || \ + usage( "birth must be >= 0" ); + all( death >= 0 ) || \ + usage( "death must be >= 0" ); + + n = length(birth) + 1; # number of states + + ## builds the transition probability matrix + Q = diag( birth, 1 ) + diag( death, -1 ); + Q -= diag( sum(Q,2) ); + p = ctmc( Q ); +endfunction +%!test +%! birth = [ 1 1 1 ]; +%! death = [ 2 2 2 ]; +%! result = ctmc_bd( birth, death ); +%! assert( result, [ 8/15 4/15 2/15 1/15 ], 1e-5 );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/ctmc_bd_solve.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,35 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{p} =} ctmc_bd_solve (@var{birth}, @var{death}) +## +## This function is deprecated and will be removed from future versions +## of the @code{queueing} toolbox. Please use @code{ctmc_bd()} instead. +## +## @seealso{ctmc_bd} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function p = ctmc_bd_solve( birth, death ) + warning("Function ctmc_db_solve() is deprecated and will be removed in the future. Please use ctmc_bd() instead."); + p = ctmc_bd(birth, death); +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/ctmc_exps.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,108 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{L} =} ctmc_exps (@var{Q}, @var{tt}, @var{p}) +## +## @cindex Markov chain, continuous time +## @cindex Expected sojourn time +## +## Compute the expected total time @code{@var{L}(t,j)} spent in state +## @math{j} during the time interval @code{[0,@var{tt}(t))}, assuming +## that at time 0 the state occupancy probability was @var{p}. +## +## @strong{INPUTS} +## +## @table @var +## +## @item Q +## Infinitesimal generator matrix. @code{@var{Q}(i,j)} is the transition +## rate from state @math{i} to state @math{j}, +## @math{1 @leq{} i \neq j @leq{} N}. The matrix @var{Q} must also satisfy the +## condition @code{sum(@var{Q},2) == 0} +## +## @item tt +## This parameter is a vector used for numerical integration. The first +## element @code{@var{tt}(1)} must be 0, and the last element +## @code{@var{tt}(end)} must be the upper bound of the interval +## @math{[0,t)} of interest (@code{@var{tt}(end) == @math{t}}). +## +## @item p +## @code{@var{p}(i)} is the probability that at time 0 the system was in +## state @math{i}, for all @math{i = 1, @dots{}, N} +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item L +## @code{@var{L}(t,j)} is the expected time spent in state @math{j} +## during the interval @code{[0,@var{tt}(t))}. @code{1 @leq{} @var{t} @leq{} length(@var{tt})} +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function L = ctmc_exps( Q, tt, p ) + + persistent epsilon = 10*eps; + + if ( nargin != 3 ) + print_usage(); + endif + + issquare(Q) || \ + usage( "Q must be a square matrix" ); + + ( norm( sum(Q,2), "inf" ) < epsilon ) || \ + error( "Q is not an infinitesimal generator matrix" ); + + ( isvector(p) && length(p) == size(Q,1) && all(p>=0) && abs(sum(p)-1.0)<epsilon ) || \ + usage( "p must be a probability vector" ); + + ( isvector(tt) && abs(tt(1)) < epsilon ) || \ + usage( "tt must be a vector, and tt(1) must be 0.0" ); + tt = tt(:)'; # make tt a row vector + p = p(:)'; # make p a row vector + ff = @(x,t) (x(:)'*Q+p); + fj = @(x,t) (Q); + L = lsode( {ff, fj}, p, tt ); +endfunction + +%!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)); +%! tt = linspace(0,10,100); +%! p0 = zeros(1,N); p0(1)=1; +%! L = ctmc_exps(Q,tt,p0); +%! plot( tt, L(:,1), ";State 1;", "linewidth", 2, \ +%! tt, L(:,2), ";State 2;", "linewidth", 2, \ +%! tt, L(:,3), ";State 3;", "linewidth", 2, \ +%! tt, L(:,4), ";State 4 (absorbing);", "linewidth", 2); +%! legend("location","northwest"); +%! xlabel("Time"); +%! ylabel("Expected sojourn time");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/ctmc_fpt.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,128 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{M} =} ctmc_fpt (@var{Q}) +## @deftypefnx {Function File} {@var{m} =} ctmc_fpt (@var{Q}, @var{i}, @var{j}) +## +## @cindex Markov chain, continuous time +## @cindex First passage times +## +## If called with a single argument, computes the mean first passage +## times @code{@var{M}(i,j)}, the average times before state @var{j} is +## reached, starting from state @var{i}, for all @math{1 \leq i, j \leq +## N}. If called with three arguments, returns the single value +## @code{@var{m} = @var{M}(i,j)}. +## +## @strong{INPUTS} +## +## @table @var +## +## @item Q +## Infinitesimal generator matrix. @var{Q} is a @math{N \times N} square +## matrix where @code{@var{Q}(i,j)} is the transition rate from state +## @math{i} to state @math{j}, for @math{1 @leq{} i \neq j @leq{} N}. +## Transition rates must be nonnegative, and @math{\sum_{j=1}^N Q_{i j} = 0} +## +## @item i +## Initial state. +## +## @item j +## Destination state. If @var{j} is a vector, returns the mean first passage +## time to any state in @var{j}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item M +## If this function is called with a single argument, the result +## @code{@var{M}(i,j)} is the average time before state +## @var{j} is visited for the first time, starting from state @var{i}. +## +## @item m +## If this function is called with three arguments, the result +## @var{m} is the average time before state @var{j} is visited for the first +## time, starting from state @var{i}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function result = ctmc_fpt( Q, i, j ) + + persistent epsilon = 10*eps; + + if ( nargin != 1 && nargin != 3 ) + print_usage(); + endif + + issquare(Q) || \ + usage( "Q must be a square matrix" ); + + N = rows(Q); + + ( norm( sum(Q,2), "inf" ) < epsilon ) || \ + usage( "Q is not an infinitesimal generator matrix" ); + + if ( nargin == 1 ) + M = zeros(N,N); + for j=1:N + QQ = Q; + QQ(j,:) = 0; # make state j absorbing + for i=1:N + p0 = zeros(1,N); p0(i) = 1; + M(i,j) = ctmc_mtta(QQ,p0); + endfor + endfor + result = M; + else + (isscalar(i) && i>=1 && j<=N) || usage("i must be an integer in the range 1..%d", N); + (isvector(j) && all(j>=1) && all(j<=N)) || usage("j must be an integer or vector with elements in 1..%d", N); + j = j(:)'; # make j a row vector + Q(j,:) = 0; # make state(s) j absorbing + p0 = zeros(1,N); p0(i) = 1; + result = ctmc_mtta(Q,p0); + endif +endfunction +%!demo +%! Q = [ -1.0 0.9 0.1; \ +%! 0.1 -1.0 0.9; \ +%! 0.9 0.1 -1.0 ]; +%! M = ctmc_fpt(Q) +%! m = ctmc_fpt(Q,1,3) + +%!test +%! Q = unifrnd(0.1,0.9,10,10); +%! Q -= diag(sum(Q,2)); +%! M = ctmc_fpt(Q); + +%!test +%! Q = unifrnd(0.1,0.9,10,10); +%! Q -= diag(sum(Q,2)); +%! m = ctmc_fpt(Q,1,3); + +%!test +%! Q = unifrnd(0.1,0.9,10,10); +%! Q -= diag(sum(Q,2)); +%! m = ctmc_fpt(Q,1,[3 5 6]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/ctmc_mtta.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,140 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{t} =} ctmc_mtta (@var{Q}, @var{p}) +## +## @cindex Markov chain, continuous time +## @cindex Mean time to absorption +## +## Compute the Mean-Time to Absorption (MTTA) starting from initial +## occupancy probability @var{p} at time 0. If there are no absorbing +## states, this function fails with an error. +## +## @strong{INPUTS} +## +## @table @var +## +## @item Q +## @math{N \times N} infinitesimal generator matrix. @code{@var{Q}(i,j)} +## is the transition rate from state @math{i} to state @math{j}, @math{i +## \neq j}. The matrix @var{Q} must satisfy the condition +## @math{\sum_{j=1}^N Q_{i j} = 0} +## +## @item p +## @code{@var{p}(i)} is the probability that the system is in state @math{i} +## at time 0, for each @math{i=1, @dots{}, N} +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item t +## Mean time to absorption of the process represented by matrix @var{Q}. +## If there are no absorbing states, this function fails. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function t = ctmc_mtta( Q, p ) + + persistent epsilon = 10*eps; + + if ( nargin != 2 ) + print_usage(); + endif + + issquare(Q) || \ + usage( "Q must be a square matrix" ); + + N = rows(Q); + + all( abs( sum(Q,2) ) < epsilon ) || \ + usage( "Q is not an infinitesimal generator matrix" ); + + ( isvector(p) && length(p) == N && all(p>=0) && abs(sum(p)-1.0)<epsilon ) || \ + usage( "p must be a probability vector" ); + + ## Find nonzero rows. Nonzero rows correspond to transient states, + ## while zero rows are absorbing states. If there are no zero rows, + ## then the Markov chain does not contain absorbing states and we + ## raise an error + nzrows = find( any( abs(Q) > epsilon, 2 ) ); + if ( length( nzrows ) == N ) + error( "There are no absorbing states" ); + endif + + QN = Q(nzrows,nzrows); + pN = p(nzrows); + L = -pN*inv(QN); + t = sum(L); +endfunction +%!test +%! Q = [0 1 0; 1 0 1; 0 1 0 ]; Q -= diag( sum(Q,2) ); +%! fail( "ctmc_mtta(Q,[1 0 0])", "no absorbing"); + +%!test +%! Q = [0 1 0; 1 0 1; 0 0 0; 0 0 0 ]; +%! fail( "ctmc_mtta(Q,[1 0 0])", "square matrix"); + +%!test +%! Q = [0 1 0; 1 0 1; 0 0 0 ]; +%! fail( "ctmc_mtta(Q,[1 0 0])", "not an 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( ctmc_mtta( Q,[0 0 0 1] ), 0 ); # state 4 is absorbing + +%!test +%! Q = [-1 1; 0 0]; +%! assert( ctmc_mtta( Q, [0 1] ), 0 ); # state 2 is absorbing +%! assert( ctmc_mtta( Q, [1 0] ), 1 ); # the result has been computed by hand + +## Compute the MTTA of a pure death process with 4 states +## (state 1 is absorbing). State 4 is the initial state. +%!demo +%! mu = 0.01; +%! death = [ 3 4 5 ] * mu; +%! Q = diag(death,-1); +%! Q -= diag(sum(Q,2)); +%! t = ctmc_mtta(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) = ctmc_mtta(Q,p); +%! endfor +%! plot(initial_state,t,"+"); +%! xlabel("Initial state"); +%! ylabel("MTTA");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/ctmc_solve.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,35 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{q} =} ctmc_solve (@var{Q}) +## +## This function is deprecated and will be removed from future versions +## of the @code{queueing} toolbox. Please use @code{ctmc()} instead. +## +## @seealso{ctmc} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function q = ctmc_solve( Q ) + warning("Function ctmc_solve() is deprecated and will be removed in the future. Please use ctmc() instead."); + q = ctmc(Q); +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/ctmc_taexps.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,152 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{M} =} ctmc_taexps (@var{Q}, @var{tt}, @var{p}) +## +## @cindex Markov chain, continuous time +## @cindex Time-alveraged sojourn time +## +## Compute the @emph{time-averaged sojourn time} @code{@var{M}(t,j)}, +## defined as the fraction of the time interval @code{[0,@var{tt}(t))} spent in +## state @math{j}, assuming that at time 0 the state occupancy +## probability was @var{p}. +## +## @strong{INPUTS} +## +## @table @var +## +## @item Q +## Infinitesimal generator matrix. @code{@var{Q}(i,j)} is the transition +## rate from state @math{i} to state @math{j}, +## @math{1 @leq{} i \neq j @leq{} N}. The +## matrix @var{Q} must also satisfy the condition @code{sum(@var{Q},2) == 0} +## +## @item tt +## This parameter is a vector used for numerical integration of the +## sujourn time. The first element @code{@var{tt}(1)} must be slightly +## larger than 0, and the +## last element @code{@var{tt}(end)} must be the upper limit of the +## interval @math{[0,t)} of interest (@code{@var{tt}(end) == @math{t}}). +## This vector is used by the ODE solver to compute the solution +## @var{M}. +## +## @item p +## @code{@var{p}(i)} is the probability that, at time 0, the system was in +## state @math{i}, for all @math{i = 1, @dots{}, N} +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item M +## @code{@var{M}(t,j)} is the expected fraction of time spent in state +## @math{j} during the interval @math{[0,tt(t))} assuming that the state +## occupancy probability at time zero was @var{p}. @code{1 @leq{} +## @var{t} @leq{} length(@var{tt})} +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function M = ctmc_taexps( Q, t, p ) + + persistent epsilon = 10*eps; + + if ( nargin != 3 ) + print_usage(); + endif + + issquare(Q) || \ + usage( "Q must be a square matrix" ); + + N = rows(Q); + + ( norm( sum(Q,2), "inf" ) < epsilon ) || \ + usage( "Q is not an infinitesimal generator matrix" ); + + ( isvector(p) && length(p) == N && all(p>=0) && abs(sum(p)-1.0)<epsilon ) || \ + usage( "p must be a probability vector" ); + t = t(:)'; # make t a row vector + p = p(:)'; # make p a row vector + ff = @(x,t) (((x')*(Q-eye(N)/t).+p/t)'); + fj = @(x,t) (Q-eye(N)/t); + M = lsode( {ff, fj}, zeros(size(p)), t ); +endfunction + +%!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-3,50,500); +%! p = zeros(1,N); p(1)=1; +%! M = ctmc_taexps(Q,t,p); +%! 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"); +%! xlabel("Time"); +%! ylabel("Time-averaged Expected sojourn time"); + +## This example is from: David I. Heimann, Nitin Mittal, Kishor S. Trivedi, +## "Availability and Reliability Modeling for Computer Systems", sep 1989, +## section 2.5 +%!demo +%! sec = 1; +%! min = sec*60; +%! hour = 60*min; +%! day = 24*hour; +%! +%! # state space enumeration {2, RC, RB, 1, 0} +%! a = 1/(10*min); # 1/a = duration of reboot (10 min) +%! b = 1/(30*sec); # 1/b = reconfiguration time (30 sec) +%! g = 1/(5000*hour); # 1/g = processor MTTF (5000 hours) +%! d = 1/(4*hour); # 1/d = processor MTTR (4 hours) +%! c = 0.9; # coverage +%! Q = [ -2*g 2*c*g 2*(1-c)*g 0 0; \ +%! 0 -b 0 b 0; \ +%! 0 0 -a a 0; \ +%! d 0 0 -(g+d) g; \ +%! 0 0 0 d -d]; +%! p = ctmc(Q); +%! printf("System availability: %f\n",p(1)+p(4)); +%! TT = linspace(1e-5,1*day,101); +%! PP = ctmc_taexps(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 +%! semilogy(TT,A,";Steady-state;", \ +%! TT,At,";Instantaneous;", \ +%! TT,Abart,";Interval base;"); +%! ax = axis(); +%! ax(3) = 1-1e-5; +%! axis(ax);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/dtmc.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,159 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{p} =} dtmc (@var{P}) +## @deftypefnx {Function File} {@var{p} =} dtmc (@var{P}, @var{n}, @var{p0}) +## +## @cindex Markov chain, discrete time +## @cindex Discrete time Markov chain +## @cindex Markov chain, stationary probabilities +## @cindex Stationary probabilities +## +## With a single argument, compute the steady-state probability vector +## @code{@var{p}(1), @dots{}, @var{p}(N)} for a +## Discrete-Time Markov Chain given the @math{N \times N} transition +## probability matrix @var{P}. With three arguments, compute the +## probability vector @code{@var{p}(1), @dots{}, @var{p}(N)} +## after @var{n} steps, given initial probability vector @var{p0} at +## time 0. +## +## @strong{INPUTS} +## +## @table @var +## +## @item P +## @code{@var{P}(i,j)} is the transition probability from state @math{i} +## to state @math{j}. @var{P} must be an irreducible stochastic matrix, +## which means that the sum of each row must be 1 (@math{\sum_{j=1}^N P_{i j} = 1}), and the rank of +## @var{P} must be equal to its dimension. +## +## @item n +## Step at which to compute the transient probability +## +## @item p0 +## @code{@var{p0}(i)} is the probability that at step 0 the system +## is in state @math{i}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item p +## If this function is invoked with a single argument, +## @code{@var{p}(i)} is the steady-state probability that the system is +## in state @math{i}. @var{p} satisfies the equations @math{p = p{\bf P}} and @math{\sum_{i=1}^N p_i = 1}. If this function is invoked +## with three arguments, @code{@var{p}(i)} is the marginal probability +## that the system is in state @math{i} at step @var{n}, +## given the initial probabilities @code{@var{p0}(i)} that the initial state is +## @math{i}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function q = dtmc( P, n, p0 ) + + persistent epsilon = 10*eps; + + if ( nargin < 1 || nargin > 3 ) + print_usage(); + endif + + N = dtmc_check_P(P); + + if ( nargin > 1 ) + ( isscalar(n) && n>=0 ) || \ + usage( "n must be >=0" ); + endif + + if ( nargin > 2 ) + ( isvector(p0) && length(p0) == N && all(p0>=0) && abs(sum(p0)-1.0)<epsilon ) || \ + usage( "p0 must be a probability vector" ); + p0 = p0(:)'; # make q0 a row vector + else + p0 = ones(1,N) / N; + endif + + if ( nargin == 1 ) + q = __dtmc_steady_state( P ); + else + q = __dtmc_transient(P, n, p0); + endif +endfunction + +## Helper function, compute steady-state probability +function q = __dtmc_steady_state( P ) + N = rows(P); + A = P-eye(N); + A(:,N) = 1; # add normalization condition + rank( A ) == N || \ + warning( "dtmc(): P is reducible" ); + + b = [ zeros(1,N-1) 1 ]; + q = b/A; +endfunction + +## Helper function, compute transient probability +function q = __dtmc_transient( P, n, p0 ) + q = p0*P^n; +endfunction + +%!test +%! P = [0.75 0.25; 0.5 0.5]; +%! q = dtmc(P); +%! assert( q*P, q, 1e-5 ); +%! assert( q, [0.6666 0.3333], 1e-4 ); + +%!test +%! #Example 2.11 p. 44 Bolch et al. +%! P = [0.5 0.5; 0.5 0.5]; +%! q = dtmc(P); +%! assert( q, [0.5 0.5], 1e-3 ); + +%!test +%! fail("dtmc( [1 1 1; 1 1 1] )", "square"); + +%!test +%! a = 0.2; +%! b = 0.8; +%! P = [1-a a; b 1-b]; +%! plim = dtmc(P); +%! p = dtmc(P, 100, [1 0]); +%! assert( plim, p, 1e-5 ); + +%!demo +%! a = 0.2; +%! b = 0.15; +%! P = [ 1-a a; b 1-b]; +%! T = 0:14; +%! pp = zeros(2,length(T)); +%! for i=1:length(T) +%! pp(:,i) = dtmc(P,T(i),[1 0]); +%! endfor +%! ss = dtmc(P); # 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 Step");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/dtmc_check_P.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,56 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{result} =} dtmc_check_P (@var{P}) +## +## @cindex Markov chain, discrete time +## +## Returns the size (number of rows or columns) of square matrix +## @var{P}, if and only if @var{P} is a valid transition probability +## matrix. This means that (i) all elements of @var{P} must be nonnegative, +## and (ii) the sum of each row must be 1.0. +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function result = dtmc_check_P( P ) + + persistent epsilon = 10*eps; + + if ( nargin != 1 ) + print_usage(); + endif + + issquare(P) || \ + usage( "P must be a square matrix" ); + + ( all(all(P >= 0) ) && norm( sum(P,2) - 1, "inf" ) < epsilon ) || \ + error( "P is not a stochastic matrix" ); + + result = rows(P); +endfunction +%!test +%! fail("dtmc_check_P( [1 1 1; 1 1 1] )", "square"); +%! fail("dtmc_check_P( [1 0 0; 0 0.5 0; 0 0 0] )", "stochastic" ); + +%!test +%! P = [0 1; 1 0]; +%! assert( dtmc_check_P(P), 2 ); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/dtmc_fpt.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,150 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{M} =} dtmc_fpt (@var{P}) +## @deftypefnx {Function File} {@var{m} =} dtmc_fpt (@var{P}, @var{i}, @var{j}) +## +## @cindex Markov chain, discrete time +## @cindex First passage times +## +## If called with a single argument, computes the mean first passage +## times @code{@var{M}(i,j)}, that are the average number of transitions before +## state @var{j} is reached, starting from state @var{i}, for all +## @math{1 \leq i, j \leq N}. If called with three arguments, returns +## the single value @code{@var{m} = @var{M}(i,j)}. +## +## @strong{INPUTS} +## +## @table @var +## +## @item P +## @code{@var{P}(i,j)} is the transition probability from state @math{i} +## to state @math{j}. @var{P} must be an irreducible stochastic matrix, +## which means that the sum of each row must be 1 (@math{\sum_{j=1}^N +## P_{i j} = 1}), and the rank of @var{P} must be equal to its +## dimension. +## +## @item i +## Initial state. +## +## @item j +## Destination state. If @var{j} is a vector, returns the mean first passage +## time to any state in @var{j}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item M +## If this function is called with a single argument, the result +## @code{@var{M}(i,j)} is the average number of transitions before state +## @var{j} is reached for the first time, starting from state @var{i}. +## +## @item m +## If this function is called with three arguments, the result @var{m} +## is the average number of transitions before state @var{j} is visited +## for the first time, starting from state @var{i}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function result = dtmc_fpt( P, i, j ) + persistent epsilon = 10*eps; + + if ( nargin != 1 && nargin != 3) + print_usage(); + endif + + issquare(P) || \ + usage( "P must be a square matrix" ); + + N = rows(P); + + ( all(P >= 0 ) && norm( sum(P,2) - 1, "inf" ) < epsilon ) || \ + usage( "P is not a stochastic matrix" ); + + if ( nargin == 1 ) + M = zeros(N,N); + ## M(i,j) = 1 + sum_{k \neq j} P(i,k) M(k,j) + b = ones(N,1); + for j=1:N + A = -P; + A(:,j) = 0; + A += eye(N,N); + res = A \ b; + M(:,j) = res'; + endfor + result = M; + else + (isscalar(i) && i>=1 && j<=N) || usage("i must be an integer in the range [1,%d]", N); + (isvector(j) && all(j>=1) && all(j<=N)) || usage("j must be an integer or vector with elements in 1..%d", N); + j = j(:)'; # make j a row vector + b = ones(N,1); + A = -P; + A(:,j) = 0; + A += eye(N,N); + res = A \ b; + result = res(i); + endif +endfunction +%!demo +%! P = [ 0.0 0.9 0.1; \ +%! 0.1 0.0 0.9; \ +%! 0.9 0.1 0.0 ]; +%! M = dtmc_fpt(P); + +%!test +%! P = [ 0.0 0.9 0.1; \ +%! 0.1 0.0 0.9; \ +%! 0.9 0.1 0.0 ]; +%! p = dtmc(P); +%! M = dtmc_fpt(P); +%! assert( diag(M)', 1./p, 1e-8 ); + +%!test +%! P = [ 0.0 0.9 0.1; \ +%! 0.1 0.0 0.9; \ +%! 0.9 0.1 0.0 ]; +%! p = dtmc(P); +%! m = dtmc_fpt(P, 1, 1); +%! assert( m, 1/p(1), 1e-8 ); + +%!test +%! P = [ 0.0 0.9 0.1; \ +%! 0.1 0.0 0.9; \ +%! 0.9 0.1 0.0 ]; +%! m = dtmc_fpt(P, 1, [2 3]); + +%!test +%! P = unifrnd(0.1,0.9,10,10); +%! normP = repmat(sum(P,2),1,columns(P)); +%! P = P./normP; +%! M = dtmc_fpt(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); +%! assert( M(i,j), dtmc_fpt(P, i, j), 1e-8 ); +%! endfor +%! endfor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/dtmc_solve.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,35 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{p} =} dtmc_solve (@var{P}) +## +## This function is deprecated and will be removed from future +## versions of @code{queueing}. Please use @code{dtmc()} instead. +## +## @seealso{dtmc} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function q = dtmc_solve( P ) + warning("Function dtmc_solve() is deprecated and will be removed in the future. Please use dtmc() instead."); + q = dtmc(P); +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/population_mix.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,141 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {pop_mix =} population_mix (@var{k}, @var{N}) +## +## @cindex population mix +## @cindex closed network, multiple classes +## +## Return the set of valid population mixes with exactly @var{k} +## customers, for a closed multiclass Queueing Network with population +## vector @var{N}. More specifically, given a multiclass Queueing +## Network with @math{C} customer classes, such that there are +## @code{@var{N}(i)} requests of class @math{i}, a +## @math{k}-mix @var{mix} is a @math{C}-dimensional vector with the +## following properties: +## +## @example +## @group +## all( mix >= 0 ); +## all( mix <= N ); +## sum( mix ) == k; +## @end group +## @end example +## +## @noindent This function enumerates all valid @math{k}-mixes, such that +## @code{@var{pop_mix}(i)} is a @math{C} dimensional row vector representing +## a valid population mix, for all @math{i}. +## +## @strong{INPUTS} +## +## @table @var +## +## @item k +## Total population size of the requested mix. @var{k} must be a nonnegative integer +## +## @item N +## @code{@var{N}(i)} is the number of class @math{i} requests. +## The condition @code{@var{k} @leq{} sum(@var{N})} must hold. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item pop_mix +## @code{@var{pop_mix}(i,j)} is the number of class @math{j} requests +## in the @math{i}-th population mix. The number of +## population mixes is @code{rows( @var{pop_mix} ) }. +## +## @end table +## +## Note that if you are interested in the number of @math{k}-mixes +## and you don't care to enumerate them, you can use the funcion +## @code{qnmvapop}. +## +## @seealso{qnmvapop} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function pop_mix = population_mix( k, population ) + + if ( nargin != 2 ) + print_usage(); + endif + + isvector( population ) && all( population>=0 ) || \ + usage( "N must be an array >=0" ); + R = length(population); # number of classes + ( isscalar(k) && k >= 0 && k <= sum(population) ) || \ + usage( "k must be a scalar <= %d", sum(population)); + N = zeros(1, R); + const = min(k, population); + mp = 0; + pop_mix = []; # Init result + while ( N(R) <= const(R) ) + x=k-mp; + ## Fill the current configuration + i=1; + while ( x>0 && i<=R ) + N(i) = min(x,const(i)); + x = x-N(i); + mp = mp+N(i); + i = i+1; + endwhile + + ## here the configuration is filled. add it to the set of mixes + assert( sum(N), k ); + pop_mix = [pop_mix; N]; ## FIXME: pop_mix is continuously resized + + ## advance to the next feasible configuration + i = 1; + sw = true; + while sw + if ( ( mp==k || N(i)==const(i)) && ( i<R ) ) + mp = mp-N(i); + N(i) = 0; + i=i+1; + else + N(i)=N(i)+1; + mp=mp+1; + sw = false; + endif + endwhile + endwhile +endfunction +%!test +%! N = [2 3 4]; +%! f = population_mix( 1, N ); +%! assert( f, [1 0 0; 0 1 0; 0 0 1] ); +%! f = population_mix( 2, N ); +%! assert( f, [2 0 0; 1 1 0; 0 2 0; 1 0 1; 0 1 1; 0 0 2] ); +%! f = population_mix( 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 = population_mix( 1, N ); +%! assert( f, [1 0; 0 1] ); +%! f = population_mix( 2, N ); +%! assert( f, [2 0; 1 1] ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnammm.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,102 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnammm (@var{lambda}, @var{mu}) +## +## @cindex Asymmetric @math{M/M/m} system +## +## Compute @emph{approximate} utilization, response time, average number +## of requests in service and throughput for an asymmetric @math{M/M/m} +## queue. In this system there are @math{m} different service centers +## connected to a single queue. Each server has its own (possibly different) +## service rate. If there is more than one server available, requests +## are routed to a randomly-chosen one. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Arrival rate (@code{@var{lambda}>0}). +## +## @item mu +## @code{@var{mu}(i)} is the service rate of server +## @math{i}, @math{1 @leq{} i @leq{} m}. +## The system must be ergodic (@code{@var{lambda} < sum(@var{mu})}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## Approximate service center utilization, +## @math{U = \lambda / ( \sum_i \mu_i )}. +## +## @item R +## Approximate service center response time +## +## @item Q +## Approximate number of requests in the system +## +## @item X +## Approximate service center throughput. If the system is ergodic, +## we will always have @code{@var{X} = @var{lambda}} +## +## @end table +## +## @seealso{qnmmm} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X p0 pm] = qnammm( lambda, mu ) + if ( nargin != 2 ) + print_usage(); + endif + + ( isscalar(lambda) && isvector(mu) ) || \ + usage( "the parameters must be vectors" ); + + m = length(mu); # number of servers + + all( lambda < sum(mu) ) || \ + error( "Processing capacity exceeded" ); + + X = lambda; + U = rho = lambda / sum(mu); + Q = p0 = 0; + k=[0:m-1]; + p0 = 1 / ( ... + sum( (m*rho).^k ./ factorial(k)) + ... + (m*rho)^m / (factorial(m)*(1-rho)) ... + ); + pm = (m*rho)^m/(factorial(m)*(1-rho))*p0; + Q = m*rho+rho / (1-rho) * pm; + R = Q / X; +endfunction +%!test +%! [U R Q X] = qnammm( 73,[10,15,20,20,25] ); +%! assert( U, 0.81, 1e-2 ); +%! assert( Q, 6.5278, 1e-4 ); + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosed.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,101 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosed (@var{N}, @var{S}, @var{V}, @dots{}) +## +## @cindex closed network +## +## This function computes steady-state performance measures of closed +## queueing networks using the Mean Value Analysis (MVA) algorithm. The +## qneneing network is allowed to contain fixed-capacity centers, delay +## centers or general load-dependent centers. Multiple request +## classes are supported. +## +## This function dispatches the computation to one of +## @code{qnclosedsinglemva}, @code{qnclosedsinglemvald} or +## @code{qnclosedmultimva}. +## +## @itemize +## +## @item If @var{N} is a scalar, the network is assumed to have a single +## class of requests; in this case, the exact MVA algorithm is used to +## analyze the network. If @var{S} is a vector, then @code{@var{S}(k)} +## is the average service time of center @math{k}, and this function +## calls @code{qnclosedsinglemva} which supports load-independent +## service centers. If @var{S} is a matrix, @code{@var{S}(k,i)} is the +## average service time at service center @math{k} when @math{i @geq{} +## 1} jobs are present; in this case, the network is analyzed with the +## @code{qnclosedsinglemvald} function. +## +## @item If @var{N} is a vector, the network is assumed to have multiple +## classes of requests, and is analyzed using the exact multiclass +## MVA algorithm as implemented in the @code{qnclosedmultimva} function. +## +## @end itemize +## +## @seealso{qnclosedsinglemva, qnclosedsinglemvald, qnclosedmultimva} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnclosed( N, S, V, varargin ) + if ( nargin < 3 ) + print_usage(); + endif + if ( isscalar(N) ) + if ( isvector(S) ) + [U R Q X] = qnclosedsinglemva( N, S, V, varargin{:} ); + else + [U R Q X] = qnclosedsinglemvald( N, S, V, varargin{:} ); + endif + else + [U R Q X] = qnclosedmultimva( N, S, V, varargin{:} ); + endif +endfunction + +%!demo +%! P = [0 0.3 0.7; 1 0 0; 1 0 0]; # Transition probability matrix +%! S = [1 0.6 0.2]; # Average service times +%! m = ones(1,3); # All centers are single-server +%! Z = 2; # External delay +%! N = 15; # Maximum population to consider +%! +%! V = qnvisits(P); # Compute number of visits from P +%! D = V .* S; # Compute service demand from S and V +%! X_bsb_lower = X_bsb_upper = zeros(1,N); +%! X_ab_lower = X_ab_upper = zeros(1,N); +%! X_mva = zeros(1,N); +%! for n=1:N +%! [X_bsb_lower(n) X_bsb_upper(n)] = qnclosedbsb(n, D, Z); +%! [X_ab_lower(n) X_ab_upper(n)] = qnclosedab(n, D, Z); +%! [U R Q X] = qnclosed( n, S, V, m, Z ); +%! X_mva(n) = X(1)/V(1); +%! endfor +%! close all; +%! plot(1:N, X_ab_lower,"g;Asymptotic Bounds;", \ +%! 1:N, X_bsb_lower,"k;Balanced System Bounds;", \ +%! 1:N, X_mva,"b;MVA;", "linewidth", 2, \ +%! 1:N, X_bsb_upper,"k", \ +%! 1:N, X_ab_upper,"g" ); +%! axis([1,N,0,1]); +%! xlabel("Number of Requests n"); +%! ylabel("System Throughput X(n)"); +%! legend("location","southeast");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedab.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,102 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnclosedab (@var{N}, @var{D}) +## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnclosedab (@var{N}, @var{D}, @var{Z}) +## +## @cindex bounds, asymptotic +## @cindex closed network +## +## Compute Asymptotic Bounds for single-class, closed Queueing Networks +## with @math{K} service centers. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## number of requests in the system (scalar, @code{@var{N}>0}). +## +## @item D +## @code{@var{D}(k)} is the service demand of service center @math{k}, +## @code{@var{D}(k) @geq{} 0}. +## +## @item Z +## external delay (think time, scalar, @code{@var{Z} @geq{} 0}). If +## omitted, it is assumed to be zero. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item Xl +## @itemx Xu +## Lower and upper bound on the system throughput. +## +## @item Rl +## @itemx Ru +## Lower and upper bound on the system response time. +## +## @end table +## +## @seealso{qnclosedbsb, qnclosedgb, qnclosedpb} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [Xl Xu Rl Ru] = qnclosedab( N, D, Z ) + if ( nargin < 2 || nargin > 3 ) + print_usage(); + endif + ( isscalar(N) && N > 0 ) || \ + usage( "N must be a positive integer" ); + ( isvector(D) && length(D)>0 && all( D >= 0 ) ) || \ + usage( "D must be a vector of nonnegative floats" ); + if ( nargin < 3 ) + Z = 0; + else + ( isscalar(Z) && Z >= 0 ) || \ + usage( "Z must be a nonnegative scalar" ); + endif + + D_tot = sum(D); + D_max = max(D); + Xl = N/(N*D_tot+Z); + Xu = min( N/(D_tot+Z), 1/D_max ); + Rl = max( D_tot, N*D_max-Z ); + Ru = N*D_tot; +endfunction + +%!test +%! fail( "qnclosedab( 1, [] )", "vector" ); +%! fail( "qnclosedab( 1, [0 -1])", "vector" ); +%! fail( "qnclosedab( 0, [1 2] )", "positive integer" ); +%! fail( "qnclosedab( -1, [1 2])", "positive integer" ); + +## Example 9.6 p. 913 Bolch et al. +%!test +%! N = 20; +%! D = [ 4.6*2 8 ]; +%! Z = 120; +%! [X_l X_u R_l R_u] = qnclosedab(N, D, Z); +%! assert( [X_u R_l], [0.109 64], 1e-3 );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedbsb.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,96 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnclosedbsb (@var{N}, @var{D}) +## @deftypefnx {Function File} {[@var{Xl}, @var{Xu}, @var{Rl}, @var{Ru}] =} qnclosedbsb (@var{N}, @var{D}, @var{Z}) +## +## @cindex bounds, balanced system +## @cindex closed network +## +## Compute Balanced System Bounds for single-class, closed Queueing Networks +## with @math{K} service centers. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## number of requests in the system (scalar). +## +## @item D +## @code{@var{D}(k)} is the service demand at center @math{k}; +## @code{@var{K}(k) @geq{} 0}. +## +## @item Z +## external delay (think time, scalar, @code{@var{Z} @geq{} 0}). If +## omitted, it is assumed to be zero. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item Xl +## @itemx Xu +## Lower and upper bound on the system throughput. +## +## @item Rl +## @itemx Ru +## Lower and upper bound on the system response time. +## +## @end table +## +## @seealso{qnclosedab, qnclosedgb, qnclosedpb} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [Xl Xu Rl Ru] = qnclosedbsb( N, D, Z ) + if ( nargin < 2 || nargin > 3 ) + print_usage(); + endif + ( isscalar(N) && N>0 ) || \ + usage( "N must be a positive scalar" ); + ( isvector(D) && length(D)>0 && all(D>=0) ) || \ + usage( "D must be a vector of nonnegative floats" ); + if ( nargin < 3 ) + Z = 0; + else + ( isscalar(Z) && Z>=0 ) || \ + usage( "Z must be a nonnegative scalar" ); + endif + + D_max = max(D); + D_tot = sum(D); + D_ave = mean(D); + Xl = N/(D_tot+Z+( (N-1)*D_max )/( 1+Z/(N*D_tot) ) ); + Xu = min( 1/D_max, N/( D_tot+Z+( (N-1)*D_ave )/(1+Z/D_tot) ) ); + Rl = max( N*D_max-Z, D_tot+( (N-1)*D_ave )/( 1+Z/D_tot) ); + Ru = D_tot + ( (N-1)*D_max )/( 1+Z/(N*D_tot) ); +endfunction + +%!test +%! fail("qnclosedbsb(1)"); +%! fail("qnclosedbsb(1, [])", "vector"); +%! fail("qnclosedbsb(-1,[1 1 1], [1 1 1])", "positive scalar"); +%! fail("qnclosedbsb(1,[-1 0 0], [1 1 1])", "nonnegative"); +%! fail("qnclosedbsb(1,[0 0 0],-1)", "nonnegative scalar");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedgb.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,214 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{Xl}, @var{Xu}, @var{Ql}, @var{Qu}] =} qnclosedgb (@var{N}, @var{D}, @var{Z}) +## +## @cindex bounds, geometric +## @cindex closed network +## +## Compute Geometric Bounds (GB) for single-class, closed Queueing Networks. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## number of requests in the system (scalar, @code{@var{N} > 0}). +## +## @item D +## @code{@var{D}(k)} is the service demand of service center @math{k} +## (@code{@var{D}(k) @geq{} 0}). +## +## @item Z +## external delay (think time, scalar). If omitted, it is assumed to be zero. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item Xl +## @itemx Xu +## Lower and upper bound on the system throughput. If @code{@var{Z}>0}, +## these bounds are computed using @emph{Geometric Square-root Bounds} +## (GSB). If @code{@var{Z}==0}, these bounds are computed using @emph{Geometric Bounds} (GB) +## +## @item Ql +## @itemx Qu +## @code{@var{Ql}(i)} and @code{@var{Qu}(i)} are the lower and upper +## bounds respectively of the queue length for service center @math{i}. +## +## @end table +## +## @seealso{qnclosedab} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [X_lower X_upper Q_lower Q_upper] = qnclosedgb( N, L, Z, X_minus, X_plus ) + ## The original paper uses the symbol "L" instead of "D" to denote the + ## loadings of service centers. In this function we adopt the same + ## notation as the paper. + if ( nargin < 2 || nargin > 5 ) + print_usage(); + endif + ( isscalar(N) && N > 0 ) || \ + usage( "N must be >0" ); + ( isvector(L) && length(L) > 0 && all( L >= 0 ) ) || \ + usage( "D must be a vector >=0" ); + L = L(:)'; # make L a row vector + if ( nargin < 3 ) + Z = 0; + else + ( isscalar(Z) && (Z >= 0) ) || \ + usage( "Z must be >=0" ); + endif + L_tot = sum(L); + L_max = max(L); + M = length(L); + if ( nargin < 4 ) + [X_minus X_plus] = qnclosedab(N,L,Z); + endif + ##[X_minus X_plus] = [0 1/L_max]; + [Q_lower Q_upper] = __compute_Q( N, L, Z, X_plus, X_minus); + [Q_lower_Nm1 Q_upper_Nm1] = __compute_Q( N-1, L, Z, X_plus, X_minus); + if ( Z > 0 ) + ## Use Geometric Square-root Bounds (GSB) + i = find(L<L_max); + bN = Z+L_tot+L_max*(N-1)-sum( (L_max-L(i)).*Q_lower_Nm1(i) ); + X_lower = 2*N/(bN+sqrt(bN^2-4*Z*L_max*(N-1))); + bN = Z+L_tot+L_max*(N-1)-sum( (L_max-L(i)).*Q_upper_Nm1(i) ); + X_upper = 2*N/(bN+sqrt(bN^2-4*Z*L_max*N)); + else + ## Use Geometric Bounds (GB). FIXME: given that this branch is + ## executed when Z=0, the expressions below can be simplified. + X_lower = N/(Z+L_tot+L_max*(N-1-Z*X_minus) - ... + sum( (L_max - L) .* Q_lower_Nm1 ) ); + X_upper = N/(Z+L_tot+L_max*(N-1-Z*X_plus) - ... + sum( (L_max - L) .* Q_upper_Nm1 ) ); + endif +endfunction + +## [ Q_lower Q_uppwer ] = __compute_Q( N, D, Z, X_plus, X_minus ) +## +## compute Q_lower(i) and Q_upper(i), the lower and upper bounds +## respectively for queue length at service center i, for a closed +## network with N customers, service demands D and think time Z. This +## function uses Eq. (8) and (13) from the reference paper. +function [ Q_lower Q_upper ] = __compute_Q( N, L, Z, X_plus, X_minus ) + isscalar(X_plus) || usage( "X_plus must be a scalar" ); + isscalar(X_minus) || usage( "X_minus must be a scalar" ); + ( isscalar(N) && (N>=0) ) || usage( "N is not valid" ); + L_tot = sum(L); + L_max = max(L); + M = length(L); + m_max = sum( L == L_max ); + y = Y = zeros(1,M); + ## first, handle the case of servers with loading less than the + ## maximum that is, L(i) < L_max + i=find(L<L_max); + y(i) = L(i)*N./(Z+L_tot+L_max*N); + Q_lower(i) = y(i)./(1-y(i)) .- (y(i).^(N+1))./(1-y(i)); # Eq. (8) + Y(i) = L(i)*X_plus; + Q_upper(i) = Y(i)./(1-Y(i)) .- (Y(i).^(N+1))./(1-Y(i)); # Eq. (13) + ## now, handle the case of servers with demand equal to the maximum + i=find(L==L_max); + Q_lower(i) = 1/m_max*(N-Z*X_plus - sum( Q_upper( find(L<L_max) ) ) ); \ + # Eq. (8) + Q_upper(i) = 1/m_max*(N-Z*X_minus - sum( Q_lower( find(L<L_max) \ + ) ) ); # Eq. (13) +endfunction + +%!test +%! fail( "qnclosedpb( 1, [] )", "vector" ); +%! fail( "qnclosedpb( 1, [0 -1])", "vector" ); +%! fail( "qnclosedpb( 0, [1 2] )", "positive integer" ); +%! fail( "qnclosedpb( -1, [1 2])", "positive integer" ); + +%!# 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] = qnclosedgb(N,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 + +%!xtest +%! # 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); + +%!xtest +%! # 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 = qnvisits(P); +%! Nmax = 20; +%! +%! ## Test case with Z>0 +%! for n=1:Nmax +%! [X_gb_lower X_gb_upper Q_gb_lower Q_gb_upper] = qnclosedgb(n, S.*V, 2); +%! [U R Q X] = qnclosed( n, S, V, m, 2 ); +%! X_mva = X(1)/V(1); +%! assert( X_gb_lower <= X_mva ); +%! assert( X_gb_upper >= X_mva ); +%! assert( Q_gb_lower <= Q+1e-5 ); # compensate for numerical errors +%! assert( Q_gb_upper >= Q-1e-5 ); # compensate for numerical errors +%! endfor + +%!test +%! P = [0 0.3 0.7; 1 0 0; 1 0 0]; +%! S = [1 0.6 0.2]; +%! m = ones(1,3); +%! V = qnvisits(P); +%! Nmax = 20; +%! +%! ## Test case with Z=0 +%! for n=1:Nmax +%! [X_gb_lower X_gb_upper Q_gb_lower Q_gb_upper] = qnclosedgb(n, S.*V, 0); +%! [U R Q X] = qnclosed( n, S, V, m, 0 ); +%! X_mva = X(1)/V(1); +%! assert( X_gb_lower <= X_mva ); +%! assert( X_gb_upper >= X_mva ); +%! assert( Q_gb_lower <= Q ); +%! assert( Q_gb_upper >= Q ); +%! endfor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedmultimva.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,760 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimva (@var{N}, @var{S} ) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimva (@var{N}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimva (@var{N}, @var{S}, @var{V}, @var{m}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimva (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimva (@var{N}, @var{S}, @var{P}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimva (@var{N}, @var{S}, @var{P}, @var{m}) +## +## @cindex Mean Value Analysys (MVA) +## @cindex closed network, multiple classes +## +## Analyze closed, multiclass queueing networks with @math{K} service +## centers and @math{C} independent customer classes (chains) using the +## Mean Value Analysys (MVA) algorithm. +## +## Queueing policies at service centers can be any of the following: +## +## @table @strong +## +## @item FCFS +## (First-Come-First-Served) customers are served in order of arrival; +## multiple servers are allowed. For this kind of queueing discipline, +## average service times must be class-independent. +## +## @item PS +## (Processor Sharing) customers are served in parallel by a single +## server, each customer receiving an equal share of the service rate. +## +## @item LCFS-PR +## (Last-Come-First-Served, Preemptive Resume) customers are served in +## reverse order of arrival by a single server and the last arrival +## preempts the customer in service who will later resume service at the +## point of interruption. +## +## @item IS +## (Infinite Server) customers are delayed independently of other +## customers at the service center (there is effectively an infinite +## number of servers). +## +## @end table +## +## @quotation Note +## If this function is called specifying the visit ratios +## @var{V}, class switching is @strong{not} allowed. +## +## If this function is called specifying the routing probability matrix +## @var{P}, then class switching @strong{is} allowed; however, in this +## case all nodes are restricted to be fixed rate service centers or +## delay centers: multiple-server and general load-dependent +## centers are not supported. @end quotation +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## @code{@var{N}(c)} is the number of class @math{c} requests in the +## system; @code{@var{N}(c) @geq{} 0}. If class @math{c} has +## no requests (@code{@var{N}(c) = 0}), then +## @code{@var{U}(c,k) = @var{R}(c,k) = @var{Q}(c,k) = @var{X}(c,k) = 0} +## for all @var{k}. +## +## @item S +## @code{@var{S}(c,k)} is the mean service time for class @math{c} +## customers at center @math{k} (@code{@var{S}(c,k) @geq{} 0}). +## If service time at center @math{k} is class-dependent, +## then center #math{k} is assumed to be of type @math{-/G/1}--PS +## (Processor Sharing). +## If center @math{k} is a FCFS node (@code{@var{m}(k)>1}), then the +## service times @strong{must} be class-independent. +## +## @item V +## @code{@var{V}(c,k)} is the average number of visits of class @math{c} +## customers to service center @math{k}; @code{@var{V}(c,k) @geq{} 0}, +## default is 1. +## @strong{If you pass this parameter, no class switching is not +## allowed} +## +## @item P +## @code{@var{P}(r,i,s,j)} is the probability that a class @math{r} +## job completing service at center @math{i} is routed to center @math{j} +## as a class @math{s} job. @strong{If you pass this parameter, +## class switching is allowed}. +## +## @item m +## If @code{@var{m}(k)<1}, then center @math{k} is assumed to be a delay +## center (IS node @math{-/G/\infty}). If @code{@var{m}(k)==1}, then +## service center @math{k} is a regular queueing center +## (@math{M/M/1}--FCFS, @math{-/G/1}--LCFS-PR or @math{-/G/1}--PS). +## Finally, if @code{@var{m}(k)>1}, center @math{k} is a +## @math{M/M/m}--FCFS center with @code{@var{m}(k)} identical servers. +## Default is @code{@var{m}(k)=1} for each @math{k}. +## +## @item Z +## @code{@var{Z}(c)} is the class @math{c} external delay (think time); +## @code{@var{Z}(c) @geq{} 0}. Default is 0. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## If @math{k} is a FCFS, LCFS-PR or PS node, then @code{@var{U}(c,k)} +## is the class @math{c} utilization at center +## @math{k}. If @math{k} is an IS node, then @code{@var{U}(c,k)} is the +## class @math{c} @emph{traffic intensity} at center @math{k}, +## defined as @code{@var{U}(c,k) = @var{X}(c,k)*@var{S}(c,k)}. +## +## @item R +## @code{@var{R}(c,k)} is the class @math{c} response time at +## center @math{k}. The total class @math{c} system response time +## can be computed as @code{dot(@var{R}, @var{V}, 2)}. +## +## @item Q +## @code{@var{Q}(c,k)} is the average number of +## class @math{c} requests at center @math{k}. The total number of +## requests at center @math{k} is @code{sum(@var{Q}(:,k))}. +## The total number of class @math{c} requests in the system +## is @code{sum(@var{Q}(c,:))}. +## +## @item X +## @code{@var{X}(c,k)} is the class @math{c} throughput at +## center @math{k}. The class @math{c} system throughput can be computed +## as @code{@var{X}(c,1) / @var{V}(c,1)}. +## +## @end table +## +## @seealso{qnclosed, qnclosedmultimvaapprox} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnclosedmultimva( N, S, V, varargin ) + + if ( nargin < 2 || nargin > 5 ) + print_usage(); + endif + + if ( nargin == 2 ) + V = ones(size(S)); + endif + + ( ismatrix(V) && (ndims(V) == 2 || ndims(V) == 4) ) || \ + usage("The third parameter has %d dimensions (must be 2- or 4-dimensional)", ndims(V) ); + + if ( ndims(V) == 2 ) + [U R Q X] = __qnclosedmultimva_nocs( N, S, V, varargin{:} ); + else + [U R Q X] = __qnclosedmultimva_cs( N, S, V, varargin{:} ); + endif + +endfunction + +############################################################################## +## Analyze closed, multiclass QNs with class switching +function [U R Q X] = __qnclosedmultimva_cs( N, S, P, m ) + + if ( nargin < 3 || nargin > 4 ) + print_usage(); + endif + + isvector(N) && all( N>=0 ) || \ + usage( "N must be >=0" ); + N = N(:)'; # make N a row vector + C = length(N); ## Number of classes + K = columns(S); ## Number of service centers + ( ndims(S) == 2 ) || \ + usage( "S must be a %dx%d matrix", C, K ); + size(S) == [C,K] || \ + usage( "S size mismatch (is %dx%d, should be %dx%d)", rows(S), columns(S), C, K ); + ndims(P) == 4 && size(P) == [C,K,C,K] || \ + usage( "P size mismatch" ); + + if ( nargin < 4 ) + m = ones(1,K); + else + isvector(m) || \ + usage( "m must be a vector" ); + m = m(:)'; # make m a row vector + length(m) == K || \ + usage( "m size mismatch (should be %d, is %d)", K, length(m) ); + endif + + ## Check consistency of parameters + all( all( S >= 0 ) ) || \ + usage( "S must be >0" ); + all( any(S>0,2) ) || \ + usage( "S must contain at least a value >0 for each row" ); + all( all( P >= 0 ) ) || \ + usage( "V must be >=0" ); + + U = R = Q = X = zeros(C,K); + + ## 1. Compute visit counts + [V ch] = qnvisits(P); + + ## 2. Identify chains + ## ch = qnchains(P); + nch = max(ch); + + ## 3. Compute visit counts for the equivalent network + Vstar = zeros(nch,K); + for q=1:nch + r = (ch == q); + Vstar(q,:) = sum(V(r,:),1); + endfor + + ## 4. Compute proportionality constants + alpha = zeros(C,K); + for r=1:C + for k=find( Vstar(ch(r),:) > 0 ) + alpha(r,k) = V(r,k) / Vstar( ch(r), k ); + endfor + endfor + + ## 5. Compute service times + Sstar = zeros(nch,K); + for q=1:nch + r = (ch==q); + Sstar(q,:) = dot( alpha(r,:), S(r,:), 1 ); + endfor + + ## 6. Compute populations of superclasses + Nstar = zeros(1,nch); + for q=1:nch + r = (ch == q); + Nstar(q) = sum( N(r) ); + endfor + + ## 7. Solve the equivalent network + [Ustar Rstar Qstar Xstar Qnm1] = __qnclosedmultimva_nocs( Nstar, Sstar, Vstar, m ); + + ## 8. Compute solutions of the original network + for r=1:C + for k=1:K + R(r,k) = S(r,k) * (1 + Qnm1(ch(r),k)*(m(k)==1)); + X(r,k) = alpha(r,k) * Xstar(ch(r),k); + Q(r,k) = X(r,k) * R(r,k); + U(r,k) = S(r,k) * X(r,k); + endfor + endfor + +endfunction + +############################################################################## +## Analyze closed, multiclass QNs WITHOUT class switching +## +## This implementation is based on: +## +## Herb Schwetman, "Implementing the MEan Value Algorithm for the +## Solution of Queueing Network Models", technical report OSD-TR-355, +## dept. of Computer Science, Purdue University, feb. 1982. +## +function [U R Q X Qnm1] = __qnclosedmultimva_nocs( N, S, V, m, Z ) + + if ( nargin < 3 || nargin > 5 ) + print_usage(); + endif + + isvector(N) && all( N>=0 ) || \ + usage( "N must be >=0" ); + N = N(:)'; # make N a row vector + C = length(N); ## Number of classes + K = columns(S); ## Number of service centers + size(S) == [C,K] || \ + usage( "S size mismatch" ); + size(V) == [C,K] || \ + usage( "V size mismatch" ); + + if ( nargin < 4 ) + m = ones(1,K); + else + isvector(m) || \ + usage( "m must be a vector" ); + m = m(:)'; # make m a row vector + length(m) == K || \ + usage( "m size mismatch (should be %d, is %d)", K, length(m) ); + endif + + if ( nargin < 5 ) + Z = zeros(1,C); + else + isvector(Z) || \ + usage( "Z must be a vector" ); + Z = Z(:)'; # make Z a row vector + length(Z) == C || \ + usage( "Z size mismatch (should be %d, is %d)", C, length(Z) ); + endif + + ## Check consistency of parameters + all( all( S >= 0 ) ) || \ + usage( "S must be >=0" ); + all( any(S>0,2) ) || \ + usage( "S must contain at least a value >0 for each row" ); + all( all( V >= 0 ) ) || \ + usage( "V must be >=0" ); + + ## ensure that the service times for multiserver nodes + ## are class-independent + for k=find(m>1) + all( S(:,k) == S(1,k) ) || \ + error( "Service times for FCFS node %d are not class-independent", k ); + endfor + + ## Initialize results + R = zeros( C, K ); + X = zeros( 1, C ); + D = S .* V; + + ## The multiclass MVA algorithm requires to store the queue lengths Q( + ## _n_, k ) at center k where the population vector is _n_. The space + ## required would be K*prod(N+1), but this can be reduced by + ## considering that, at each iteration of the main MVA loop, the total + ## number of requests is n; therefore it is sufficient to consider the + ## first (C-1) components of vector _n_ to uniquely identify the cell + ## containing Q( _n_, k ). See Schwetman for a better explanation. + bufsize = prod((N+1)(1:end-1)); + Q_next = Q = zeros( bufsize,K ); + + p = cell(1,K); + for k=find(m>1) + ## p{i}(j+1,k+1) is the probability to have j jobs at node i + ## where the network is in state k + p{k} = zeros( m(k)+1,bufsize ); + p{k}(1,__getidx(N,0*N)) = 1; + endfor + + Qnm1= zeros(C,K); ## Qnm1(c,k) is the number of requests in center k, provided that the population size is N-1_c (N is the total population vector). This value is needed by __qnclosedmultimva_cs. Qnm1 is only filled for M/M/1 or PS centers. The values are not computed for PS nodes + + dd = zeros(1,C); + for c=find(N>0) + h = zeros(1,C); h(c) = 1; + dd(c) = __getidx(N,h)-1; + endfor + + for n=1:sum(N) + + ## MVA iteration for population size n + n_bar = zeros(1, C); + const = min(n, N); + mp = 0; + while ( n_bar(C) <= const(C) ) + + ## Fill the current configuration (algorithm 3b, p. 10, Schwetman) + x=n-mp; + i=1; + while ( x>0 && i<=C ) + n_bar(i) = min(x,const(i)); + x -= n_bar(i); + mp += n_bar(i); + i += 1; + endwhile + + idx = __getidx( N, n_bar ); + + R = S; + + ## Compute response time for LI servers + k=find(m==1); + for c=find(n_bar>0) + ## idx-dd(c) is the index of element n_bar - 1_c + R(c,k) = S(c,k).*(1 + Q( idx-dd(c), k ) ); + Qnm1(c,k) = Q( idx-dd(c), k); + ## for FCFS nodes with class-dependent service times, + ## it is possible to use the following approximation + ## (p. 469 Bolch et al.) + ## + ## R(c,k) = S(c,k) + sum( S(:,k) * Q(idx(:), k) ); + ## R(c,k) = S(c,k) + sum( S(:,k) .* Q(idx, k) .* V(:,k) ) / sum(V(:,k)); + endfor + + ## Compute response time for LD servers + for k=find(m>1) + j=0:m(k)-2; # range + for c=find(n_bar > 0 ) + R(c,k) = S(c,k)/m(k)*(1 + Q( idx-dd(c), k ) + ... + dot(m(k)-j-1,p{k}(j+1,idx-dd(c)) ) ); + endfor + endfor + + X = n_bar ./ ( Z .+ dot(R,V,2)' ); # X(c) = N(c) / ( Z(c) + sum_k R(c,k) * V(c,k) ) + + ## Q_k = sum_c X(c) * R(c,k) * V(c,k) + Q_next( idx, : ) = (X * (R .* V))'; + ## Q( idx, : ) = (X * (R .* V))'; + + ## Update marginal probabilities for LD servers + for k=find(m>1) + s=0; # s is actually a vector + j=1:m(k)-1; + for r=find(n_bar>0) # FIXME: I don't know how to vectorize this + s+=D(r,k)*X(r)*p{k}(j,idx-dd(r)); + endfor + p{k}(j+1,idx) = s./j; + p{k}(1,idx) = 1-1/m(k)*(dot( D(:,k),X ) + ... + dot( m(k)-j, p{k}(j+1,idx) ) ); + endfor + + if ( n_bar(C) == N(C) ) + break; + endif + + ## Advance to next feasible configuration (Algorithm 3c, p. 10 Schwetman) + i = 1; + sw = true; + while sw + if ( ( mp==n || n_bar(i)==const(i)) && ( i<C ) ) + mp -= n_bar(i); + n_bar(i) = 0; + i += 1; + else + n_bar(i)=n_bar(i)+1; + mp += 1; + sw = false; + endif + endwhile + endwhile + Q = Q_next; + endfor + U = diag(X)*D; # U(c,k) = X(c)*D(c,k) + Q = diag(X)*(R.*V); + X = diag(X)*V; +endfunction + +############################################################################## +## Compute the linear index corresponding to vector i from a population +## of N. +function idx = __getidx( N, i ) + if ( length(N) == 1 ) + idx = 1; + else + i_cell = num2cell( (i+1)(1:end-1) ); + idx = sub2ind( (N+1)(1:end-1), i_cell{:} ); + endif +endfunction + +%!test +%! S = [1 1 2; 1 1 1]; +%! V = [1 1 1; 1 1 1]; +%! N = [1 1]; +%! m = [1 1 2]; +%! fail( "qnclosedmultimva(N)" ); +%! fail( "qnclosedmultimva(N,S,V,m)", "independent" ); +%! S = [0 0 0; 1 1 1]; +%! fail( "qnclosedmultimva(N,S,V,m)", "must contain at least" ); +%! S = [1 2 3; 1 2 3]; +%! N = [1 1]; +%! V = zeros(3,2,3); +%! fail( "qnclosedmultimva(N,S,V)", "third parameter" ); + +## Check degenerate case (population is zero); LI servers +%!test +%! S = [1 1 1; 1 1 1]; +%! N = [0 0]; +%! [U R Q X] = qnclosedmultimva(N, S); +%! assert( U, 0*S ); +%! assert( R, 0*S ); +%! assert( Q, 0*S ); +%! assert( X, 0*S ); + +## Check degenerate case (population is zero); LD servers +%!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] = qnclosedmultimva(N, S, V, m); +%! assert( U, 0*S ); +%! assert( R, 0*S ); +%! assert( Q, 0*S ); +%! assert( X, 0*S ); + +## Example p. 142, Lazowska et al., "Quantitative System Performance: +## Computer System Analysis Using Queueing Network Models" +%!test +%! S = [ 1/10 1/3; 2/5 1 ]; +%! V = [ 10 9; 5 4 ]; +%! N = [ 1 1 ]; +%! [U R Q X] = qnclosedmultimva(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(all(U<=1)) ); + +## Example 8.3 p. 331, Bolch et al. Note that this is not a multiclass +## network, because there is a single job class. Nevertheless, the +## multiclass MVA algorithm must produce the same results as the single +## class one. +%!test +%! S = [0.02 0.2 0.4 0.6]; +%! V = [1 0.4 0.2 0.1]; +%! N = [6]; +%! [U R Q X] = qnclosedmultimva( 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 from table 3, p. 22, Herb Schwetman, "Implementing the Mean +## Value Algorith for the Solution of Queueing Network Models", +## Technical Report CSD-TR-355, Department of Computer Sciences, Purdue +## University, feb 15, 1982. +%!test +%! S = [1 0 .025; 0 15 .5]; +%! V = [1 0 1; 0 1 1]; +%! N = [2 1]; +%! m = [-1 -1 1]; +%! [U R Q X] = qnclosedmultimva(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) ); + +## Example from table 5, p. 23, Herb Schwetman, "Implementing the Mean +## Value Algorith for the Solution of Queueing Network Models", +## Technical Report CSD-TR-355, Department of Computer Sciences, Purdue +## University, feb 15, 1982. +%!test +%! S = [1 0 .025; 0 15 .5]; +%! V = [1 0 1; 0 1 1]; +%! N = [15 5]; +%! m = [-1 -1 1]; +%! [U R Q X] = qnclosedmultimva(N,S,V,m); +%! # FIXME: I replaced 14.3->14.323 +%! assert( U, [14.323 0 .358; 0 4.707 .157], 1e-3 ); +%! # FIXME: I replaced 14.3->14.323 +%! assert( X, [14.323 0 14.323; 0 .314 .314 ], 1e-3 ); +%! # FIXME: 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 ); + +## Example 9.5 p. 337, Bolch et al. +%!test +%! S = [ 0.2 0.4 1; 0.2 0.6 2 ]; +%! V = [ 1 0.6 0.4; 1 0.3 0.7 ]; +%! N = [ 2 1 ]; +%! m = [ 2 1 -1 ]; +%! [U R Q X] = qnclosedmultimva(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( all(U<=1) ) ); + +## Multiclass network with two classes; however, class 2 has 0 requests. +## Therefore, we check that the results for class 1 are the same as those +## computed by the single-class MVA +%!test +%! C = 2; # two classes +%! K = 4; # four servers +%! S = V = zeros(C,K); +%! S(1,:) = linspace(1,2,K); +%! S(2,:) = linspace(2,3,K); +%! V(1,:) = linspace(4,1,K); +%! V(2,:) = linspace(6,3,K); +%! N = [10 0]; # class 2 has no customers +%! [U1 R1 Q1 X1] = qnclosedmultimva(N,S,V); +%! [U2 R2 Q2 X2] = qnclosedsinglemva(N(1),S(1,:),V(1,:)); +%! assert( U1(1,:), U2, 1e-5 ); +%! assert( R1(1,:), R2, 1e-5 ); +%! assert( Q1(1,:), Q2, 1e-5 ); +%! assert( X1(1,:), X2, 1e-5 ); + +## This is example 5(b) page 7 of +## http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1258&context=cstech +## "Testing network-of-queues software", technical report CSD-TR 330, +%!test +%! Z = [1 15]; +%! V = [1; 1]; +%! S = [.025; .5]; +%! N = [15; 5]; +%! [U R Q X] = qnclosedmultimva(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 ); + +## This is example of Figure 6, page 9 of +## http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1258&context=cstech +## "Testing network-of-queues software", technical report CSD-TR 330, +%!test +%! C = 2; +%! K = 6; +%! P = zeros(C,K,C,K); +%! P(1,1,1,2) = P(2,1,2,2) = 1; +%! P(1,2,1,3) = P(1,2,1,4) = P(1,2,1,5) = P(1,2,1,6) = .25; +%! P(2,2,2,3) = P(2,2,2,4) = P(2,2,2,5) = P(2,2,2,6) = .25; +%! P(1,3,1,1) = P(1,4,1,1) = P(1,5,1,1) = P(1,6,1,1) = .9; +%! P(1,3,1,2) = P(1,4,1,2) = P(1,5,1,2) = P(1,6,1,2) = .1; +%! P(2,3,2,1) = P(2,4,2,1) = P(2,5,2,1) = P(2,6,2,1) = .05; +%! P(2,3,2,2) = P(2,4,2,2) = P(2,5,2,2) = P(2,6,2,2) = .95; +%! N = [40 4]; +%! S = [ 5.0 .010 .035 .035 .035 .035; \ +%! 10.0 .100 .035 .035 .035 .035 ]; +%! V = qnvisits(P); +%! [U R Q X] = qnclosedmultimva(N, S, V, [-1 1 1 1 1 1]); +%! # FIXME: The results below were computed with JMVA; the numbers +%! # in the paper are different (wrong?!?)!! +%! 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 ); + + +## If there is no class switching, we must get the same results as +## the plain application of multiclass MVA +%!test +%! C = 2; # two classes +%! K = 4; # four servers +%! C = 2; K = 4; +%! P = zeros(C,K,C,K); +%! S = zeros(C,K); +%! +%! # Routing +%! +%! # class 1 routing +%! P(1,1,1,1) = .05; +%! P(1,1,1,2) = .45; +%! P(1,1,1,3) = .5; +%! P(1,2,1,1) = 1; +%! P(1,3,1,1) = 1; +%! # class 2 routing +%! P(2,1,2,1) = .01; +%! P(2,1,2,3) = .5; +%! P(2,1,2,4) = .49; +%! P(2,3,2,1) = 1; +%! P(2,4,2,1) = 1; +%! +%! # Compute visits +%! +%! V = qnvisits(P); +%! +%! # Define population and service times +%! +%! N = [3 2]; +%! S = [0.01 0.09 0.10 0.08; \ +%! 0.05 0.09 0.10 0.08]; +%! [U1 R1 Q1 X1] = qnclosedmultimva(N,S,V); # this invokes __qnclosedmultimva_nocs +%! [U2 R2 Q2 X2] = qnclosedmultimva(N,S,P); # this invokes __qnclosedmultimva_cs +%! assert( U2, U1, 1e-5 ); +%! assert( R2, R1, 1e-5 ); +%! assert( Q2, Q1, 1e-5 ); +%! assert( X2, X1, 1e-5 ); + +## Example from table 5, p. 23, Herb Schwetman, "Implementing the Mean +## Value Algorith for the Solution of Queueing Network Models", +## Technical Report CSD-TR-355, Department of Computer Sciences, Purdue +## University, feb 15, 1982. Note: below, server 1 is the PS +## node labeled "Sys 3" in the example; server 2 is the IS labeled +## "APL1" and server e is the IS labeled "IMS2" +%!test +%! S = [.025 1 15; .5 1 15 ]; +%! P = zeros(2,3,2,3); +%! P(1,1,1,2) = P(1,2,1,1) = 1; +%! P(2,1,2,3) = P(2,3,2,1) = 1; +%! ## V = qnvisits(P); +%! N = [15 5]; +%! m = [1 -1 -1]; +%! [U R Q X] = qnclosedmultimva(N,S,P,m); +%! # FIXME: I replaced 14.3->14.323 +%! assert( U, [0.358 14.323 0; 0.156 0 4.707], 1e-3 ); +%! # FIXME: I replaced 14.3->14.323 +%! assert( X, [14.323 14.3230 0; .314 0 .314 ], 1e-3 ); +%! # FIXME: 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 ); + +## Example figure 9 Schwetman +%!test +%! C = 2; K = 3; +%! S = [.01 .07 .10; \ +%! .05 .07 .10 ]; +%! P = zeros(C,K,C,K); +%! P(1,1,1,2) = .7; +%! P(1,1,1,3) = .2; +%! P(1,1,2,1) = .1; +%! P(2,1,2,2) = .3; +%! P(2,1,2,3) = .5; +%! P(2,1,1,1) = .2; +%! P(1,2,1,1) = P(2,2,2,1) = 1; +%! P(1,3,1,1) = P(2,3,2,1) = 1; +%! N = [3 0]; +%! V = qnvisits(P); +%! [U R Q X] = qnclosedmultimva(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 ); + +## This example is from G. Casale and G. Serazzi. Quantitative system +## evaluation with java modeling tools. In Proceedings of the second +## joint WOSP/SIPEW international conference on Performance engineering, +## ICPE '11, pages 449-454, New York, NY, USA, 2011. ACM +%!demo +%! Ntot = 100; # total population size +%! b = linspace(0.1,0.9,10); # fractions of class-1 requests +%! S = [20 80 31 14 23 12; \ +%! 90 30 33 20 14 7]; +%! V = ones(size(S)); +%! X1 = X1 = XX = zeros(size(b)); +%! R1 = R2 = RR = zeros(size(b)); +%! for i=1:length(b) +%! N = [fix(b(i)*Ntot) Ntot-fix(b(i)*Ntot)]; +%! # printf("[%3d %3d]\n", N(1), N(2) ); +%! [U R Q X] = qnclosedmultimva( 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, "linewidth", 2, \ +%! b, X2, "linewidth", 2, \ +%! b, XX, "linewidth", 2 ); +%! legend("location","south"); +%! 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"); +%! xlabel("Population mix \\beta for Class 1"); +%! ylabel("Resp. Time");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedmultimvaapprox.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,260 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimvaapprox (@var{N}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimvaapprox (@var{N}, @var{S}, @var{V}, @var{m}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimvaapprox (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimvaapprox (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedmultimvaapprox (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}, @var{iter_max}) +## +## @cindex Mean Value Analysys (MVA), approximate +## @cindex Approximate MVA +## @cindex Closed network, multiple classes +## @cindex Closed network, approximate analysis +## +## Analyze closed, multiclass queueing networks with @math{K} service +## centers and @math{C} customer classes using the approximate Mean +## Value Analysys (MVA) algorithm. +## +## This implementation uses Bard and Schweitzer approximation. It is based +## on the assumption that +## @iftex +## @tex +## $$Q_i({\bf N}-{\bf 1}_c) \approx {n-1 \over n} Q_i({\bf N})$$ +## @end tex +## @end iftex +## @ifnottex +## the queue length at service center @math{k} with population +## set @math{{\bf N}-{\bf 1}_c} is approximately equal to the queue length +## with population set @math{\bf N}, times @math{(n-1)/n}: +## +## @example +## @group +## Q_i(N-1c) ~ (n-1)/n Q_i(N) +## @end group +## @end example +## @end ifnottex +## +## where @math{\bf N} is a valid population mix, @math{{\bf N}-{\bf 1}_c} +## is the population mix @math{\bf N} with one class @math{c} customer +## removed, and @math{n = \sum_c N_c} is the total number of requests. +## +## This implementation works for networks made of infinite server (IS) +## nodes and single-server nodes only. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## @code{@var{N}(c)} is the number of +## class @math{c} requests in the system (@code{@var{N}(c)>0}). +## +## @item S +## @code{@var{S}(c,k)} is the mean service time for class @math{c} +## customers at center @math{k} (@code{@var{S}(c,k) @geq{} 0}). +## +## @item V +## @code{@var{V}(c,k)} is the average number of visits of class @math{c} +## requests to center @math{k} (@code{@var{V}(c,k) @geq{} 0}). +## +## @item m +## @code{@var{m}(k)} is the number of servers at service center +## @math{k}. If @code{@var{m}(k) < 1}, then the service center @math{k} +## is assumed to be a delay center (IS). If @code{@var{m}(k) == 1}, +## service center @math{k} is a regular queueing center (FCFS, LCFS-PR +## or PS) with a single server node. If omitted, each service center has +## a single server. Note that multiple server nodes are not supported. +## +## @item Z +## @code{@var{Z}(c)} is the class @math{c} external delay. Default +## is 0. +## +## @item tol +## Stopping tolerance (@code{@var{tol}>0}). The algorithm stops if +## the queue length computed on two subsequent iterations are less than +## @var{tol}. Default is @math{10^{-5}}. +## +## @item iter_max +## Maximum number of iterations (@code{@var{iter_max}>0}. +## The function aborts if convergenge is not reached within the maximum +## number of iterations. Default is 100. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## If @math{k} is a FCFS, LCFS-PR or PS node, then @code{@var{U}(c,k)} +## is the utilization of class @math{c} requests on service center +## @math{k}. If @math{k} is an IS node, then @code{@var{U}(c,k)} is the +## class @math{c} @emph{traffic intensity} at device @math{k}, +## defined as @code{@var{U}(c,k) = @var{X}(c)*@var{S}(c,k)} +## +## @item R +## @code{@var{R}(c,k)} is the response +## time of class @math{c} requests at service center @math{k}. +## +## @item Q +## @code{@var{Q}(c,k)} is the average number of +## class @math{c} requests at service center @math{k}. +## +## @item X +## @code{@var{X}(c,k)} is the class @math{c} +## throughput at service center @math{k}. +## +## @end table +## +## @seealso{qnclosed} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnclosedmultimvaapprox( N, S, V, m, Z, \ + tol, \ + iter_max ) + + if ( nargin < 3 || nargin > 7 ) + print_usage(); + endif + + isvector(N) && all( N>=0 ) || \ + usage( "N must be a vector of positive integers" ); + N = N(:)'; # make N a row vector + C = length(N); ## Number of classes + K = columns(S); ## Number of service centers + size(S) == [C,K] || \ + usage( "S size mismatch" ); + size(V) == [C,K] || \ + usage( "V size mismatch" ); + + if ( nargin < 4 ) + m = ones(1,K); + else + isvector(m) || \ + usage( "m must be a vector"); + m = m(:)'; # make m a row vector + ( length(m) == K && all( m <= 1 ) ) || \ + usage( "m must be <= 1 and have %d elements", K ); + endif + + if ( nargin < 5 ) + Z = zeros(1,C); + else + isvector(Z) || \ + usage( "Z must be a vector" ); + Z = Z(:)'; # make Z a row vector + ( length(Z) == C && all(Z >= 0 ) ) || \ + usage( "Z must be >= 0 and have %d elements", C ); + endif + + if ( nargin < 6 ) + tol = 1e-5; + endif + + if ( nargin < 7 ) + iter_max = 100; + endif + + ## Check consistency of parameters + all( all( S >= 0 ) ) || \ + usage( "S contains negative values" ); + all( all( V >= 0 ) ) || \ + usage( "V contains negative values" ); + + ## Initialize results + R = zeros( C, K ); + Xc = zeros( 1, C ); # Xc(c) is the class c throughput + Q = zeros( C, K ); + D = V .* S; + + ## Initialization of temporaries + iter = 0; + A = zeros( C, K ); + Q = diag(N/K)*ones(C,K); # Q(c,k) = N(c) / K + + i_single=find(m==1); + i_multi=find(m<1); + ## Main loop + N(N==0)=1; + do + iter++; + Qold = Q; + + ## A(c,k) = (N(c)-1)/N(c) * Q(c,k) + sum_{j=1, j|=c}^C Qold(j,k) + A = diag( (N-1) ./ N )*Q + ( (1 - eye(C)) * Qold ); + + ## R(c,k) = + ## S(c,k) is k is a delay center + ## S(c,k) * (1+A(c,k)) if k is a queueing center; + R(:,i_multi) = S(:,i_multi); + R(:,i_single) = S(:,i_single) .* ( 1 + A(:,i_single)); + + ## X(c) = N(c) / (sum_k R(c,k) * V(c,k)) + Xc = N ./ (Z .+ sum(R.*V,2)'); + + ## Q(c,k) = X(c) * R(c,k) * V(c,k) + Q = (diag(Xc)*R).*V; + + ## err = norm(Q-Qold); + err = norm((Q-Qold)./Qold, "inf"); + until (err<tol || iter>iter_max); + + if ( iter > iter_max ) + warning( "qnclosedmultimvaapprox(): Convergence not reached after %d iterations", iter_max ); + endif + X = diag(Xc)*V; # X(c,k) = X(c) * V(c,k) + U = diag(Xc)*D; # U(c,k) = X(c) * D(c,k) + + # U(N==0,:) = R(N==0,:) = Q(N==0,:) = X(N==0,:) = 0; + +endfunction +%!test +%! S = [ 1 3 3; 2 4 3]; +%! V = [ 1 1 3; 1 1 3]; +%! N = [ 1 1 ]; +%! m = [1 ; 1 ]; +%! Z = [2 2 2]; +%! fail( "qnclosedmultimvaapprox(N,S,V,m,Z)", "m must be" ); +%! m = [1 ; 1 ; 1]; +%! fail( "qnclosedmultimvaapprox(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] = qnclosedmultimvaapprox(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] = qnclosedmultimvaapprox(N,S,V,m);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedpb.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,110 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{Xl}, @var{Xu}] =} qnclosedpb (@var{N}, @var{D} ) +## +## Compute PB Bounds (C. H. Hsieh and S. Lam, 1987) +## for single-class, closed Queueing Networks +## with @math{K} service centers. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## number of requests in the system (scalar). Must be @code{@var{N} > 0}. +## +## @item D +## @code{@var{D}(k)} is the service demand of service center @math{k}. Must be +## @code{@var{D}(k) @geq{} 0} for all @math{k}. +## +## @item Z +## external delay (think time, scalar). If omitted, it is assumed to be zero. +## Must be @code{@var{Z} @geq{} 0}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item Xl +## @itemx Xu +## Lower and upper bounds on the system throughput. +## +## @end table +## +## @seealso{qnclosedab, qbclosedbsb, qnclosedgb} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [X_lower X_upper] = qnclosedpb( N, D, Z ) + if ( nargin < 2 || nargin > 3 ) + print_usage(); + endif + ( isscalar(N) && N > 0 ) || \ + usage( "N must be a positive integer" ); + ( isvector(D) && length(D)>0 && all( D >= 0 ) ) || \ + usage( "D must be a vector of nonnegative floats" ); + if ( nargin < 3 ) + Z = 0; + else + ( isscalar(Z) && Z >= 0 ) || \ + usage( "Z must be a nonnegative scalar" ); + endif + D_tot = sum(D); + X_max = 1/max(D); + X_min = 0; + X_lower = N/( Z + D_tot + ... + ( sum( D .^ N * (N-1-Z*X_min) ) / sum( D .^ (N-1) ) ) ); + X_upper = N/( Z + D_tot + ... + ( sum( D .^ 2 * (N-1-Z*X_max) ) / sum( D ) ) ); + X_upper = min( X_upper, X_max ); # cap X upper bound to 1/max(D) +endfunction + +%!test +%! fail( "qnclosedpb( 1, [] )", "vector" ); +%! fail( "qnclosedpb( 1, [0 -1])", "vector" ); +%! fail( "qnclosedpb( 0, [1 2] )", "positive integer" ); +%! fail( "qnclosedpb( -1, [1 2])", "positive integer" ); +%! fail( "qnclosedpb( 1, [1 2], -1)", "nonnegative scalar" ); + +%!# shared test function +%!function test_pb( D, expected, Z=0 ) +%! for i=1:rows(expected) +%! N = expected(i,1); +%! [X_lower X_upper] = qnclosedpb(N,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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedsinglemva.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,364 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qnclosedsinglemva (@var{N}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qnclosedsinglemva (@var{N}, @var{S}, @var{V}, @var{m}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qnclosedsinglemva (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) +## +## @cindex Mean Value Analysys (MVA) +## @cindex closed network, single class +## @cindex normalization constant +## +## Analyze closed, single class queueing networks using the exact Mean +## Value Analysis (MVA) algorithm. The following queueing disciplines +## are supported: FCFS, LCFS-PR, PS and IS (Infinite Server). This +## function supports fixed-rate service centers or multiple server +## nodes. For general load-dependent service centers, use the function +## @code{qnclosedsinglemvald} instead. +## +## Additionally, the normalization constant @math{G(n)}, @math{n=0, +## @dots{}, N} is computed; @math{G(n)} can be used in conjunction with +## the BCMP theorem to compute steady-state probabilities. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## Population size (number of requests in the system, @code{@var{N} @geq{} 0}). +## If @code{@var{N} == 0}, this function returns +## @code{@var{U} = @var{R} = @var{Q} = @var{X} = 0} +## +## @item S +## @code{@var{S}(k)} is the mean service time on server @math{k} +## (@code{@var{S}(k)>0}). +## +## @item V +## @code{@var{V}(k)} is the average number of visits to service center +## @math{k} (@code{@var{V}(k) @geq{} 0}). +## +## @item Z +## External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. +## +## @item m +## @code{@var{m}(k)} is the number of servers at center @math{k} +## (if @var{m} is a scalar, all centers have that number of servers). If +## @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); +## otherwise it is a regular queueing center (FCFS, LCFS-PR or PS) with +## @code{@var{m}(k)} servers. Default is @code{@var{m}(k) = 1} for all +## @math{k} (each service center has a single server). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## If @math{k} is a FCFS, LCFS-PR or PS node (@code{@var{m}(k) == 1}), +## then @code{@var{U}(k)} is the utilization of center @math{k}. If +## @math{k} is an IS node (@code{@var{m}(k) < 1}), then +## @code{@var{U}(k)} is the @emph{traffic intensity} defined as +## @code{@var{X}(k)*@var{S}(k)}. +## +## @item R +## @code{@var{R}(k)} is the response time at center @math{k}. +## The system response time @var{Rsys} +## can be computed as @code{@var{Rsys} = @var{N}/@var{Xsys} - Z} +## +## @item Q +## @code{@var{Q}(k)} is the average number of requests at center +## @math{k}. The number of requests in the system can be computed +## either as @code{sum(@var{Q})}, or using the formula +## @code{@var{N}-@var{Xsys}*@var{Z}}. +## +## @item X +## @code{@var{X}(k)} is the throughput of center @math{k}. The +## system throughput @var{Xsys} can be computed as +## @code{@var{Xsys} = @var{X}(1) / @var{V}(1)} +## +## @item G +## Normalization constants. @code{@var{G}(n+1)} corresponds to the value +## of the normalization constant @math{G(n)}, @math{n=0, @dots{}, N} as +## array indexes in Octave start from 1. @math{G(n)} can be used in +## conjunction with the BCMP theorem to compute steady-state +## probabilities. +## +## @end table +## +## @seealso{qnclosedsinglemvald} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X G] = qnclosedsinglemva( N, S, V, m, Z ) + + if ( nargin < 3 || nargin > 5 ) + print_usage(); + endif + + isscalar(N) && N >= 0 || \ + usage( "N must be >= 0" ); + isvector(S) || \ + usage( "S must be a vector" ); + S = S(:)'; # make S a row vector + + isvector(V) || \ + usage( "V must be a vector" ); + V = V(:)'; # make V a row vector + + K = length(S); # Number of servers + + if ( nargin < 4 ) + m = ones(1,K); + else + isvector(m) || \ + usage( "m must be a vector" ); + m = m(:)'; # make m a row vector + endif + + [err S V m] = common_size(S, V, m); + (err == 0) || \ + usage( "S, V and m are of incompatible size" ); + all(S>=0) || \ + usage( "S must be a vector >= 0" ); + all(V>=0) || \ + usage( "V must be a vector >= 0" ); + + if ( nargin < 5 ) + Z = 0; + else + (isscalar(Z) && Z >= 0) || \ + usage( "Z must be >= 0" ); + endif + + U = R = Q = X = zeros( 1, K ); + G = zeros(1,N+1); G(1) = 1; + if ( N == 0 ) # Trivial case of empty population: just return all zeros + return; + endif + + ## Initialize results + p = zeros( K, max(m)+1 ); # p(i,j+1) is the probability that there are j jobs at server i + p(:,1) = 1; + X_s = 0; # System throughput + + i_single = find( m==1 ); + i_multi = find( m>1 ); + i_delay = find( m<1 ); + + ## Main MVA loop, iterates over the population size + for n=1:N + + R(i_single) = S(i_single) .* (1 + Q(i_single)); + for i=i_multi # I cannot easily vectorize this + j=0:m(i)-2; + R(i) = S(i) / m(i) * (1+Q(i)+dot( m(i)-j-1, p( i, 1+j ) ) ); + endfor + R(i_delay) = S(i_delay); + + R_s = dot( V, R ); # System response time + X_s = n / ( Z + R_s ); # System Throughput + Q = X_s * ( V .* R ); + G(1+n) = G(n) / X_s; + + ## prepare for next iteration + lambda_i = V * X_s; # lambda_i(i) is the node i throughput + for i=i_multi + j=1:m(i)-1; # range + p(i, j+1) = lambda_i(i) .* S(i) ./ min( j,m(i) ) .* p(i,j); + p(i,1) = 1 - 1/m(i) * ... + (V(i)*S(i)*X_s + dot( m(i)-j, p(i,j+1)) ); + endfor + + endfor + X = X_s * V; # Service centers throughput + U(i_single) = X(i_single) .* S(i_single); + U(i_delay) = X(i_delay) .* S(i_delay); + U(i_multi) = X(i_multi) .* S(i_multi) ./ m(i_multi); +endfunction + +#{ + +## This function is slightly faster (and more compact) than the above +## when all servers are single-server or delay centers. Improvements are +## quite small (10%-15% faster, depends on the network size), so at the +## moment it is commented out. +function [U R Q X G] = __qnclosedsinglemva_fast( N, S, V, m, Z ) + U = R = Q = X = zeros( 1, length(S) ); + X_s = 0; # System throughput + G = zeros(1,N+1); G(1) = 1; + + ## Main MVA loop + for n=1:N + R = S .* (1+Q.*(m==1)); + R_s = dot( V, R ); # System response time + X_s = n / ( Z + R_s ); # System Throughput + Q = X_s * ( V .* R ); + G(1+n) = G(n) / X_s; + endfor + X = X_s * V; # Service centers throughput + U = X .* S; +endfunction + +#} + +%!test +%! fail( "qnclosedsinglemva()", "Invalid" ); +%! fail( "qnclosedsinglemva( 10, [1 2], [1 2 3] )", "S, V and m" ); +%! fail( "qnclosedsinglemva( 10, [-1 1], [1 1] )", ">= 0" ); + +## Check degenerate case of N==0 (LI case) +%!test +%! N = 0; +%! S = [1 2 3 4]; +%! V = [1 1 1 4]; +%! [U R Q X] = qnclosedsinglemva(N, S, V); +%! assert( U, 0*S ); +%! assert( R, 0*S ); +%! assert( Q, 0*S ); +%! assert( X, 0*S ); + +## Check degenerate case of N==0 (LD case) +%!test +%! N = 0; +%! S = [1 2 3 4]; +%! V = [1 1 1 4]; +%! m = [2 3 4 5]; +%! [U R Q X] = qnclosedsinglemva(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] = qnclosedsinglemva(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 ) ); + +%!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] = qnclosedsinglemva(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 ) ); + +%!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] = qnclosedsinglemva(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 ) ); + +%!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] = qnclosedsinglemva(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] = qnclosedsinglemva(n, S, V); +%! Xs = X(1)/V(1); +%! Rs = dot(R,V); +%! # Compare with balanced system bounds +%! [Xlbsb Xubsb Rlbsb Rubsb] = qnclosedbsb( n, S .* V ); +%! assert( Xlbsb<=Xs ); +%! assert( Xubsb>=Xs ); +%! assert( Rlbsb<=Rs ); +%! assert( Rubsb>=Rs ); +%! # Compare with asymptotic bounds +%! [Xlab Xuab Rlab Ruab] = qnclosedab( n, S .* V ); +%! assert( Xlab<=Xs ); +%! assert( Xuab>=Xs ); +%! assert( Rlab<=Rs ); +%! assert( Ruab>=Rs ); +%! endfor + +## Example from Schwetman (figure 7, page 9 of +## http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1258&context=cstech +## "Testing network-of-queues software, technical report CSD-TR 330, +## Purdue University). Note that the results for that network (table 9 +## of the reference above) seems to be wrong. The "correct" results +## below have been computed using the multiclass MVA implementation of +## JMT (http://jmt.sourceforge.net/) +%!test +%! V = [ 1.00 0.45 0.50 0.00; \ +%! 1.00 0.00 0.50 0.49 ]; +%! N = [3 2]; +%! S = [0.01 0.09 0.10 0.08; \ +%! 0.05 0.09 0.10 0.08]; +%! [U R Q X] = qnclosedmultimva(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 ); + +%!demo +%! S = [ 0.125 0.3 0.2 ]; +%! V = [ 16 10 5 ]; +%! N = 20; +%! m = ones(1,3); +%! Z = 4; +%! [U R Q X] = qnclosedsinglemva(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 ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedsinglemvaapprox.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,237 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedsinglemvaapprox (@var{N}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedsinglemvaapprox (@var{N}, @var{S}, @var{V}, @var{m}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedsinglemvaapprox (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedsinglemvaapprox (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedsinglemvaapprox (@var{N}, @var{S}, @var{V}, @var{m}, @var{Z}, @var{tol}, @var{iter_max}) +## +## @cindex Mean Value Analysys (MVA), approximate +## @cindex Approximate MVA +## @cindex Closed network, single class +## @cindex Closed network, approximate analysis +## +## Analyze closed, single class queueing networks using the Approximate +## Mean Value Analysis (MVA) algorithm. This function is based on +## approximating the number of customers seen at center @math{k} when a +## new request arrives as @math{Q_k(N) \times (N-1)/N}. This function +## only handles single-server and delay centers; if your network +## contains general load-dependent service centers, use the function +## @code{qnclosedsinglemvald} instead. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## Population size (number of requests in the system, @code{@var{N} > 0}). +## +## @item S +## @code{@var{S}(k)} is the mean service time on server @math{k} +## (@code{@var{S}(k)>0}). +## +## @item V +## @code{@var{V}(k)} is the average number of visits to service center +## @math{k} (@code{@var{V}(k) @geq{} 0}). +## +## @item m +## @code{@var{m}(k)} is the number of servers at center @math{k} +## (if @var{m} is a scalar, all centers have that number of servers). If +## @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); if +## @code{@var{m}(k) == 1}, center @math{k} is a regular queueing +## center (FCFS, LCFS-PR or PS) with one server (default). This function +## does not support multiple server nodes (@code{@var{m}(k) > 1}). +## +## @item Z +## External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. +## +## @item tol +## Stopping tolerance. The algorithm stops when the maximum relative difference +## between the new and old value of the queue lengths @var{Q} becomes +## less than the tolerance. Default is @math{10^{-5}}. +## +## @item iter_max +## Maximum number of iterations (@code{@var{iter_max}>0}. +## The function aborts if convergenge is not reached within the maximum +## number of iterations. Default is 100. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## If @math{k} is a FCFS, LCFS-PR or PS node (@code{@var{m}(k) == 1}), +## then @code{@var{U}(k)} is the utilization of center @math{k}. If +## @math{k} is an IS node (@code{@var{m}(k) < 1}), then +## @code{@var{U}(k)} is the @emph{traffic intensity} defined as +## @code{@var{X}(k)*@var{S}(k)}. +## +## @item R +## @code{@var{R}(k)} is the response time at center @math{k}. +## The system response time @var{Rsys} +## can be computed as @code{@var{Rsys} = @var{N}/@var{Xsys} - Z} +## +## @item Q +## @code{@var{Q}(k)} is the average number of requests at center +## @math{k}. The number of requests in the system can be computed +## either as @code{sum(@var{Q})}, or using the formula +## @code{@var{N}-@var{Xsys}*@var{Z}}. +## +## @item X +## @code{@var{X}(k)} is the throughput of center @math{k}. The +## system throughput @var{Xsys} can be computed as +## @code{@var{Xsys} = @var{X}(1) / @var{V}(1)} +## +## @end table +## +## @seealso{qnclosedsinglemva,qnclosedsinglemvald} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnclosedsinglemvaapprox( N, S, V, m, Z, tol, iter_max ) + + if ( nargin < 3 || nargin > 7 ) + print_usage(); + endif + + isscalar(N) && N >= 0 || \ + usage( "N must be >= 0" ); + isvector(S) || \ + usage( "S must be a vector" ); + isvector(V) || \ + usage( "V must be a vector" ); + S = S(:)'; # make S a row vector + V = V(:)'; # make V a row vector + + K = length(S); # Number of servers + + if ( nargin < 4 ) + m = ones(1,K); + else + isvector(m) || \ + usage( "m must be a vector" ); + m = m(:)'; # make m a row vector + endif + + [err S V m] = common_size(S, V, m); + (err == 0) || \ + usage( "S, V and m are of incompatible size" ); + all(S>=0) || \ + usage( "S must be a vector >= 0" ); + all(V>=0) || \ + usage( "V must be a vector >= 0" ); + all(m<=1) || \ + usage( "Vector m must be <= 1 (this function supports IS and single-server nodes only)" ); + + if ( nargin < 5 ) + Z = 0; + else + (isscalar(Z) && Z >= 0) || \ + usage( "Z must be >= 0" ); + endif + + if ( nargin < 6 ) + tol = 1e-5; + else + ( isscalar(tol) && tol>0 ) || \ + usage("tol must be a positive scalar"); + endif + + if ( nargin < 7 ) + iter_max = 100; + else + ( isscalar(iter_max) && iter_max > 0 ) || \ + usage("iter_max must be a positive integer"); + endif + + U = R = Q = X = zeros( 1, K ); + ## Trivial case of empty population: just return all zeros + if ( N == 0 ) + return; + endif + + Q = N/K * ones(1,K); # initialize queue lengths + iter = 0; + do + iter++; + Qold = Q; + A = (N-1)/N * Q; + R = S.*(1+A.*(m==1)); + Rs = dot(V,R); + Xs = N/(Z+Rs); + Q = Xs*(V.*R); + err = norm((Q-Qold)./Qold, "inf"); + until (err < tol || iter>iter_max); + if ( iter > iter_max ) + warning( "qnclosedsinglemvaapprox(): Convergence not reached after %d iterations", iter_max ); + endif + X = Xs * V; + U = X .* S; +endfunction +%!test +%! fail( "qnclosedsinglemvaapprox()", "Invalid" ); +%! fail( "qnclosedsinglemvaapprox( 10, [1 2], [1 2 3] )", "S, V and m" ); +%! fail( "qnclosedsinglemvaapprox( 10, [-1 1], [1 1] )", ">= 0" ); +%! fail( "qnclosedsinglemvaapprox( 10, [1 2], [1 2], [1 2] )", "supports"); +%! fail( "qnclosedsinglemvaapprox( 10, [1 2], [1 2], [1 1], 0, -1)", "tol"); + +%!test +%! # Example p. 117 Lazowska et al. +%! S = [0.605 2.1 1.35]; +%! V = [1 1 1]; +%! N = 3; +%! Z = 15; +%! m = 1; +%! [U R Q X] = qnclosedsinglemvaapprox(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] = qnclosedsinglemva(n,S,V,m,Z); +%! Xmva(n) = X(1)/V(1); +%! Rmva(n) = dot(R,V); +%! [U R Q X] = qnclosedsinglemvaapprox(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"); +%! 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"); +%! ylabel("Response Time R(n)"); +%! xlabel("Number of Requests n");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnclosedsinglemvald.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,198 @@ +## Copyright (C) 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedsinglemvald (@var{N}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnclosedsinglemvald (@var{N}, @var{S}, @var{V}, @var{Z}) +## +## @cindex Mean Value Analysys (MVA) +## @cindex closed network, single class +## @cindex load-dependent service center +## +## Exact MVA algorithm for closed, single class queueing networks +## with load-dependent service centers. This function supports +## FCFS, LCFS-PR, PS and IS nodes. For networks with only fixed-rate +## service centers and multiple-server nodes, the function +## @code{qnclosedsinglemva} is more efficient. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## Population size (number of requests in the system, @code{@var{N} @geq{} 0}). +## If @code{@var{N} == 0}, this function returns @code{@var{U} = @var{R} = @var{Q} = @var{X} = 0} +## +## @item S +## @code{@var{S}(k,n)} is the mean service time at center @math{k} +## where there are @math{n} requests, @math{1 @leq{} n +## @leq{} N}. @code{@var{S}(k,n)} @math{= 1 / \mu_{k,n}}, +## where @math{\mu_{k,n}} is the service rate of center @math{k} +## when there are @math{n} requests. +## +## @item V +## @code{@var{V}(k)} is the average number +## of visits to service center @math{k} (@code{@var{V}(k) @geq{} 0}). +## +## @item Z +## external delay ("think time", @code{@var{Z} @geq{} 0}); default 0. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## @code{@var{U}(k)} is the utilization of service center @math{k}. The +## utilization is defined as the probability that service center +## @math{k} is not empty, that is, @math{U_k = 1-\pi_k(0)} where +## @math{\pi_k(0)} is the steady-state probability that there are 0 +## jobs at service center @math{k}. +## +## @item R +## @code{@var{R}(k)} is the response time on service center @math{k}. +## +## @item Q +## @code{@var{Q}(k)} is the average number of requests in service center +## @math{k}. +## +## @item X +## @code{@var{X}(k)} is the throughput of service center @math{k}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnclosedsinglemvald( N, S, V, Z ) + + if ( nargin < 3 || nargin > 4 ) + print_usage(); + endif + + isvector(V) && all(V>=0) || \ + usage( "V must be a vector >= 0" ); + V = V(:)'; # make V a row vector + K = length(V); # Number of servers + isscalar(N) && N >= 0 || \ + usage( "N must be >= 0" ); + ( ismatrix(S) && rows(S) == K && columns(S) >= N ) || \ + usage( "S size mismatch: is %dx%d, should be %dx%d", rows(S), columns(S), K, N ); + all(all(S>=0)) || \ + usage( "S must be >= 0" ); + + if ( nargin < 4 ) + Z = 0; + else + isscalar(Z) && Z>=0 || \ + usage( "Z must be >= 0" ); + endif + + ## Initialize results + p = zeros( K, N+1 ); # p(k,i+1) is the probability that there are i jobs at server k, given that the network population is j + p(:,1) = 1; + U = R = Q = X = zeros( 1, K ); + X_s = 0; # System throughput + + ## Main MVA loop, iterates over the population size + for n=1:N # over population size + + j=1:n; + ## for i=1:K + ## R(i) = sum( j.*S(i,j).*p(i,j) ); + ## endfor + R = sum( repmat(j,K,1).*S(:,1:n).*p(:,1:n), 2)'; + + R_s = dot( V, R ); # System response time + X_s = n / (Z+R_s); # System Throughput + ## G_N = G_Nm1 / X_s; G_Nm1 = G_N; + + ## prepare for next iteration + for i=1:K + p(i, 1+j) = X_s * S(i,j) .* p(i,j) * V(i); + p(i, 1) = 1-sum(p(i,1+j)); + endfor + endfor + Q = X_s * ( V .* R ); + U = 1-p(:,1)'; # Service centers utilization + X = X_s * V; # Service centers throughput +endfunction + +## Check degenerate case of N==0 (general LD case) +%!test +%! N = 0; +%! S = [1 2; 3 4; 5 6; 7 8]; +%! V = [1 1 1 4]; +%! [U R Q X] = qnclosedsinglemvald(N, S, V); +%! assert( U, 0*V ); +%! assert( R, 0*V ); +%! assert( Q, 0*V ); +%! assert( X, 0*V ); + +%!test +%! # Exsample 3.42 p. 577 Jain +%! V = [ 16 10 5 ]; +%! N = 20; +%! S = [ 0.125 0.3 0.2 ]; +%! Sld = repmat( S', 1, N ); +%! Z = 4; +%! [U1 R1 Q1 X1] = qnclosedsinglemvald(N,Sld,V,Z); +%! [U2 R2 Q2 X2] = qnclosedsinglemva(N,S,V,ones(1,3),Z); +%! assert( U1, U2, 1e-3 ); +%! assert( R1, R2, 1e-3 ); +%! assert( Q1, Q2, 1e-3 ); +%! assert( X1, X2, 1e-3 ); + +%!test +%! # Example 8.7 p. 349 Bolch et al. +%! N = 3; +%! Sld = 1 ./ [ 2 4 4; \ +%! 1.667 1.667 1.667; \ +%! 1.25 1.25 1.25; \ +%! 1 2 3 ]; +%! V = [ 1 .5 .5 1 ]; +%! [U R Q X] = qnclosedsinglemvald(N,Sld,V); +%! assert( Q, [0.624 0.473 0.686 1.217], 1e-3 ); +%! assert( R, [0.512 0.776 1.127 1], 1e-3 ); +%! assert( all( U<=1) ); + +%!test +%! # Example 8.4 p. 333 Bolch et al. +%! N = 3; +%! S = [ .5 .6 .8 1 ]; +%! m = [2 1 1 N]; +%! Sld = zeros(3,N); +%! Sld(1,:) = .5 ./ [1 2 2]; +%! Sld(2,:) = [.6 .6 .6]; +%! Sld(3,:) = [.8 .8 .8]; +%! Sld(4,:) = 1 ./ [1 2 3]; +%! V = [ 1 .5 .5 1 ]; +%! [U1 R1 Q1 X1] = qnclosedsinglemvald(N,Sld,V); +%! [U2 R2 Q2 X2] = qnclosedsinglemva(N,S,V,m); +%! ## Note that qnclosedsinglemvald computes the utilization in a different +%! ## way as qnclosedsinglemva; in fact, qnclosedsinglemva knows that service +%! ## center i has m(i)>1 servers, but qnclosedsinglemvald does not. Thus, +%! ## utilizations for multiple-server nodes cannot be compared +%! assert( U1([2,3]), U2([2,3]), 1e-3 ); +%! assert( R1, R2, 1e-3 ); +%! assert( Q1, Q2, 1e-3 ); +%! assert( X1, X2, 1e-3 ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qncmva.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,170 @@ +## Copyright (C) 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmva (@var{N}, @var{S}, @var{Sld}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qncmva (@var{N}, @var{S}, @var{Sld}, @var{V}, @var{Z}) +## +## @cindex Mean Value Analysys (MVA) +## @cindex CMVA +## +## Implementation of the Conditional MVA (CMVA) algorithm, a numerically +## stable variant of MVA for load-dependent servers. CMVA is described +## in G. Casale, @cite{A Note on Stable Flow-Equivalent Aggregation in +## Closed Networks}. The network is made of @math{M} service centers and +## a delay center. Servers @math{1, \ldots, M-1} are load-independent; +## server @math{M} is load-dependent. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## Population size (number of requests in the system, @code{@var{N} @geq{} 0}). +## If @code{@var{N} == 0}, this function returns +## @code{@var{U} = @var{R} = @var{Q} = @var{X} = 0} +## +## @item S +## @code{@var{S}(k)} is the mean service time on server @math{k = 1, @dots{}, M-1} +## (@code{@var{S}(k) > 0}). +## +## @item Sld +## @code{@var{Sld}(n)} is the mean service time on server @math{M} +## when there are @math{n} requests, @math{n=1, @dots{}, N}. +## @code{@var{Sld}(n) = } @math{1 / \mu(n)}, where @math{\mu(n)} is the +## service rate at center @math{N} when there are @math{n} requests. +## +## @item V +## @code{@var{V}(k)} is the average number of visits to service center +## @math{k= 1, @dots{}, M} (@code{@var{V}(k) @geq{} 0}). +## +## @item Z +## External delay for customers (@code{@var{Z} @geq{} 0}). Default is 0. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## @code{@var{U}(k)} is the utilization of center @math{k=1, @dots{}, M} +## +## @item R +## @code{@var{R}(k)} is the response time at center @math{k=1, @dots{}, M}. +## The system response time @var{Rsys} +## can be computed as @code{@var{Rsys} = @var{N}/@var{Xsys} - Z} +## +## @item Q +## @code{@var{Q}(k)} is the average number of requests at center +## @math{k=1, @dots{}, M}. +## +## @item X +## @code{@var{X}(k)} is the throughput of center @math{k=1, @dots{}, M}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qncmva( N, S, Sld, V, Z ) + + if ( nargin < 4 || nargin > 5 ) + print_usage(); + endif + + isscalar(N) && N >= 0 || \ + usage("N must be a positive scalar"); + + isvector(S) || \ + usage("S must be a vector"); + S = S(:)'; # make S a row vector + M = length(S)+1; # number of service centers (escluding the delay center) + + isvector(Sld) && length(Sld) == N && all(Sld>=0) || \ + usage("Sld must be a vector with %d elements >= 0", N); + Sld = Sld(:)'; # Make Sld a row vector + + isvector(V) && length(V) == M && all(V>=0) || \ + usage("V must be a vector with %d elements", M); + V = V(:)'; # Make V a row vector + + if ( nargin == 5 ) + isscalar(Z) && Z>=0 || \ + usage("Z must be nonnegative"); + else + Z = 0; + endif + + if ( N == 0 ) + U = R = Q = X = zeros(1,M); + endif + + D = S .* V(1:M-1); # service demands + Ri = Qi = zeros(M,N+1,N+1); + DM = Xs = zeros(N+1,N+1); # system throughput + + ## Main MVA loop + for n=1:N + for t=1:(N-n+1) + if ( n==1 ) + DM(1+n,t) = Sld(t)*V(M); + else + DM(1+n,t) = Xs(n,t)/Xs(n,t+1)*DM(n,t); + endif + i=1:(M-1); + Ri(i,1+n,t) = D(i).*(1+Qi(i,n,t))'; + Ri(M,1+n,t) = DM(1+n,t).*(1+Qi(M,n,t+1)); + Xs(1+n,t) = n/(Z+sum(Ri(:,1+n,t))); + i=1:(M-1); + Qi(i,1+n,t) = D(i) .* Xs(1+n,t) .* (1+Qi(i,n,t))'; + Qi(M,1+n,t) = DM(1+n,t).*Xs(1+n,t).*(1+Qi(M,n,t+1)); + endfor + endfor + X = Xs(1+N,1)*V; + Q = Qi(:,1+N,1)'; + R = Ri(:,1+N,1)'; + U = [D DM(1+N,1)] .* X; +endfunction +%!test +%! N=5; +%! S = [1 0.3 0.8 0.9]; +%! V = [1 1 1 1]; +%! [U1 R1 Q1 X1] = qncmva( N, S(1:3), repmat(S(4),1,N), V ); +%! [U2 R2 Q2 X2] = qnclosedsinglemva(N, S, V); +%! assert( U1, U2, 1e-5 ); +%! assert( R1, R2, 1e-5 ); +%! assert( Q1, Q2, 1e-5 ); +%! assert( X1, X2, 1e-5 ); + +%!test +%! N=5; +%! S = [1 1 1 1 1; \ +%! 1 1 1 1 1; \ +%! 1 1 1 1 1; \ +%! 1 1/2 1/3 1/4 1/5]; +%! V = [1 1 1 1]; +%! [U1 R1 Q1 X1] = qncmva( N, S(1:3,1), S(4,:), V ); +%! [U2 R2 Q2 X2] = qnclosedsinglemvald(N, S, V); +%! assert( U1, U2, 1e-5 ); +%! assert( R1, R2, 1e-5 ); +%! assert( Q1, Q2, 1e-5 ); +%! assert( X1, X2, 1e-5 ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnconvolution.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,236 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qnconvolution (@var{N}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qnconvolution (@var{N}, @var{S}, @var{V}, @var{m}) +## +## @cindex closed network +## @cindex normalization constant +## @cindex convolution algorithm +## +## This function implements the @emph{convolution algorithm} for +## computing steady-state performance measures of product-form, +## single-class closed queueing networks. Load-independent service +## centers, multiple servers (@math{M/M/m} queues) and IS nodes are +## supported. For general load-dependent service centers, use the +## @code{qnconvolutionld} function instead. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## Number of requests in the system (@code{@var{N}>0}). +## +## @item S +## @code{@var{S}(k)} is the average service time on center @math{k} +## (@code{@var{S}(k) @geq{} 0}). +## +## @item V +## @code{@var{V}(k)} is the visit count of service center @math{k} +## (@code{@var{V}(k) @geq{} 0}). +## +## @item m +## @code{@var{m}(k)} is the number of servers at center +## @math{k}. If @code{@var{m}(k) < 1}, center @math{k} is a delay center (IS); +## if @code{@var{m}(k) @geq{} 1}, center @math{k} +## it is a regular @math{M/M/m} queueing center with @code{@var{m}(k)} +## identical servers. Default is @code{@var{m}(k) = 1} for all @math{k}. +## +## @end table +## +## @strong{OUTPUT} +## +## @table @var +## +## @item U +## @code{@var{U}(k)} is the utilization of center @math{k}. +## For IS nodes, @code{@var{U}(k)} is the @emph{traffic intensity}. +## +## @item R +## @code{@var{R}(k)} is the average response time of center @math{k}. +## +## @item Q +## @code{@var{Q}(k)} is the average number of customers at center +## @math{k}. +## +## @item X +## @code{@var{X}(k)} is the throughput of center @math{k}. +## +## @item G +## Vector of normalization constants. @code{@var{G}(n+1)} contains the value of +## the normalization constant with @math{n} requests +## @math{G(n)}, @math{n=0, @dots{}, N}. +## +## @end table +## +## @seealso{qnconvolutionld} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X G] = qnconvolution( N, S, V, m ) + + if ( nargin < 3 || nargin > 4 ) + print_usage(); + endif + + ( isscalar(N) && N>0 ) || \ + usage( "K must be a positive scalar" ); + K = N; # To be compliant with the reference, we use K to denote the population size + ( isvector(S) && all(S >= 0) ) || \ + usage( "S must be a vector of positive scalars" ); + S = S(:)'; # make S a row vector + N = length(S); # Number of service centers + ( isvector(V) && size_equal(V,S) ) || \ + usage( "V must be a vector of the same length as S" ); + V = V(:)'; + + if ( nargin < 4 ) + m = ones(1,N); + else + isvector(m) || \ + usage( "m must be a vector" ); + m = m(:)'; + [err m S] = common_size(m, S); + (err == 0) || \ + usage( "m and S have incompatible size" ); + endif + + ## First, we remember the indexes of IS nodes + i_delay = find(m<1); + + m( i_delay ) = K; # IS nodes are handled as if they were M/M/K nodes with number of servers equal to the population size K, such that queueing never occurs. + + ## Initialization + G_n = G_nm1 = zeros(1,K+1); G_n(1) = 1; + F_n = zeros(N,K+1); F_n(:,1) = 1; + k=0:K; G_nm1(k+1) = F_n(1,k+1) = F(1,k,V,S,m); + ## Main convolution loop + for n=2:N + k=1:K; F_n(n,1+k) = F(n,k,V,S,m); + G_n = conv( F_n(n,:), G_nm1(:) )(1:K+1); + G_nm1 = G_n; + endfor + ## Done computation of G(n,k). + G = G_n; + G = G(:)'; # ensure G is a row vector + ## Computes performance measures + X = V*G(K)/G(K+1); + U = X .* S ./ m; + ## Adjust utilization of delay centers + U(i_delay) = X(i_delay) .* S(i_delay); + Q = zeros(1,N); + i_multi = find(m>1); + for i=i_multi + G_N_i = zeros(1,K+1); + G_N_i(1) = 1; + for k=1:K + j=1:k; + G_N_i(k+1) = G(k+1)-dot( F_n(i,j+1), G_N_i(k-j+1) ); + endfor + k=0:K; + p_i(k+1) = F_n(i,k+1)./G(K+1).*G_N_i(K-k+1); + Q(i) = dot( k, p_i( k+1 ) ); + endfor + i_single = find(m==1); + for i=i_single + k=1:K; + Q(i) = sum( ( V(i)*S(i) ) .^ k .* G(K+1-k)/G(K+1) ); + endfor + R = Q ./ X; +endfunction + +%!test +%! # Example 8.1 p. 318 Bolch et al. +%! K=3; +%! S = [ 1/0.8 1/0.6 1/0.4 ]; +%! m = [2 3 1]; +%! V = [ 1 .667 .2 ]; +%! [U R Q X G] = qnconvolution( 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] = qnclosedsinglemva(K, S, V); +%! [U_con R_con Q_con X_con G_con] = qnconvolution(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] = qnclosedsinglemva(K, S, V, m); +%! [U_con R_con Q_con X_con G] = qnconvolution(K, S, V, m ); +%! assert( U_mva, U_con, 1e-5 ); +%! assert( R_mva, R_con, 1e-5 ); +%! assert( Q_mva, Q_con, 1e-5 ); +%! assert( X_mva, X_con, 1e-5 ); + +## result = F(i,j,v,S,m) +## +## Helper fuction to compute F(i,j) as defined in Eq 7.61 p. 289 of +## Bolch, Greiner, de Meer, Trivedi "Queueing Networks and Markov +## Chains: Modeling and Performance Evaluation with Computer Science +## Applications", Wiley, 1998. This function has been vectorized, +## and accepts a vector as parameter j. +function result = F(i,j,v,S,m) + isscalar(i) || \ + usage( "i must be a scalar" ); + k_i = j; + if ( m(i) == 1 ) + result = ( v(i)*S(i) ).^k_i; + else + ii = find(k_i<=m(i)); ## if k_i<=m(i) + result(ii) = ( v(i)*S(i) ).^k_i(ii) ./ factorial(k_i(ii)); + ii = find(k_i>m(i)); ## if k_i>m(i) + result(ii) = ( v(i)*S(i) ).^k_i(ii) ./ ( factorial(m(i))*m(i).^(k_i(ii)-m(i)) ); + endif +endfunction + +%!demo +%! k = [1 2 0]; +%! K = sum(k); # 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] = qnconvolution( K, S, V, m ); +%! p = [0 0 0]; # initialize p +%! # Compute the probability to have k(i) jobs at service center i +%! for i=1:3 +%! p(i) = (V(i)*S(i))^k(i) / G(K+1) * \ +%! (G(K-k(i)+1) - V(i)*S(i)*G(K-k(i)) ); +%! printf("k(%d)=%d prob=%f\n", i, k(i), p(i) ); +%! endfor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnconvolutionld.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,220 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{G}] =} qnconvolutionld (@var{N}, @var{S}, @var{V}) +## +## @cindex closed network +## @cindex normalization constant +## @cindex convolution algorithm +## @cindex load-dependent service center +## +## This function implements the @emph{convolution algorithm} for +## product-form, single-class closed queueing networks with general +## load-dependent service centers. +## +## This function computes steady-state performance measures for +## single-class, closed networks with load-dependent service centers +## using the convolution algorithm; the normalization constants are also +## computed. The normalization constants are returned as vector +## @code{@var{G}=[@var{G}(1), @dots{}, @var{G}(N+1)]} where +## @code{@var{G}(i+1)} is the value of @math{G(i)}. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## Number of requests in the system (@code{@var{N}>0}). +## +## @item S +## @code{@var{S}(k,n)} is the mean service time at center @math{k} +## where there are @math{n} requests, @math{1 @leq{} n +## @leq{} N}. @code{@var{S}(k,n)} @math{= 1 / \mu_{k,n}}, +## where @math{\mu_{k,n}} is the service rate of center @math{k} +## when there are @math{n} requests. +## +## @item V +## @code{@var{V}(k)} is the visit count of service center @math{k} +## (@code{@var{V}(k) @geq{} 0}). The length of @var{V} is the number of +## servers @math{K} in the network. +## +## @end table +## +## @strong{OUTPUT} +## +## @table @var +## +## @item U +## @code{@var{U}(k)} is the utilization of center @math{k}. +## +## @item R +## @code{@var{R}(k)} is the average response time at center @math{k}. +## +## @item Q +## @code{@var{Q}(k)} is the average number of customers in center @math{k}. +## +## @item X +## @code{@var{X}(k)} is the throughput of center @math{k}. +## +## @item G +## Normalization constants (vector). @code{@var{G}(n+1)} +## corresponds to @math{G(n)}, as array indexes in Octave start +## from 1. +## +## @end table +## +## @seealso{qnconvolution} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X G] = qnconvolutionld( N, S, V ) + + if ( nargin != 3 ) + print_usage(); + endif + + ( isscalar(N) && N>0 ) || \ + usage( "N must be a positive scalar" ); + K = N; # To be compliant with the reference, we denote K as the population size + ( isvector(V) ) || \ + usage( "V must be a vector" ); + V = V(:)'; # Make V a row vector + N = length(V); # Number of service centers + if ( isnumeric(S) ) + ( rows(S) == N && columns(S) == K) || \ + usage( sprintf("S size mismatch: is %dx%d, should be %dx%d", rows(S), columns(S),K,N ) ); + all( all(S>=0) ) || \ + usage( "S must be >=0" ); + endif + + ## Initialization + G_n = G_nm1 = zeros(1,K+1); G_n(1) = 1; + F_n = zeros(N,K+1); F_n(:,1) = 1; + for k=0:K + G_nm1(k+1) = F_n(1,k+1) = F(1,k,V,S); + endfor + ## Main convolution loop + for n=2:N + for k=2:K+1 + F_n(n,k) = F(n,k-1,V,S); + endfor + G_n = conv( F_n(n,:), G_nm1(:) )(1:K+1); + G_nm1 = G_n; + endfor + ## Done computation of G(n,k). + G = G_n; + G = G(:)'; # ensure G is a row vector + ## Computes performance measures + X = V*G(K)/G(K+1); + Q = U = zeros(1,N); + for i=1:N + G_N_i = zeros(1,K+1); + G_N_i(1) = 1; + for k=1:K + j=1:k; + G_N_i(k+1) = G(k+1)-dot( F_n(i,j+1), G_N_i(k-j+1) ); + endfor + k=0:K; + p_i(k+1) = F_n(i,k+1)./G(K+1).*G_N_i(K-k+1); + Q(i) = dot( k, p_i( k+1 ) ); + U(i) = 1-p_i(1); + endfor + R = Q ./ X; +endfunction +%!test +%! K=3; +%! S = [ 1 1 1; 1 1 1 ]; +%! V = [ 1 .667 .2 ]; +%! fail( "qnconvolutionld(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] = qnconvolutionld( 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] = qnclosedsinglemva(K, S, V); +%! [U_con R_con Q_con X_con G] = qnconvolutionld(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] = qnclosedsinglemva(K, S, V); +%! [U_con R_con Q_con X_con G] = qnconvolutionld(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] = qnconvolutionld( K, @S_function, V ); +%! assert( G, [1 2.861 4.218 4.465], 5e-3 ); +%! assert( X, [0.945 0.630 0.189], 1e-3 ); +%! assert( Q, [1.290 1.050 0.660], 1e-3 ); +%! assert( R, [1.366 1.667 3.496], 1e-3 ); + +## result = F(i,j,v,S) +## +## Helper fuction to compute a generalization of equation F(i,j) as +## defined in Eq 7.61 p. 289 of Bolch, Greiner, de Meer, Trivedi +## "Queueing Networks and Markov Chains: Modeling and Performance +## Evaluation with Computer Science Applications", Wiley, 1998. This +## generalization is taken from Schwetman, "Some Computational Aspects +## of Queueing Network Models", Technical Report CSD-TR 354, Dept. of +## CS, Purdue University, Dec 1980 (see definition of f_i(n) on p. 7). +function result = F(i,j,v,S) + k_i = j; + if ( k_i == 0 ) + result = 1; + else + result = v(i)^k_i * prod(S(i,1:k_i)); + endif +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnjackson.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,223 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnjackson (@var{lambda}, @var{S}, @var{P} ) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnjackson (@var{lambda}, @var{S}, @var{P}, @var{m} ) +## @deftypefnx {Function File} {@var{pr} =} qnjackson (@var{lambda}, @var{S}, @var{P}, @var{m}, @var{k}) +## +## @cindex open network, single class +## @cindex Jackson network +## +## With three or four input parameters, this function computes the +## steady-state occupancy probabilities for a Jackson network. With five +## input parameters, this function computes the steady-state probability +## @code{@var{pi}(j)} that there are @code{@var{k}(j)} requests at +## service center @math{j}. +## +## This function solves a subset of Jackson networks, with the +## following constraints: +## +## @itemize +## +## @item External arrival rates are load-independent. +## +## @item Service center @math{i} consists either of @code{@var{m}(i) @geq{} +## 1} identical servers with individual average service time +## @code{@var{S}(i)}, or of an Infinite Server (IS) node. +## +## @end itemize +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## @code{@var{lambda}(i)} is +## the external arrival rate to service center @math{i}. @var{lambda} +## must be a vector of length @math{N}, @code{@var{lambda}(i) @geq{} 0}. +## +## @item S +## @code{@var{S}(i)} is the average service time on service center @math{i} +## @var{S} must be a vector of length @math{N}, @code{@var{S}(i)>0}. +## +## @item P +## @code{@var{P}(i,j)} is the probability +## that a job which completes service at service center @math{i} proceeds +## to service center @math{j}. @var{P} must be a matrix of size +## @math{N \times N}. +## +## @item m +## @code{@var{m}(i)} is the number of servers at service center +## @math{i}. If @code{@var{m}(i) < 1}, service center @math{i} is an +## infinite-server node. Otherwise, it is a regular FCFS queueing center with +## @code{@var{m}(i)} servers. If this parameter is omitted, default is +## @code{@var{m}(i) = 1} for all @math{i}. If this parameter is a scalar, +## it will be promoted to a vector with the same size as @var{lambda}. +## Otherwise, @var{m} must be a vector of length @math{N}. +## +## @item k +## Compute the steady-state probability that there are @code{@var{k}(i)} +## requests at service center @math{i}. @var{k} must have the same length +## as @var{lambda}, with @code{@var{k}(i) @geq{} 0}. +## +## @end table +## +## @strong{OUTPUT} +## +## @table @var +## +## @item U +## If @math{i} is a FCFS node, then +## @code{@var{U}(i)} is the utilization of service center @math{i}. +## If @math{i} is an IS node, then @code{@var{U}(i)} is the +## @emph{traffic intensity} defined as @code{@var{X}(i)*@var{S}(i)}. +## +## @item R +## @code{@var{R}(i)} is the average response time of service center @math{i}. +## +## @item Q +## @code{@var{Q}(i)} is the average number of customers in service center +## @math{i}. +## +## @item X +## @code{@var{X}(i)} is the throughput of service center @math{i}. +## +## @item pr +## @code{@var{pr}(i)} is the steady state probability +## that there are @code{@var{k}(i)} requests at service center @math{i}. +## +## @end table +## +## @seealso{qnopen} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U_or_pi R Q X] = qnjackson( lambda, S, P, m, k ) + if ( nargin < 3 || nargin > 5 ) + print_usage(); + endif + ( isvector(lambda) && all(lambda>=0) ) || \ + usage( "lambda must be a vector >= 0" ); + lambda=lambda(:)'; # make lambda a row vector + N = length(lambda); + isvector(S) || \ + usage( "S must be a vector" ); + S = S(:)'; # make S a row vector + size_equal(lambda,S) || \ + usage( "lambda and S must of be of the same length" ); + all(S>0) || \ + usage( "S must be >0" ); + [N,N] == size(P) || \ + usage(" P must be a matrix of size length(lambda) x length(lambda)" ); + all(all(P>=0)) && all(sum(P,2)<=1) || \ + error( "P is not a transition probability matrix" ); + + if ( nargin < 4 ) + m = ones(1,N); + else + [errorcode, lambda, m] = common_size(lambda, m); + ( isvector(m) && (errorcode==0) ) || \ + usage("m and lambda must have the same length" ); + endif + + ## Compute the arrival rates using the traffic equation: + l = sum(lambda)*qnvisits( P, lambda ); + ## Check ergodicity + for i=1:N + if ( m(i)>0 && l(i)>=m(i)/S(i) ) + error( "Server %d not ergodic: arrival rate=%f, service rate=%f", i, l(i), m(i)/S(i) ); + endif + endfor + + U_or_pi = zeros(1,N); + + if ( nargin == 5 ) + + ( isvector(k) && size_equal(lambda,k) ) || \ + usage( "k must be a vector of the same size as lambda" ); + all(k>=0) || \ + usage( "k must be nonnegative" ); + + ## compute occupancy probability + rho = l .* S ./ m; + i = find(m==1); # M/M/1 queues + U_or_pi(i) = (1-rho(i)).*rho(i).^k(i); + for i=find(m>1) # M/M/k queues + k = [0:m(i)-1]; + pizero = 1 / (sum( (m(i)*rho(i)).^k ./ factorial(k)) + \ + (m(i)*rho(i))^m(i) / (factorial(m(i))*(1-rho(i))) \ + ); + ## Compute the marginal probabilities + U_or_pi(i) = pizero * (m(i)^min(k(i),m(i))) * (rho(i)^k(i)) / \ + factorial(min(m(i),k(i))); + endfor + i = find(m<1); # infinite server nodes + U_or_pi(i) = exp(-rho(i)).*rho(i).^k(i)./factorial(k(i)); + + else + + ## Compute steady-state parameters + U_or_pi = R = Q = X = zeros(1,N); # Initialize vectors + ## single server nodes + i = find( m==1 ); + [U_or_pi(i) R(i) Q(i) X(i)] = qnmm1(l(i),1./S(i)); + ## multi server nodes + i = find( m>1 ); + [U_or_pi(i) R(i) Q(i) X(i)] = qnmmm(l(i),1./S(i),m(i)); + ## infinite server nodes + i = find( m<1 ); + [U_or_pi(i) R(i) Q(i) X(i)] = qnmminf(l(i),1./S(i)); + + endif +endfunction +%!test +%! # Test various error conditions +%! fail( "qnjackson( [0.5 0.5], [0 1], [0 0; 0 0], [1 1])", "S must be" ); +%! fail( "qnjackson( [-1 1], [1 1], [0 0; 0 0], [1 1])", "lambda must be" ); +%! fail( "qnjackson( [0.5 0.5], [1 1], [1 1; 0 0], [1 1])", "P is not" ); +%! fail( "qnjackson( [0.5 0.5], [1 1], [1 0; -1 0], [1 1])", "P is not" ); +%! fail( "qnjackson( [0.5 0.5], [1 1 1], [0 0; 0 0], [1 1])", "lambda and S" ); +%! fail( "qnjackson( [0.5 0.5], [1 1], [0 0; 0 0], [1 1 1])", "m and lambda" ); +%! fail( "qnjackson( [0.5 0.5], [1 1], [0 0; 0 0], [1 1], [1 1 1])", "k must be" ); +%! fail( "qnjackson( [0.5 0.5], [1 1], [0 0; 0 0], [1 1], [1 -1])", "k must be" ); +%! fail( "qnjackson( [0 1], [2 2], [0 0.9; 0 0] )", "not ergodic" ); + +%!test +%! # Example 7.4 p. 287 Bolch et al. +%! S = [ 0.04 0.03 0.06 0.05 ]; +%! P = [ 0 0.5 0.5 0; 1 0 0 0; 0.6 0 0 0; 1 0 0 0 ]; +%! lambda = [0 0 0 4]; +%! k = [ 3 2 4 1 ]; +%! [U R Q X] = qnjackson( lambda, S, P, 1 ); +%! assert( X, [20 10 10 4], 1e-4 ); +%! assert( U, [0.8 0.3 0.6 0.2], 1e-2 ); +%! assert( R, [0.2 0.043 0.15 0.0625], 1e-3 ); +%! assert( Q, [4, 0.429 1.5 0.25], 1e-3 ); + +%!test +%! # Example 7.4 p. 287 Bolch et al. +%! S = [ 0.04 0.03 0.06 0.05 ]; +%! P = [ 0 0.5 0.5 0; 1 0 0 0; 0.6 0 0 0; 1 0 0 0 ]; +%! lambda = [0 0 0 4]; +%! k = [ 3 2 4 1 ]; +%! p_i = qnjackson( lambda, S, P, 1, k ); +%! assert( p_i, [0.1024, 0.063, 0.0518, 0.16], 1e-4 );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmarkov.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,344 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{lambda}, @var{S}, @var{C}, @var{P}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{lambda}, @var{S}, @var{C}, @var{P}, @var{m}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{N}, @var{S}, @var{C}, @var{P}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmarkov (@var{N}, @var{S}, @var{C}, @var{P}, @var{m}) +## +## @cindex closed network, multiple classes +## @cindex closed network, finite capacity +## @cindex blocking queueing network +## @cindex RS blocking +## +## Compute utilization, response time, average queue length and +## throughput for open or closed queueing networks with finite capacity. +## Blocking type is Repetitive-Service (RS). This function explicitly +## generates and solve the underlying Markov chain, and thus might +## require a large amount of memory. +## +## More specifically, networks which can me analyzed by this +## function have the following properties: +## +## @itemize @bullet +## +## @item There exists only a single class of customers. +## +## @item The network has @math{K} service centers. Center +## @math{i} has @math{m_i > 0} servers, and has a total (finite) capacity of +## @math{C_i \geq m_i} which includes both buffer space and servers. +## The buffer space at service center @math{i} is therefore +## @math{C_i - m_i}. +## +## @item The network can be open, with external arrival rate to +## center @math{i} equal to +## @math{\lambda_i}, or closed with fixed +## population size @math{N}. For closed networks, the population size +## @math{N} must be strictly less than the network capacity: @math{N < \sum_i C_i}. +## +## @item Average service times are load-independent. +## +## @item @math{P_{ij}} is the probability that requests completing +## execution at center @math{i} are transferred to +## center @math{j}, @math{i \neq j}. For open networks, a request may leave the system +## from any node @math{i} with probability @math{1-\sum_j P_{ij}}. +## +## @item Blocking type is Repetitive-Service (RS). Service +## center @math{j} is @emph{saturated} if the number of requests is equal +## to its capacity @code{C_j}. Under the RS blocking discipline, +## a request completing service at center @math{i} which is being +## transferred to a saturated server @math{j} is put back at the end of +## the queue of @math{i} and will receive service again. Center @math{i} +## then processes the next request in queue. External arrivals to a +## saturated servers are dropped. +## +## @end itemize +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## @itemx N +## If the first argument is a vector @var{lambda}, it is considered to be +## the external arrival rate @code{@var{lambda}(i) @geq{} 0} to service center +## @math{i} of an open network. If the first argument is a scalar, it is +## considered as the population size @var{N} of a closed network; in this case +## @var{N} must be strictly +## less than the network capacity: @code{@var{N} < sum(@var{C})}. +## +## @item S +## @code{@var{S}(i)} is the average service time at service center +## @math{i} +## +## @item C +## @code{@var{C}(i)} is the Capacity of service center @math{i}. The capacity includes both +## the buffer and server space @code{@var{m}(i)}. Thus the buffer space is +## @code{@var{C}(i)-@var{m}(i)}. +## +## @item P +## @code{@var{P}(i,j)} is the transition probability from service center +## @math{i} to service center @math{j}. +## +## @item m +## @code{@var{m}(i)} is the number of servers at service center +## @math{i}. Note that @code{@var{m}(i) @geq{} @var{C}(i)} for each @var{i}. +## If @var{m} is omitted, all service centers are assumed to have a +## single server (@code{@var{m}(i) = 1} for all @math{i}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## @code{@var{U}(i)} is the utilization of service center @math{i}. +## +## @item R +## @code{@var{R}(i)} is the response time on service center @math{i}. +## +## @item Q +## @code{@var{Q}(i)} is the average number of customers in the +## service center @math{i}, @emph{including} the request in service. +## +## @item X +## @code{@var{X}(i)} is the throughput of service center @math{i}. +## +## @end table +## +## @quotation Note +## +## The space complexity of this implementation is +## @math{O( \prod_{i=1}^K (C_i + 1)^2)}. The time complexity is dominated +## by the time needed to solve a linear system with +## @math{\prod_{i=1}^K (C_i + 1)} +## unknowns. +## +## @end quotation +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnmarkov( x, S, C, P, m ) + + if ( nargin < 4 || nargin > 5 ) + print_usage(); + endif + + isvector(S) || usage( "S must be a vector" ); + K = length(S); # number of service centers + + if ( nargin < 5 ) + m = ones(1,K); + else + size_equal(m,S) || usage( "m must have the same langth as S" ); + endif + + ( [K,K] == size(P) && all( all(P>=0)) && all(sum(P,2) <= 1)) || \ + usage( "P must be SxS and nonnegative" ); + + if ( isscalar(x) ) + is_open = false; + N = x; # closed network + ( N < sum(C) ) || \ + error( "The population size exceeds the network capacity" ); + all( abs(sum(P,2)-1) < 1000*eps ) || \ + error( "P for closed networks cannot have exit nodes" ); + else + is_open = true; + lambda = x; # open network + size_equal(lambda, S ) || \ + usage( "lambda must have the same langth as S" ); + endif + + ( all(m > 0) && all(m <= C) ) || \ + error( "Capacities C must be greater or equal than m" ); + + q_size = prod( C+1 ); # number of states of the system + + ## The infinitesimal generator matrix Q_markovmight be sparse, so it + ## would be appropriate to represent it as a sparse matrix. In this + ## case the UMFPACK library must be installed to solve the @math{{\bf + ## A}x=b} sparse system. Since I'm not sure everyone built Octave with + ## sparse matrix support, I leave Q_markov as a full matrix here. + Q_markov = zeros( q_size, q_size ); + cur_state = zeros(1, K); + + if ( is_open ) + valid_populations = linspace(0, sum(C), sum(C)+1); + else + valid_populations = [ N ]; + endif + ## exit_prob(i) is the probability that a job leaves the system from node i + exit_prob = 1 - sum(P,2); + for n=valid_populations + pop_mix = population_mix( n, C ); + for cur_state=pop_mix' # for each feasible configuration with n customers + cur_idx = sub2cell( C, cur_state ); + for i=1:K + if ( is_open ) # for open networks only + ## handle new external arrival to center i + if ( lambda(i) > 0 && cur_state(i) < C(i) ) + next_state = cur_state; next_state(i) += 1; + next_idx = sub2cell( C, next_state ); + Q_markov( cur_idx, next_idx ) = lambda(i); + endif + ## handle requests that leave the system from center i + ## exit_prob = 1-sum(P(i,:)); + if ( exit_prob(i) > 0 && cur_state(i) > 0 ) + next_state = cur_state; next_state(i) -= 1; + next_idx = sub2cell( C, next_state ); + Q_markov( cur_idx, next_idx ) = min(m(i), cur_state(i))*exit_prob(i)/S(i); + endif + endif # end open networks only + ## for both open and closed networks + for j=[1:(i-1) (i+1):K] + ## check whether a job can move from server i to server j!=i + if ( cur_state(i) > 0 && cur_state(j) < C(j) && P(i,j) > 0 ) + next_state = cur_state; next_state(i) -= 1; next_state(j) += 1; + next_idx = sub2cell( C, next_state ); + Q_markov( cur_idx, next_idx ) = min(m(i), cur_state(i))*P(i,j)/S(i); + endif + endfor + endfor + endfor + endfor + ##spy( Q_markov ); + ## complete the diagonal elements of the matrix Q + d = sum(Q_markov,2); + Q_markov -= diag( d ); + ## Solve the ctmc + prob = ctmc( Q_markov ); + ## Compute the average queue length + p = zeros(K, max(C)+1); # p(k,i+1) = prob that there are i requests at service center k + for n=valid_populations + pop_mix = population_mix( n, C ); + for cur_state=pop_mix' + cur_idx = sub2cell( C, cur_state ); + for k=1:K + i=cur_state(k); + p(k,i+1) += prob(cur_idx); + endfor + endfor + endfor + ## We can now compute all the performance measures + U = R = Q = X = zeros(1,K); + for k=1:K + j = [0:m(k)-1]; + U(k) = 1 - sum( ( m(k) - j ) ./ m(k) .* p(k,1+j) ); + ##X(k) = U(k)/S(k); + j = [1:C(k)]; + Q(k) = sum( j .* p(k,1+j) ); + ##R(k) = Q(k)/X(k); + endfor + X = U./S; + R = Q./X; +endfunction +%!test +%! S = [5 2.5]; +%! P = [0 1; 1 0]; +%! C = [3 3]; +%! m = [1 1]; +%! [U R Q X] = qnmarkov( 3, S, C, P, m ); +%! assert( U, [0.9333 0.4667], 1e-4 ); +%! assert( X, [0.1867 0.1867], 1e-4 ); +%! assert( R, [12.1429 3.9286], 1e-4 ); + +## Example 7.5 p. 292 Bolch et al. +%!test +%! S = [1/0.8 1/0.6 1/0.4]; +%! P = [0.6 0.3 0.1; 0.2 0.3 0.5; 0.4 0.1 0.5]; +%! C = [3 3 3]; +%! [U R Q X] = qnmarkov( 3, S, C, P ); +%! assert( U, [0.543 0.386 0.797], 1e-3 ); +%! assert( Q, [0.873 0.541 1.585], 1e-3 ); + +## Example 10.19, p. 551 Bolch et al. +%!xtest +%! S = [2 0.9]; +%! C = [7 5]; +%! P = [0 1; 1 0]; +%! [U R Q X] = qnmarkov( 10, S, C, P ); +%! assert( Q, [6.73 3.27], 1e-3 ); + +## Example 8.1 p. 317 Bolch et al. +%!test +%! S = [1/0.8 1/0.6 1/0.4]; +%! P = [(1-0.667-0.2) 0.667 0.2; 1 0 0; 1 0 0]; +%! m = [2 3 1]; +%! C = [3 3 3]; +%! [U R Q X] = qnmarkov( 3, S, C, P, m ); +%! assert( U, [0.590 0.350 0.473], 1e-3 ); +%! assert( Q(1:2), [1.290 1.050], 1e-3 ); + +## This is a simple test of an open QN with fixed capacity queues. There +## are two service centers, S1 and S2. C(1) = 2 and C(2) = 1. Transition +## probability from S1 to S2 is 1. Transition probability from S2 to S1 +## is p. +%!test +%! p = 0.5; # transition prob. from S2 to S1 +%! mu = [1 2]; # Service rates +%! C = [2 1]; # Capacities +%! lambda = [0.5 0]; # arrival rate at service center 1 +%! +%! PP = [ 0 1; p 0 ]; +%! [U R Q X] = qnmarkov( lambda, 1./mu, C, PP ); +%! ## Now we generate explicitly the infinitesimal generator matrix +%! ## of the underlying MC. +%! ## 00 01 10 11 20 21 +%! QQ = [ 0 0 lambda(1) 0 0 0; ... ## 00 +%! mu(2)*(1-p) 0 mu(2)*p lambda(1) 0 0; ... ## 01 +%! 0 mu(1) 0 0 lambda(1) 0; ... ## 10 +%! 0 0 mu(2)*(1-p) 0 mu(2)*p lambda(1); ... ## 11 +%! 0 0 0 mu(1) 0 0; ... ## 20 +%! 0 0 0 0 mu(2)*(1-p) 0 ]; ## 21 +%! ## Complete matrix +%! sum_el = sum(QQ,2); +%! QQ -= diag(sum_el); +%! q = ctmc(QQ); +%! ## Compare results +%! assert( U(1), 1-sum(q([1, 2])), 1e-5 ); +%! assert( U(2), 1-sum(q([1,3,5])), 1e-5 ); + +## This is a closed network with fixed-capacity queues. The population +## size N is such that blocking never occurs, so this model can be +## analyzed using the conventional MVA algorithm. MVA and qnmarkov() +## must produce the same results. +%!test +%! P = [0 0.5 0.5; 1 0 0; 1 0 0]; +%! C = [6 6 6]; +%! S = [1 0.8 1.8]; +%! N = 6; +%! [U1 R1 Q1 X1] = qnclosed( N, S, qnvisits(P) ); +%! [U2 R2 Q2 X2] = qnmarkov( N, S, C, P ); +%! assert( U1, U2, 1e-6 ); +%! assert( R1, R2, 1e-6 ); +%! assert( Q1, Q2, 1e-6 ); +%! assert( X1, X2, 1e-6 ); + +## return a linear index corresponding to index idx on a +## multidimensional vector of dimension(s) dim +function i = sub2cell( dim, idx ) + idx_cell = num2cell( idx+1 ); + i = sub2ind( dim+1, idx_cell{:} ); +endfunction +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmg1.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,100 @@ +## Copyright (C) 2009 Dmitry Kolesnikov +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qnmg1 (@var{lambda}, @var{xavg}, @var{x2nd}) +## +## @cindex @math{M/G/1} system +## +## Compute utilization, response time, average number of requests and +## throughput for a @math{M/G/1} system. The service time distribution +## is described by its mean @var{xavg}, and by its second moment +## @var{x2nd}. The computations are based on results from L. Kleinrock, +## @cite{Queuing Systems}, Wiley, Vol 2, and Pollaczek-Khinchine formula. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Arrival rate. +## +## @item xavg +## Average service time +## +## @item x2nd +## Second moment of service time distribution +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## Service center utilization +## +## @item R +## Service center response time +## +## @item Q +## Average number of requests in the system +## +## @item X +## Service center throughput +## +## @item p0 +## probability that there is not any request at system +## +## @end table +## +## @var{lambda}, @var{xavg}, @var{t2nd} can be vectors of the +## same size. In this case, the results will be vectors as well. +## +## @seealso{qnmh1} +## +## @end deftypefn + +## Author: Dmitry Kolesnikov + +function [U R Q X p0] = qnmg1(lambda, xavg, x2nd) + if ( nargin != 3 ) + print_usage(); + endif + ## bring the parameters to a common size + [ err lambda xavg x2nd ] = common_size( lambda, xavg, x2nd ); + if ( err ) + usage( "parameters are of incompatible size" ); + endif + + mu = 1 ./ xavg; + rho = lambda ./ mu; + + #coefficient of variation + Cx = (x2nd .- xavg .* xavg) ./ (xavg .* xavg); + + #PK mean formula(s) + Q = rho .+ rho .* rho .* (1 .+ Cx) ./ (2 .* (1 .- rho)); + R = xavg .+ xavg .* rho .* (1 .+ Cx) ./ (2 .* (1 .- rho)); + + p0 = exp(-rho); + #General Results + #utilization + U = rho; + X = lambda; +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmh1.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,117 @@ +## Copyright (C) 2009 Dmitry Kolesnikov +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qnmh1 (@var{lambda}, @var{mu}, @var{alpha}) +## +## @cindex @math{M/H_m/1} system +## +## Compute utilization, response time, average number of requests and +## throughput for a @math{M/H_m/1} system. In this system, the customer +## service times have hyper-exponential distribution: +## +## @iftex +## @tex +## $$ B(x) = \sum_{j=1}^m \alpha_j(1-e^{-\mu_j x}),\quad x>0 $$ +## @end tex +## @end iftex +## +## @ifnottex +## @example +## @group +## ___ m +## \ +## B(x) = > alpha(j) * (1-exp(-mu(j)*x)) x>0 +## /__ +## j=1 +## @end group +## @end example +## @end ifnottex +## +## where @math{\alpha_j} is the probability that the request is served +## at phase @math{j}, in which case the average service rate is +## @math{\mu_j}. After completing service at phase @math{j}, for +## some @math{j}, the request exits the system. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Arrival rate. +## +## @item mu +## @code{@var{mu}(j)} is the phase @math{j} service rate. The total +## number of phases @math{m} is @code{length(@var{mu})}. +## +## @item alpha +## @code{@var{alpha}(j)} is the probability that a request +## is served at phase @math{j}. @var{alpha} must have the same size +## as @var{mu}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## Service center utilization +## +## @item R +## Service center response time +## +## @item Q +## Average number of requests in the system +## +## @item X +## Service center throughput +## +## @end table +## +## @c @seealso{qnmhr1} +## +## @end deftypefn + +## Author: Dmitry Kolesnikov + +function [U R Q X p0] = qnmh1(lambda, mu, alpha) + if ( nargin != 3 ) + print_usage(); + endif + if ( size(mu) != size(alpha) ) + usage( "parameters are of incompatible size" ); + endif + [n c] = size(mu); + + if (!is_scalar(lambda) && (n != length(lambda)) ) + usage( "parameters are of incompatible size" ); + endif + for i=1:n + avg = sum( alpha(i,:) .* (1 ./ mu(i,:)) ); + m2nd = sum( alpha(i,:) .* (1 ./ (mu(i,:) .* mu(i,:))) ); + if (is_scalar(lambda)) + xavg = avg; + x2nd = m2nd; + else + xavg(i) = avg; + x2nd(i) = m2nd; + endif + endfor + [U R Q X p0] = qnmg1(lambda, xavg, x2nd); +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmix.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,247 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmix (@var{lambda}, @var{N}, @var{S}, @var{V}, @var{m}) +## +## @cindex Mean Value Analysys (MVA) +## @cindex mixed network +## +## Solution of mixed queueing networks through MVA. The network consists +## of @math{K} service centers (single-server or delay centers) and +## @math{C} independent customer chains. Both open and closed chains +## are possible. @var{lambda} is the vector of per-chain +## arrival rates (open classes); @var{N} is the vector of populations +## for closed chains. +## +## @quotation Note +## In this implementation class switching is @strong{not} allowed. Each +## customer class @emph{must} correspond to an independent chain. +## @end quotation +## +## If the network is made of open or closed classes only, then this +## function calls @code{qnopenmulti} or @code{qnclosedmultimva} +## respectively, and prints a warning message. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## @itemx N +## For each customer chain @math{c}: +## +## @itemize +## +## @item if @math{c} is a closed chain, then @code{@var{N}(c)>0} is the +## number of class @math{c} requests and @code{@var{lambda}(c)} must be +## zero; +## +## @item If @math{c} is an open chain, +## @code{@var{lambda}(c)>0} is the arrival rate of class @math{c} +## requests and @code{@var{N}(c)} must be zero; +## +## @end itemize +## +## @noindent For each @math{c}, the following must hold: +## +## @example +## (@var{lambda}(c)>0 && @var{N}(c)==0) || (@var{lambda}(c)==0 && @var{N}(c)>0) +## @end example +## +## which means that either @code{@var{lambda}(c)} is nonzero and +## @code{@var{N}(n)} is zero, or the other way around. If for some +## @math{c}, @math{@var{lambda}(c) \neq 0} and @math{@var{N}(c) \neq 0}, an +## error is reported and this function aborts. +## +## @item S +## @code{@var{S}(c,k)} is the mean service time for class @math{c} +## customers on service center @math{k}, @code{@var{S}(c,k) @geq{} 0}. +## For FCFS nodes, service times must be class-independent. +## +## @item V +## @code{@var{V}(c,k)} is the average number of visits of class @math{c} +## customers to service center @math{k} (@code{@var{V}(c,k) @geq{} 0}). +## +## @item m +## @code{@var{m}(k)} is the number of servers at service center +## @math{k}. Only single-server (@code{@var{m}(k)==1}) or IS (Infinite +## Server) nodes (@code{@var{m}(k)<1}) are supported. If omitted, each +## service center is assumed to have a single server. Queueing discipline +## for single-server nodes can be FCFS, PS or LCFS-PR. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## @code{@var{U}(c,k)} is the +## utilization of class @math{c} requests on service center @math{k}. +## +## @item R +## @code{@var{R}(c,k)} is the response +## time of class @math{c} requests on service center @math{k}. +## +## @item Q +## @code{@var{Q}(c,k)} is the average number of +## class @math{c} requests on service center @math{k}. +## +## @item X +## @code{@var{X}(c,k)} is the class @math{c} +## throughput on service center @math{k}. +## +## @end table +## +## @seealso{qnclosedmultimva, qnopenmulti} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnmix( lambda, N, S, V, m ) + if ( nargin < 4 || nargin > 5 ) + print_usage(); + endif + isvector(lambda) || \ + usage( "lambda must be a vector" ); + lambda = lambda(:)'; + isvector(N) || \ + usage( "N must be a vector" ); + N = N(:)'; + size_equal(lambda,N) || \ + usage( "lambda and N must be of equal length" ); + ( !any( lambda>0 & N>0 ) ) || \ + usage("A class cannot be open and closed at the same time. Check lambda and N" ); + ( all( lambda>0 | N>0 ) ) || \ + usage( "A class cannot be neither open nor closed. Check lambda and N" ); + size_equal(S,V) || \ + usage( "S and V must have the same size" ); + C = length(lambda); # number of classes + K = columns(S); # number of service centers + rows(S) == C || \ + usage( "S must have %d rows", C ); + if ( nargin < 5 ) + m = ones(1,K); + else + isvector( m ) || \ + usage( "m must be a vector" ); + m = m(:)'; + size_equal(lambda,m) || \ + usage( "lambda and m must be of equal length" ); + endif + all( m<=1 ) || \ + usage( "This function supports single-server and delay centers only. Check m" ); + if ( !any(lambda>0) ) + warning( "qnmix(): There are no open classes. Using qnclosedmultimva()" ); + [U R Q X] = qnclosedmultimva( N, S, V, m ); + return; + endif + if ( !any(N>0) ) + warning( "qnmix(): There are no closed classes. Using qnopenmulti()" ); + [U R Q X] = qnopenmulti( lambda, S, V, m ); + return; + endif + + D = S.*V; # service demands + op = find( lambda>0 ); # indexes of open networks + cl = find( N>0 ); # indexes of closed networks + + ## Initialize results + U = R = Q = X = zeros(C,K); + U(op,:) = diag( lambda(op) )* D(op,:); # U(c,:) = lambda(c)*D(c,:); + Uo = sum(U,1); # Total utilization for open classes on service center k + ## Build closed model to solve + Ncl = N(cl); + Scl = S; + for c=cl + Scl(c,:) = Scl(c,:) ./ (1-Uo); + endfor + Scl = Scl(cl,:); # select only rows for closed classes + Vcl = V(cl,:); + [Ucl Rcl Qcl Xcl] = qnclosedmultimva(Ncl, Scl, Vcl, m ); + ## Results for closed classes + X(cl,:) = Xcl; + Q(cl,:) = Qcl; + R(cl,:) = Rcl; + U(cl,:) = X(cl,:) .* D(cl,:); + ## Results for open classes + Qc = sum(Q(cl,:),1); + i_single=find(m==1); + i_multi=find(m<1); + for c=op + R(c,i_single) = S(c,i_single).*(1+Qc) ./ (1-Uo); # This is the Response time, _not_ the residence time + R(c,i_multi) = S(c,i_multi); + endfor + Q(op,:) = (diag(lambda(op))*V(op,:)).*R(op,:); # Q(c,k) = lambda(c)*V(c,k)*R(c,k) + X(op,:) = U(op,:) ./ D(op,:); # X(c,k) = U(c,k)/D(c,k) +endfunction +%!test +%! lambda = [1 0 0]; +%! N = [1 1 1]; +%! S = V = [1 1 1; 1 1 1; 1 1 1]; +%! fail( "qnmix( lambda, N, S, V)", "same time"); +%! N = [0 0 1]; +%! fail( "qnmix( lambda, N, S, V)", "open nor closed" ); +%! N = [0 1 2]; +%! m = [ 1 1 2 ]; +%! fail( "qnmix( lambda, N, S, V, m)", "single-server and delay" ); +%! S = V = [1 1 1; 1 1 1]; +%! fail( "qnmix( lambda, N, S, V)", "rows" ); + +%!test +%! # Example p. 148 Zahorjan et al. +%! lambda = [1 1/2 0 0]; +%! N = [0 0 1 1]; +%! V = [1 1; 1 1; 1 1; 1 1]; +%! S = [1/4 1/6; 1/2 1; 1/2 1; 1 4/3]; +%! [U R Q X] = qnmix(lambda, N, S, V ); +%! assert( Q(3,1), 4/19, 1e-4 ); +%! assert( Q(3,2), 15/19, 1e-4 ); +%! assert( Q(4,1), 5/19, 1e-4 ); +%! assert( Q(4,2), 14/19, 1e-4 ); + +%!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 ); + +%!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 );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmknode.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,158 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{Q} =} qnmknode (@var{"m/m/m-fcfs"}, @var{S}) +## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"m/m/m-fcfs"}, @var{S}, @var{m}) +## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"m/m/1-lcfs-pr"}, @var{S}) +## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/1-ps"}, @var{S}) +## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/1-ps"}, @var{S}, @var{s2}) +## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/inf"}, @var{S}) +## @deftypefnx {Function File} {@var{Q} =} qnmknode (@var{"-/g/inf"}, @var{S}, @var{s2}) +## +## Creates a node; this function can be used together with +## @code{qnsolve}. It is possible to create either single-class nodes +## (where there is only one customer class), or multiple-class nodes +## (where the service time is given per-class). Furthermore, it is +## possible to specify load-dependent service times. +## +## @strong{INPUTS} +## +## @table @var +## +## @item S +## Average service time. @math{S} can be either a scalar, a row vector, +## a column vector or a two-dimensional matrix. +## +## @itemize +## +## @item If @math{S} is a scalar, +## it is assumed to be a load-independent, class-independent service time. +## +## @item If @math{S} is a column vector, then @code{@var{S}(c)} is assumed to +## the the load-independent service time for class @math{c} customers. +## +## @item If @math{S} is a row vector, then @code{@var{S}(n)} is assumed to be +## the class-independent service time at the node, when there are @math{n} +## requests. +## +## @item Finally, if @var{S} is a two-dimensional matrix, then +## @code{@var{S}(c,n)} is assumed to be the class @math{c} service time +## when there are @math{n} requests at the node. +## +## @end itemize +## +## @item m +## Number of identical servers at the node. Default is @code{@var{m}=1}. +## +## @item s2 +## Squared coefficient of variation for the service time. Default is 1.0. +## +## @end table +## +## The returned struct @var{Q} should be considered opaque to the client. +## +## @c The returned struct @var{Q} has the following fields: +## +## @c @table @var +## +## @c @item Q.node +## @c (String) type of the node; valid values are @code{"m/m/m-fcfs"}, +## @c @code{"-/g/1-lcfs-pr"}, @code{"-/g/1-ps"} (Processor-Sharing) +## @c and @code{"-/g/inf"} (Infinite Server, or delay center). +## +## @c @item Q.S +## @c Average service time. If @code{@var{Q}.S} is a vector, then +## @c @code{@var{Q}.S(i)} is the average service time at that node +## @c if there are @math{i} requests. +## +## @c @item Q.m +## @c Number of identical servers at a @code{"m/m/m-fcfs"}. Default is 1. +## +## @c @item Q.c +## @c Number of customer classes. Default is 1. +## +## @c @end table +## +## @seealso{qnsolve} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function Q = qnmknode( node, S, varargin ) + + ischar(node) || \ + usage( "Parameter \"node\" must be a string" ); + + node = tolower(node); + + isvector(S) || ismatrix(S) || \ + usage( "Parameter \"S\" must be a vector" ); + m = 1; + s2 = ones( size(S) ); + if ( strcmp(node, "m/m/m-fcfs") ) + ## M/M/k multiserver node + if ( nargin > 3 ) + print_usage(); + endif + if ( 3 == nargin ) + m = varargin{1}; + m>=1 || \ + usage( "m must be >=1" ); + endif + elseif ( strcmp(node, "m/m/1/k-fcfs") ) + ## M/M/1/k finite capacity node + if ( nargin > 3 ) + print_usage(); + endif + if ( 3 == nargin ) + k = varargin{1}; + k>=1 || \ + usage( "k must be >=1" ); + endif + elseif ( strcmp(node, "-/g/1-lcfs-pr") ) + ## -/G/1-LCFS-PR node + ( 2 == nargin || 3 == nargin ) || \ + print_usage(); + if ( 3 == nargin ) + s2 = varargin{1}; + endif + elseif ( strcmp(node, "-/g/1-ps") ) + ## -/G/1-PS (processor sharing) node + ( 2 == nargin || 3 == nargin ) || \ + print_usage(); + if ( 3 == nargin ) + s2 = varargin{1}; + endif + elseif ( strcmp(node, "-/g/inf") ) + ## -/G/inf (Infinite Server) node + ( 2 == nargin || 3 == nargin ) || \ + print_usage(); + if ( 3 == nargin ) + s2 = varargin{1}; + endif + else + usage( "Unknown node type \"%s\". node type must be one of \"m/m/m-fcfs\", \"-/g/1-lcfs-pr\", \"-/g/1-ps\" and \"-/g/inf\"", node ); + endif + Q = struct( "node", node, "m", m, "S", S, "s2", s2, "c", rows(S), "comment", "" ); +endfunction +%!test +%! fail( "qnmknode( 'pippo', 1 )", "must be one" ); +%! fail( "qnmknode( '-/g/1-ps', 1, 1, 1)", "Invalid call" );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmm1.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,108 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qnmm1 (@var{lambda}, @var{mu}) +## +## @cindex @math{M/M/1} system +## +## Compute utilization, response time, average number of requests +## and throughput for a @math{M/M/1} queue. +## +## @iftex +## The steady-state probability @math{\pi_k} that there are @math{k} +## jobs in the system, @math{k \geq 0}, can be computed as: +## +## @tex +## $$ +## \pi_k = (1-\rho)\rho^k +## $$ +## @end tex +## +## where @math{\rho = \lambda/\mu} is the server utilization. +## +## @end iftex +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Arrival rate (@code{@var{lambda} > 0}). +## +## @item mu +## Service rate (@code{@var{mu} > @var{lambda}}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## Server utilization +## +## @item R +## Service center response time +## +## @item Q +## Average number of requests in the system +## +## @item X +## Service center throughput. If the system is ergodic, +## we will always have @code{@var{X} = @var{lambda}} +## +## @item p0 +## Steady-state probability that there are no requests in the system. +## +## @end table +## +## @var{lambda} and @var{mu} can be vectors of the same size. In this +## case, the results will be vectors as well. +## +## @seealso{qnmmm, qnmminf, qnmmmk} +## +## @end deftypefn + +## Author: Moreno Marzolla <moreno.marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X p0] = qnmm1( lambda, mu ) + if ( nargin != 2 ) + print_usage(); + endif + ## bring the parameters to a common size + [ err lambda mu ] = common_size( lambda, mu ); + if ( err ) + usage( "parameters are of incompatible size" ); + endif + ( isvector(lambda) && isvector(mu) ) || \ + usage( "lambda and mu must be vectors" ); + all( lambda > 0 ) || \ + usage( "lambda must be >0" ); + all( mu > lambda ) || \ + usage( "The system is not ergodic" ); + U = rho = lambda ./ mu; # utilization + p0 = 1-rho; + Q = rho ./ (1-rho); + R = 1 ./ ( mu .* (1-rho) ); + X = lambda; +endfunction +%!test +%! fail( "qnmm1(10,5)", "not ergodic" ); +%! fail( "qnmm1([2 2], [1 1 1])", "incompatible size");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmm1k.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,149 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pK}] =} qnmm1k (@var{lambda}, @var{mu}, @var{K}) +## +## @cindex @math{M/M/1/K} system +## +## Compute utilization, response time, average number of requests and +## throughput for a @math{M/M/1/K} finite capacity system. In a +## @math{M/M/1/K} queue there is a single server; the maximum number of +## requests in the system is @math{K}, and the maximum queue length is +## @math{K-1}. +## +## @iftex +## The steady-state probability @math{\pi_k} that there are @math{k} +## jobs in the system, @math{0 @leq{} k @leq{} K}, can be computed as: +## +## @tex +## $$ +## \pi_k = {(1-a)a^k \over 1-a^{K+1}} +## $$ +## @end tex +## where @math{a = \lambda/\mu}. +## @end iftex +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Arrival rate (@code{@var{lambda}>0}). +## +## @item mu +## Service rate (@code{@var{mu}>0}). +## +## @item K +## Maximum number of requests allowed in the system (@code{@var{K} @geq{} 1}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## Service center utilization, which is defined as @code{@var{U} = 1-@var{p0}} +## +## @item R +## Service center response time +## +## @item Q +## Average number of requests in the system +## +## @item X +## Service center throughput +## +## @item p0 +## Steady-state probability that there are no requests in the system +## +## @item pK +## Steady-state probability that there are @math{K} requests in the system +## (i.e., that the system is full) +## +## @end table +## +## @var{lambda}, @var{mu} and @var{K} can be vectors of the +## same size. In this case, the results will be vectors as well. +## +## @seealso{qnmm1,qnmminf,qnmmm} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X p0 pK] = qnmm1k( lambda, mu, K ) + if ( nargin != 3 ) + print_usage(); + endif + + ( isvector(lambda) && isvector(mu) && isvector(K) ) || \ + usage( "lambda, mu, K must be vectors of the same size" ); + + [err lambda mu K] = common_size( lambda, mu, K ); + if ( err ) + usage( "Parameters are not of common size" ); + endif + + all( K>0 ) || \ + usage( "K must be >0" ); + ( all( lambda>0 ) && all( mu>0 ) ) || \ + usage( "lambda and mu must be >0" ); + + U = R = Q = X = p0 = pK = 0*lambda; + a = lambda./mu; + ## persistent tol = 1e-7; + ## if a!=1 + ## i = find( abs(a-1)>tol ); + i = find( a != 1 ); + p0(i) = (1-a(i))./(1-a(i).^(K(i)+1)); + pK(i) = (1-a(i)).*(a(i).^K(i))./(1-a(i).^(K(i)+1)); + Q(i) = a(i)./(1-a(i)) - (K(i)+1)./(1-a(i).^(K(i)+1)).*(a(i).^(K(i)+1)); + ## if a==1 + ## i = find( abs(a-1)<=tol ); + i = find( a == 1 ); + p0(i) = pK(i) = 1./(K(i)+1); + Q(i) = K(i)/2; + ## Compute other performance measures + U = 1-p0; + X = lambda.*(1-pK); + R = Q ./ X; +endfunction +%!test +%! lambda = mu = 1; +%! K = 10; +%! [U R Q X p0] = qnmm1k(lambda,mu,K); +%! assert( Q, K/2, 1e-7 ); +%! assert( U, 1-p0, 1e-7 ); + +%!test +%! # Compare result with one obtained by solvind the CTMC +%! lambda = 0.8; +%! mu = 0.8; +%! K = 10; +%! [U1 R1 Q1 X1] = qnmm1k( lambda, mu, K ); +%! birth = lambda*ones(1,K); +%! death = mu*ones(1,K); +%! q = ctmc_bd( birth, death ); +%! U2 = 1-q(1); +%! Q2 = dot( [0:K], q ); +%! assert( U1, U2, 1e-4 ); +%! assert( Q1, Q2, 1e-4 ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmminf.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,110 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}] =} qnmminf (@var{lambda}, @var{mu}) +## +## Compute utilization, response time, average number of requests and +## throughput for a @math{M/M/\infty} queue. This is a system with an +## infinite number of identical servers. Note that a @math{M/M/\infty} +## system is always stable, regardless the values of the arrival and +## service rates. +## +## @cindex @math{M/M/}inf system +## +## @iftex +## The steady-state probability @math{\pi_k} that there are @math{k} +## requests in the system, @math{k @geq{} 0}, can be computed as: +## +## @tex +## $$ +## \pi_k = {1 \over k!} \left( \lambda \over \mu \right)^k e^{-\lambda / \mu} +## $$ +## @end tex +## @end iftex +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Arrival rate (@code{@var{lambda}>0}). +## +## @item mu +## Service rate (@code{@var{mu}>0}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## Traffic intensity (defined as @math{\lambda/\mu}). Note that this is +## different from the utilization, which in the case of @math{M/M/\infty} +## centers is always zero. +## +## @cindex traffic intensity +## +## @item R +## Service center response time. +## +## @item Q +## Average number of requests in the system (which is equal to the +## traffic intensity @math{\lambda/\mu}). +## +## @item X +## Throughput (which is always equal to @code{@var{X} = @var{lambda}}). +## +## @item p0 +## Steady-state probability that there are no requests in the system +## +## @end table +## +## @var{lambda} and @var{mu} can be vectors of the same size. In this +## case, the results will be vectors as well. +## +## @seealso{qnmm1,qnmmm,qnmmmk} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X p0] = qnmminf( lambda, mu ) + if ( nargin != 2 ) + print_usage(); + endif + [ err lambda mu ] = common_size( lambda, mu ); + + if ( err ) + usage( "Parameters are of incompatible size" ); + endif + + ( isvector(lambda) && isvector(mu) ) || \ + usage( "lambda and mu must be vectors" ); + ( all( lambda>0 ) && all( mu>0 ) ) || \ + usage( "lambda and mu must be >0" ); + U = Q = lambda ./ mu; # Traffic intensity. + p0 = exp(-lambda./mu); # probability that there are 0 requests in the system + R = 1 ./ mu; + X = lambda; +endfunction +%!test +%! fail( "qnmminf( [1 2], [1 2 3] )", "incompatible size"); +%! fail( "qnmminf( [-1 -1], [1 1] )", ">0" );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmmm.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,158 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pm}] =} qnmmm (@var{lambda}, @var{mu}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pm}] =} qnmmm (@var{lambda}, @var{mu}, @var{m}) +## +## @cindex @math{M/M/m} system +## +## Compute utilization, response time, average number of requests in +## service and throughput for a @math{M/M/m} queue, a queueing +## system with @math{m} identical service centers connected to a single queue. +## +## @iftex +## The steady-state probability @math{\pi_k} that there are @math{k} +## jobs in the system, @math{k \geq 0}, can be computed as: +## +## @tex +## $$ +## \pi_k = \cases{ \displaystyle{\pi_0 { ( m\rho )^k \over k!}} & $0 \leq k \leq m$;\cr +## \displaystyle{\pi_0 { \rho^k m^m \over m!}} & $k>m$.\cr +## } +## $$ +## @end tex +## +## where @math{\rho = \lambda/(m\mu)} is the individual server utilization. +## The steady-state probability @math{\pi_0} that there are no jobs in the +## system can be computed as: +## +## @tex +## $$ +## \pi_0 = \left[ \sum_{k=0}^{m-1} { (m\rho)^k \over k! } + { (m\rho)^m \over m!} {1 \over 1-\rho} \right]^{-1} +## $$ +## @end tex +## +## @end iftex +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Arrival rate (@code{@var{lambda}>0}). +## +## @item mu +## Service rate (@code{@var{mu}>@var{lambda}}). +## +## @item m +## Number of servers (@code{@var{m} @geq{} 1}). +## If omitted, it is assumed @code{@var{m}=1}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## Service center utilization, @math{U = \lambda / (m \mu)}. +## +## @item R +## Service center response time +## +## @item Q +## Average number of requests in the system +## +## @item X +## Service center throughput. If the system is ergodic, +## we will always have @code{@var{X} = @var{lambda}} +## +## @item p0 +## Steady-state probability that there are 0 requests in the system +## +## @item pm +## Steady-state probability that an arriving request has to wait in the +## queue +## +## @end table +## +## @var{lambda}, @var{mu} and @var{m} can be vectors of the same size. In this +## case, the results will be vectors as well. +## +## @seealso{qnmm1,qnmminf,qnmmmk} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X p0 pm] = qnmmm( lambda, mu, m ) + if ( nargin < 2 || nargin > 3 ) + print_usage(); + endif + if ( nargin == 2 ) + m = 1; + endif + [err lambda mu m] = common_size( lambda, mu, m ); + if ( err ) + usage( "parameters are not of common size" ); + endif + + ( isvector(lambda) && isvector(mu) && isvector(m) ) || \ + usage( "the parameters must be vectors" ); + + all( m>0 ) || \ + usage( "m must be >0" ); + + all( lambda < m .* mu ) || \ + error( "Processing capacity exceeded" ); + + X = lambda; + U = rho = lambda ./ (m .* mu ); + Q = p0 = 0*lambda; + for i=1:length(lambda) # I cannot easily vectorize this + #p = zeros(1,m(i)+1); + k=[0:m(i)-1]; + p0(i) = 1 / ( ... + sum( (m(i)*rho(i)).^ k ./ factorial(k)) + ... + (m(i)*rho(i))^m(i) / (factorial(m(i))*(1-rho(i))) ... + ); + #p(2+k) = p(1)*( m(i)*rho(i) ).^(1+k)./factorial(1+k); + #U(i) = 1-dot( (m(i)-k)./m(i), p(k+1) ); # FIXME: check + endfor + pm = (m.*rho).^m./(factorial(m).*(1-rho)).*p0; + Q = m .* rho .+ rho ./ (1-rho) .* pm; + R = Q ./ X; +endfunction +%!demo +%! disp("This is figure 6.4 on p. 220 Bolch et al."); +%! rho = 0.9; +%! ntics = 21; +%! lambda = 0.9; +%! m = linspace(1,ntics,ntics); +%! mu = lambda./(rho .* m); +%! [U R Q X] = qnmmm(lambda, mu, m); +%! qlen = X.*(R-1./mu); +%! plot(m,Q,"o",qlen,"*"); +%! axis([0,ntics,0,25]); +%! legend("Jobs in the system","Queue Length","location","northwest"); +%! xlabel("Number of servers (m)"); +%! title("\lambda = 0.9, \mu = 0.9"); + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmmmk.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,223 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}, @var{p0}, @var{pK}] =} qnmmmk (@var{lambda}, @var{mu}, @var{m}, @var{K}) +## +## @cindex @math{M/M/m/K} system +## +## Compute utilization, response time, average number of requests and +## throughput for a @math{M/M/m/K} finite capacity system. In a +## @math{M/M/m/K} system there are @math{m \geq 1} identical service +## centers sharing a fixed-capacity queue. At any time, at most @math{K @geq{} m} requests can be in the system. The maximum queue length +## is @math{K-m}. This function generates and +## solves the underlying CTMC. +## +## @iftex +## +## The steady-state probability @math{\pi_k} that there are @math{k} +## jobs in the system, @math{0 @leq{} k @leq{} K} can be expressed as: +## +## @tex +## $$ +## \pi_k = \cases{ \displaystyle{{\rho^k \over k!} \pi_0} & if $0 \leq k \leq m$;\cr +## \displaystyle{{\rho^m \over m!} \left( \rho \over m \right)^{k-m} \pi_0} & if $m < k \leq K$\cr} +## $$ +## @end tex +## +## where @math{\rho = \lambda/\mu} is the offered load. The probability +## @math{\pi_0} that the system is empty can be computed by considering +## that all probabilities must sum to one: @math{\sum_{k=0}^K \pi_k = 1}, +## which gives: +## +## @tex +## $$ +## \pi_0 = \left[ \sum_{k=0}^m {\rho^k \over k!} + {\rho^m \over m!} \sum_{k=m+1}^K \left( {\rho \over m}\right)^{k-m} \right]^{-1} +## $$ +## @end tex +## +## @end iftex +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Arrival rate (@code{@var{lambda}>0}). +## +## @item mu +## Service rate (@code{@var{mu}>0}). +## +## @item m +## Number of servers (@code{@var{m} @geq{} 1}). +## +## @item K +## Maximum number of requests allowed in the system, +## including those inside the service centers +## (@code{@var{K} @geq{} @var{m}}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## Service center utilization +## +## @item R +## Service center response time +## +## @item Q +## Average number of requests in the system +## +## @item X +## Service center throughput +## +## @item p0 +## Steady-state probability that there are no requests in the system. +## +## @item pK +## Steady-state probability that there are @var{K} requests in the system +## (i.e., probability that the system is full). +## +## @end table +## +## @var{lambda}, @var{mu}, @var{m} and @var{K} can be either scalars, or +## vectors of the same size. In this case, the results will be vectors +## as well. +## +## @seealso{qnmm1,qnmminf,qnmmm} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X p0 pK] = qnmmmk( lambda, mu, m, K ) + if ( nargin != 4 ) + print_usage(); + endif + + ( isvector(lambda) && isvector(mu) && isvector(m) && isvector(K) ) || ... + usage( "lambda, mu, m, K must be vectors of the same size" ); + lambda = lambda(:)'; # make lambda a row vector + mu = mu(:)'; # make mu a row vector + m = m(:)'; # make m a row vector + K = K(:)'; # make K a row vector + + [err lambda mu m K] = common_size( lambda, mu, m, K ); + if ( err ) + usage( "Parameters are not of common size" ); + endif + + all( K>0 ) || \ + usage( "k must be strictly positive" ); + all( m>0 ) && all( m <= K ) || \ + usage( "m must be in the range 1:k" ); + all( lambda>0 ) && all( mu>0 ) || \ + usage( "lambda and mu must be >0" ); + U = R = Q = X = p0 = pK = 0*lambda; + for i=1:length(lambda) + ## Build and solve the birth-death process describing the M/M/m/k system + birth_rate = lambda(i)*ones(1,K(i)); + death_rate = [ linspace(1,m(i),m(i))*mu(i) ones(1,K(i)-m(i))*m(i)*mu(i) ]; + p = ctmc_bd(birth_rate, death_rate); + p0(i) = p(1); + pK(i) = p(1+K(i)); + j = [1:K(i)]; + Q(i) = dot( p(1+j),j ); + endfor + ## Compute other performance measures + X = lambda.*(1-pK); + U = X ./ (m .* mu ); + R = Q ./ X; +endfunction +%!test +%! lambda = mu = m = 1; +%! k = 10; +%! [U R Q X p0] = qnmmmk(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] = qnmm1k(lambda,mu,k); +%! [U2 R2 Q2 X2] = qnmmmk(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] = qnmmmk(lambda,mu,1,k); +%! [U2 R2 Q2 X2 p02] = qnmm1k(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] = qnmmmk( lambda, mu, m, k ); +%! birth = lambda*ones(1,k); +%! death = [ mu*linspace(1,m,m) mu*m*ones(1,k-m) ]; +%! q = ctmc_bd( 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] = qnmmmk( 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] = qnmmmk( 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] = qnmmmk( 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 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmvablo.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,198 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnmvablo (@var{N}, @var{S}, @var{M}, @var{P}) +## +## @cindex queueing network with blocking +## @cindex blocking queueing network +## @cindex closed network, finite capacity +## +## MVA algorithm for closed queueing networks with blocking. @command{qnmvablo} +## computes approximate utilization, response time and mean queue length +## for closed, single class queueing networks with blocking. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## population size, i.e., number of requests in the system. @var{N} must +## be strictly greater than zero, and less than the overall network capacity: +## @code{0 < @var{N} < sum(@var{M})}. +## +## @item S +## Average service time. @code{@var{S}(i)} is the average service time +## requested on server @math{i} (@code{@var{S}(i) > 0}). +## +## @item M +## Server capacity. @code{@var{M}(i)} is the capacity of service center +## @math{i}. The capacity is the maximum number of requests in a service +## center, including the request currently in service (@code{@var{M}(i) @geq{} 1}). +## +## @item P +## @code{@var{P}(i,j)} is the probability that a request which completes +## service at server @math{i} will be transferred to server @math{j}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## @code{@var{U}(i)} is the utilization of +## service center @math{i}. +## +## @item R +## @code{@var{R}(i)} is the average response time +## of service center @math{i}. +## +## @item Q +## @code{@var{Q}(i)} is +## the average number of requests in service center @math{i} (including +## the request in service). +## +## @item X +## @code{@var{X}(i)} is the throughput of +## service center @math{i}. +## +## @end table +## +## @seealso{qnopen, qnclosed} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnmvablo( K, S, M, P ) + + ## Note that we use "K" instead of "N" as the number of requests in + ## order to be compliant with the paper by Akyildiz describing this + ## algorithm. + + if ( nargin != 4 ) + print_usage(); + endif + ( isscalar(K) && K > 0 ) || \ + usage( "K must be a positive integer" ); + isvector(S) && all(S>0) || \ + error ("S must be a vector > 0"); + S = S(:)'; # make S a row vector + N = length(S); + ( isvector(M) && length(M) == N ) || \ + usage( "M must be a vector with %d elements", N ); + all( M >= 1) || \ + usage( "M must be >= 1"); + M = M(:)'; # make M a row vector + + (K < sum(M)) || \ + error( "The population size K=%d exceeds the total system capacity %d", K, sum(M) ); + dtmc_check_P(P); + rows(P) == N || \ + error("The number of rows of P must be equal to the length of S"); + + ## Note: in this implementation we make use of the same notation found + ## in Akyildiz's paper cited in the REFERENCES above, with the minor + ## exception of using 'v' instead of 'e' as the visit count vector. + ## k_bar(i) is the average number of jobs in the i-th server, lambda + ## is the network throughput, t_bar(i) is the mean residence time + ## (time spent in queue and in service) for requests in the i-th + ## service center. + + ## Initialization + k_bar_m1 = zeros(1,N); # k_bar(k-1) + BT = zeros(1,N); + z = ones(1,N); + lambda = 0; + ## Computation of the visit counts + v = qnvisits(P); + D = S .* v; # Service demand + ## Main loop + for k=1:K + do + ## t_bar_i(k) = S(i) *(z_i(k) + k_bar_i(k-1))+BT_i(k) + t_bar = S .* ( z + k_bar_m1 ) + BT; + lambda = k / dot(v,t_bar); + k_bar = t_bar .* v * lambda; + if ( any(k_bar>M) ) + i = find( k_bar > M, 1 ); + z(i) = 0; + BT = BT + S(i) * ( v .* P(:,i)' ) / v(i); + endif + until( all(k_bar<=M) ); + k_bar_m1 = k_bar; + endfor + R = t_bar; + X = v * lambda; # Throughputs + ## w_bar = t_bar - S - BT; # mean waiting time + U = X .* S; + Q = X .* R; +endfunction +%!test +%! fail( "qnmvablo( 10, [1 1], [4 5], [0 1; 1 0] )", "capacity"); +%! fail( "qnmvablo( 6, [1 1], [4 5], [0 1; 1 1] )", "stochastic"); +%! fail( "qnmvablo( 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]=qnmvablo( 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]=qnmvablo( K, S, M, P ); +%! assert( R, [6.925 8.061 4.185], 1e-3 ); +%! K = 12; +%! [U R Q X]=qnmvablo( 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] = qnmvablo( K, S, M, P ); +%! assert( R, [1.674 5.007 7.639], 1e-3 ); +%! K = 12; +%! [U R Q X] = qnmvablo( 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] = qnmvablo( K, S, M, P ); +%! V = qnvisits(P); +%! [U2 R2 Q2] = qnclosedsinglemva( K, S, V ); +%! assert( U1, U2, 1e-5 ); +%! assert( R1, R2, 1e-5 ); +%! assert( Q1, Q2, 1e-5 ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnmvapop.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,85 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {@var{H} =} qnmvapop (@var{N}) +## +## @cindex population mix +## @cindex closed network, multiple classes +## +## Given a network with @math{C} customer classes, this function +## computes the number of valid population mixes @code{@var{H}(r,n)} that can +## be constructed by the multiclass MVA algorithm by allocating @math{n} +## customers to the first @math{r} classes. +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## Population vector. @code{@var{N}(c)} is the number of class-@math{c} +## requests in the system. The total number of requests in the network +## is @code{sum(@var{N})}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item H +## @code{@var{H}(r,n)} is the number of valid populations that can be +## constructed allocating @math{n} customers to the first @math{r} classes. +## +## @end table +## +## @seealso{qnclosedmultimva,population_mix} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function H = qnmvapop( N ) + (isvector(N) && all( N > 0 ) ) || \ + error( "N must be a vector of strictly positive integers" ); + N = N(:)'; # make N a row vector + Ns = sum(N); + R = length(N); + + ## Please note that the algorithm as described in the reference (see + ## documentation in PDF format) seems incorrect: in the implementation + ## above the @code{TOTAL_POP} variable is initialized with + ## @code{@var{N}(1)}, instead of 0 as in the paper. Moreover, here the + ## @code{TOTAL_POP} variable is incremented by @code{@var{N}(r)} at + ## each iteration (instead of @code{@var{N}(r-1)} as in the paper) + + total_pop = N(1); + H = zeros(R, Ns+1); + H(1,1:N(1)+1) = 1; + for r=2:R + total_pop += N(r); + for n=0:total_pop + range = max(0,n-N(r)) : n; + H(r,n+1) = sum( H(r-1, range+1 ) ); + endfor + endfor +endfunction +%!test +%! H = qnmvapop( [1 2 2] ); +%! assert( H, [1 1 0 0 0 0; 1 2 2 1 0 0; 1 3 5 5 3 1] );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnopen.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,66 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopen (@var{lambda}, @var{S}, @var{V}, @dots{}) +## +## @cindex open network +## +## Compute utilization, response time, average number of requests in the +## system, and throughput for open queueing networks. If @var{lambda} is +## a scalar, the network is considered a single-class QN and is solved +## using @code{qnopensingle}. If @var{lambda} is a vector, the network +## is considered as a multiclass QN and solved using @code{qnopenmulti}. +## +## @seealso{qnopensingle, qnopenmulti} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnopen( lambda, S, V, varargin ) + if ( nargin < 3 ) + print_usage(); + endif + if ( isscalar(lambda) ) + [U R Q X] = qnopensingle(lambda, S, V, varargin{:}); + else + [U R Q X] = qnopenmulti(lambda, S, V, varargin{:}); + endif +endfunction +%!test +%! # Example 34.1 p. 572 +%! lambda = 3; +%! V = [16 7 8]; +%! S = [0.01 0.02 0.03]; +%! [U R Q X] = qnopen( lambda, S, V ); +%! assert( R, [0.0192 0.0345 0.107], 1e-2 ); +%! assert( U, [0.48 0.42 0.72], 1e-2 ); + +%!test +%! V = [1 1; 1 1]; +%! S = [1 3; 2 4]; +%! lambda = [3/19 2/19]; +%! [U R Q] = qnopen(lambda, S, 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 ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnopenab.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,79 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{Xu}, @var{Rl}] =} qnopenab (@var{lambda}, @var{D}) +## +## @cindex bounds, asymptotic +## @cindex open network +## +## Compute Asymptotic Bounds for single-class, open Queueing Networks +## with @math{K} service centers. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## overall arrival rate to the system (scalar). Abort if +## @code{@var{lambda} @leq{} 0} +## +## @item D +## @code{@var{D}(k)} is the service demand at center @math{k}. +## The service demand vector @var{D} must be nonempty, and all demands +## must be nonnegative (@code{@var{D}(k) @geq{} 0} for all @math{k}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item Xu +## Upper bound on the system throughput. +## +## @item Rl +## Lower bound on the system response time. +## +## @end table +## +## @seealso{qnopenbsb} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [X_upper R_lower] = qnopenab( lambda, D ) + if ( nargin != 2 ) + print_usage(); + endif + ( isscalar(lambda) && lambda > 0 ) || \ + usage( "lambda must be a positive scalar" ); + ( isvector(D) && length(D)>0 && all( D>=0 ) ) || \ + usage( "D must be a vector of nonnegative scalars" ); + + X_upper = 1/max(D); + R_lower = sum(D); +endfunction + +%!test +%! fail( "qnopenab( 0.1, [] )", "vector" ); +%! fail( "qnopenab( 0.1, [0 -1])", "vector" ); +%! fail( "qnopenab( 0, [1 2] )", "lambda" ); +%! fail( "qnopenab( -1, [1 2])", "lambda" ); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnopenbsb.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,85 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{Xu}, @var{Rl}, @var{Ru}] =} qnopenbsb (@var{lambda}, @var{D}) +## +## @cindex bounds, balanced system +## @cindex open network +## +## Compute Balanced System Bounds for single-class, open Queueing Networks +## with @math{K} service centers. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## overall arrival rate to the system (scalar). Abort if +## @code{@var{lambda} < 0 } +## +## @item D +## @code{@var{D}(k)} is the service demand at center @math{k}. +## The service demand vector @var{D} must be nonempty, and all demands +## must be nonnegative (@code{@var{D}(k) @geq{} 0} for all @math{k}). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item Xl +## Lower bound on the system throughput. +## +## @item Rl +## @itemx Ru +## Lower and upper bound on the system response time. +## +## @end table +## +## @seealso{qnopenab} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [X_upper R_lower R_upper] = qnopenbsb( lambda, D ) + if ( nargin != 2 ) + print_usage(); + endif + ( isscalar(lambda) && lambda>0 ) || \ + usage( "lambda must be a positive scalar" ); + ( isvector(D) && length(D)>0 && all(D>=0) ) || \ + usage( "D must be a vector of nonnegative floats" ); + + D_max = max(D); + D_tot = sum(D); + D_ave = mean(D_tot); + X_upper = 1/D_max; + R_lower = D_tot / (1-lambda*D_ave); + R_upper = D_tot / (1-lambda*D_max); +endfunction + +%!test +%! fail( "qnopenbsb( 0.1, [] )", "vector" ); +%! fail( "qnopenbsb( 0.1, [0 -1])", "vector" ); +%! fail( "qnopenbsb( 0, [1 2] )", "lambda" ); +%! fail( "qnopenbsb( -1, [1 2])", "lambda" ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnopenmulti.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,157 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopenmulti (@var{lambda}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopenmulti (@var{lambda}, @var{S}, @var{V}, @var{m}) +## +## @cindex open network, multiple classes +## +## Exact analysis of open, multiple-class BCMP networks. The network can +## be made of @emph{single-server} queueing centers (FCFS, LCFS-PR or +## PS) or delay centers (IS). This function assumes a network with +## @math{K} service centers and @math{C} customer classes. +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## @code{@var{lambda}(c)} is the external +## arrival rate of class @math{c} customers (@code{@var{lambda}(c)>0}). +## +## @item S +## @code{@var{S}(c,k)} is the mean service time of class @math{c} +## customers on the service center @math{k} (@code{@var{S}(c,k)>0}). +## For FCFS nodes, average service times must be class-independent. +## +## @item V +## @code{@var{V}(c,k)} is the average number of visits of class @math{c} +## customers to service center @math{k} (@code{@var{V}(c,k) @geq{} 0 }). +## +## @item m +## @code{@var{m}(k)} is the number of servers at service center +## @math{k}. Valid values are @code{@var{m}(k) < 1} to denote a delay +## center (@math{-/G/\infty}), and @code{@var{m}(k)==1} to denote +## a single server queueing center (@math{M/M/1}--FCFS, +## @math{-/G/1}--LCFS-PR or @math{-/G/1}--PS). +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## If @math{k} is a queueing center, then @code{@var{U}(c,k)} is the +## class @math{c} utilization of center @math{k}. If @math{k} is +## an IS node, then @code{@var{U}(c,k)} is the +## class @math{c} @emph{traffic intensity} +## defined as @code{@var{X}(c,k)*@var{S}(c,k)}. +## +## @item R +## @code{@var{R}(c,k)} is the class @math{c} response time at +## center @math{k}. The system response time for +## class @math{c} requests can be computed +## as @code{dot(@var{R}, @var{V}, 2)}. +## +## @item Q +## @code{@var{Q}(c,k)} is the average number of class @math{c} requests +## at center @math{k}. The average number of class @math{c} requests +## in the system @var{Qc} can be computed as @code{Qc = sum(@var{Q}, 2)} +## +## @item X +## @code{@var{X}(c,k)} is the class @math{c} throughput +## at center @math{k}. +## +## @end table +## +## @seealso{qnopen,qnopensingle,qnvisits} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ +function [U R Q X] = qnopenmulti( lambda, S, V, m ) + if ( nargin < 3 || nargin > 4 ) + print_usage(); + endif + isvector(lambda) && all(lambda > 0) || \ + usage( "lambda must be a vector of positive floats" ); + lambda = lambda(:)'; # make lambda a row vector + C = length(lambda); + K = columns(S); + [C,K] == size(S) || \ + usage( "rows(S) must be equal to length(lambda)" ); + all(all( S > 0 )) || \ + usage( "S(c,k) must be > 0" ); + [C,K] == size(V) || \ + usage( "V must be a matrix of the same size as S" ); + all( all(V>= 0) ) || \ + usage( "V must be >= 0 " ); + + if ( nargin < 4 ) + m = ones(1,K); + else + ( isvector( m ) && length(m) == K && all( m <= 1 ) ) || \ + usage( "m must be less than or equal to ones(1,K)" ); + m = m(:)'; # make m a row vector + endif + + D = S .* V; # Service demands: D(c,k) = S(c,k) * V(c,k) + max(lambda * D) < 1 || \ + error( "processing capacity exceeded" ); + + U = R = Q = X = zeros(C,K); + i_delay = find(m<1); + i_single = find(m==1); + U = diag(lambda)*D; # U(c,:) = lambda(c)*D(c,:); + X = diag(lambda)*V; # X(c,:) = lambda(c)*V(c,:); + + ## delay centers + R(:,i_delay) = S(:,i_delay); + Q(:,i_delay) = U(:,i_delay); + + ## Queueing centers + for c=1:C + R(c,i_single) = S(c,i_single) ./ ( 1 - sum(U(:,i_single),1) ); + Q(c,i_single) = U(c,i_single) ./ ( 1 - sum(U(:,i_single),1) ); + endfor +endfunction +%!test +%! V = [1 1; 1 1]; +%! S = [1 3; 2 4]; +%! lambda = [3/19 2/19]; +%! [U R Q] = qnopenmulti(lambda, S, 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 ); + +%!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] = qnopenmulti(lambda, S, 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 ); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnopensingle.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,217 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopensingle (@var{lambda}, @var{S}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnopensingle (@var{lambda}, @var{S}, @var{V}, @var{m}) +## +## @cindex open network, single class +## @cindex BCMP network +## +## Analyze open, single class BCMP queueing networks. +## +## This function works for a subset of BCMP single-class open networks +## satisfying the following properties: +## +## @itemize +## +## @item The allowed service disciplines at network nodes are: FCFS, +## PS, LCFS-PR, IS (infinite server); +## +## @item Service times are exponentially distributed and +## load-independent; +## +## @item Service center @math{i} can consist of @code{@var{m}(i) @geq{} 1} +## identical servers. +## +## @item Routing is load-independent +## +## @end itemize +## +## @strong{INPUTS} +## +## @table @var +## +## @item lambda +## Overall external arrival rate (@code{@var{lambda}>0}). +## +## @item S +## @code{@var{S}(k)} is the average service time at center +## @math{i} (@code{@var{S}(k)>0}). +## +## @item V +## @code{@var{V}(k)} is the average number of visits to center +## @math{k} (@code{@var{V}(k) @geq{} 0}). +## +## @item m +## @code{@var{m}(k)} is the number of servers at center @math{i}. If +## @code{@var{m}(k) < 1}, then service center @math{k} is a delay center +## (IS); otherwise it is a regular queueing center with +## @code{@var{m}(k)} servers. Default is @code{@var{m}(k) = 1} for each +## @math{k}. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## If @math{k} is a queueing center, +## @code{@var{U}(k)} is the utilization of center @math{k}. +## If @math{k} is an IS node, then @code{@var{U}(k)} is the +## @emph{traffic intensity} defined as @code{@var{X}(k)*@var{S}(k)}. +## +## @item R +## @code{@var{R}(k)} is the average response time of center @math{k}. +## +## @item Q +## @code{@var{Q}(k)} is the average number of requests at center +## @math{k}. +## +## @item X +## @code{@var{X}(k)} is the throughput of center @math{k}. +## +## @end table +## +## @seealso{qnopen,qnclosed,qnvisits} +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnopensingle( lambda, S, V, m ) + if ( nargin < 3 || nargin > 4 ) + print_usage(); + endif + ( isscalar(lambda) && lambda>0 ) || \ + usage( "lambda must be a positive number" ); + lambda = lambda(:)'; + ( isvector( S ) && all(S>0) ) || \ + usage( "S must be a vector >0" ); + S = S(:)'; + K = length(S); + ( isvector( V ) && length(V)==K && all(V>=0) ) || \ + usage( "V must be a vector >=0 and of the same length as S" ); + V = V(:)'; + + if ( nargin < 4 ) + m = ones(1,K); + else + (isvector(m) && (length(m) == K)) || \ + usage( "m must be a vector of %d elements", K); + m = m(:)'; + [err m] = common_size(m,S); + ( err == 0 ) || \ + usage( "m and S are not of common size" ); + endif + + ## Compute maximum processing capacity + lambda_sat = 1 / max( S.* V ); + (lambda <= lambda_sat) || \ + error( "Processing capacity exceeded (lambda must be less than %f)", lambda_sat ); + + l = lambda*V; # arrival rates + + i = find( m == 1 ); # single station queueing centers + if numel(i) + [U(i) R(i) Q(i) X(i)] = qnmm1( l(i), 1./S(i) ); + endif + + i = find( m<1 ); # delay centers + if numel(i) + [U(i) R(i) Q(i) X(i)] = qnmminf( l(i), 1./S(i) ); + endif + + i = find( m>1 ); # multiple stations queueing centers + if numel(i) + [U(i) R(i) Q(i) X(i)] = qnmmm( l(i), 1./S(i), m(i) ); + endif +endfunction +%!test +%! lambda = 0; +%! S = [1 1 1]; +%! V = [1 1 1]; +%! fail( "qnopensingle(lambda,S,V)","lambda must be"); +%! lambda = 1; +%! S = [1 0 1]; +%! fail( "qnopensingle(lambda,S,V)","S must be"); +%! S = [1 1 1]; +%! m = [1 1]; +%! fail( "qnopensingle(lambda,S,V,m)","m must be a vector"); +%! V = [1 1 1 1]; +%! fail( "qnopensingle(lambda,S,V)","same length as S"); + +%!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] = qnopensingle( lambda, S, V ); +%! assert( R, [0.0192 0.0345 0.107], 1e-2 ); +%! assert( U, [0.48 0.42 0.72], 1e-2 ); + +%!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] = qnopensingle( lambda, S, V ); +%! assert( U(1), 0.182, 1e-3 ); +%! assert( X(1), 36.3, 1e-2 ); +%! assert( Q(1), 0.222, 1e-3 ); + +%!test +%! # Compare the results of this function with qnjackson +%! P = [ 0 0.4 0.6 0; ... +%! 0.2 0 0.2 0.6; ... +%! 0 0 0 1; ... +%! 0 0 0 0 ]; +%! lambda = [0.1 0 0 0.3]; +%! V = qnvisits(P,lambda); +%! S = [2 1 2 1.8]; +%! m = [3 1 1 2]; +%! [U R Q X] = qnopensingle( sum(lambda), S, V, m ); +%! [U_j R_j Q_j X_j] = qnjackson( lambda, S, P, m ); +%! assert( U, U_j, 1e-4 ); +%! assert( R, R_j, 1e-4 ); +%! assert( Q, Q_j, 1e-4 ); +%! assert( X, X_j, 1e-4 ); + +%!test +%! lambda=[1]; +%! P=[0]; +%! V=qnvisits(P,lambda); +%! S=[0.25]; +%! [U1 R1 Q1 X1]=qnopensingle(sum(lambda),S,V); +%! [U2 R2 Q2 X2]=qnmm1(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 ); + + +%!demo +%! lambda = 3; +%! V = [16 7 8]; +%! S = [0.01 0.02 0.03]; +%! [U R Q X] = qnopensingle( lambda, S, V ); +%! R_s = dot(R,V) # System response time +%! N = sum(Q) # Average number in system +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnsolve.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,771 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"closed"}, @var{N}, @var{QQ}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"closed"}, @var{N}, @var{QQ}, @var{V}, @var{Z}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"open"}, @var{lambda}, @var{QQ}, @var{V}) +## @deftypefnx {Function File} {[@var{U}, @var{R}, @var{Q}, @var{X}] =} qnsolve (@var{"mixed"}, @var{lambda}, @var{N}, @var{QQ}, @var{V}) +## +## General evaluator of QN models. Networks can be open, +## closed or mixed; single as well as multiclass networks are supported. +## +## @itemize +## +## @item For @strong{closed} networks, the following server types are +## supported: @math{M/M/m}--FCFS, @math{-/G/\infty}, @math{-/G/1}--LCFS-PR, +## @math{-/G/1}--PS and load-dependent variants. +## +## @item For @strong{open} networks, the following server types are supported: +## @math{M/M/m}--FCFS, @math{-/G/\infty} and @math{-/G/1}--PS. General +## load-dependent nodes are @emph{not} supported. Multiclass open networks +## do not support multiple server @math{M/M/m} nodes, but only +## single server @math{M/M/1}--FCFS. +## +## @item For @strong{mixed} networks, the following server types are supported: +## @math{M/M/1}--FCFS, @math{-/G/\infty} and @math{-/G/1}--PS. General +## load-dependent nodes are @emph{not} supported. +## +## @end itemize +## +## @strong{INPUTS} +## +## @table @var +## +## @item N +## Number of requests in the system for closed networks. For +## single-class networks, @var{N} must be a scalar. For multiclass +## networks, @code{@var{N}(c)} is the population size of closed class +## @math{c}. +## +## @item lambda +## External arrival rate (scalar) for open networks. For single-class +## networks, @var{lambda} must be a scalar. For multiclass networks, +## @code{@var{lambda}(c)} is the class @math{c} overall arrival rate. +## +## @item QQ +## List of queues in the network. This must be a cell array +## with @math{N} elements, such that @code{@var{QQ}@{i@}} is +## a struct produced by the @code{qnmknode} function. +## +## @item Z +## External delay ("think time") for closed networks. Default 0. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item U +## If @math{i} is a FCFS node, then @code{@var{U}(i)} is the utilization +## of service center @math{i}. If @math{i} is an IS node, then +## @code{@var{U}(i)} is the @emph{traffic intensity} defined as +## @code{@var{X}(i)*@var{S}(i)}. +## +## @item R +## @code{@var{R}(i)} is the average response time of service center @math{i}. +## +## @item Q +## @code{@var{Q}(i)} is the average number of customers in service center +## @math{i}. +## +## @item X +## @code{@var{X}(i)} is the throughput of service center @math{i}. +## +## @end table +## +## Note that for multiclass networks, the computed results are per-class +## utilization, response time, number of customers and throughput: +## @code{@var{U}(c,k)}, @code{@var{R}(c,k)}, @code{@var{Q}(c,k)}, +## @code{@var{X}(c,k)}, +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [U R Q X] = qnsolve( network_type, varargin ) + if ( nargin < 2 ) + print_usage(); + endif + + ischar(network_type) || \ + usage("First parameter must be a string"); + + network_type = tolower(network_type); + + if ( strcmp(network_type, "open" ) ) + [U R Q X] = __qnsolve_open( varargin{:} ); + elseif ( strcmp(network_type, "closed" ) ) + [U R Q X] = __qnsolve_closed( varargin{:} ); + elseif (strcmp(network_type, "mixed" ) ) + [U R Q X] = __qnsolve_mixed( varargin{:} ); + else + usage( "Invalid network type %s: must be one of \"open\", \"closed\" or \"mixed\"", network_type ); + endif +endfunction + +############################################################################## +## Dispatcher function for open networks +function [U R Q X] = __qnsolve_open( lambda, varargin ) + if ( isscalar(lambda) ) + [U R Q X] = __qnsolve_open_single( lambda, varargin{:} ); + else + [U R Q X] = __qnsolve_open_multi( lambda, varargin{:} ); + endif +endfunction + +############################################################################## +## Worker function for open, single class networks +function [U R Q X] = __qnsolve_open_single( lambda, QQ, V ) + + if ( nargin != 3 ) + print_usage(); + endif + + ( isscalar(lambda) && (lambda>0) ) || \ + usage( "lambda must be a scalar > 0" ); + + iscell(QQ) || \ + usage( "QQ must be a cell array" ); + + N = length(QQ); + + ( isvector(V) && length(V) == N ) || \ + usage( "V must be a vector of length %d", N ); + + V = V(:); # make V a row vector + all(V>=0) || \ + usage( "V must be >= 0" ); + + ## Initialize vectors + S = zeros(size(V)); + m = ones(size(V)); + for i=1:N + QQ{i}.c == 1 || \ + usage( "Multiclass networks are not supported by this function" ); + S(i) = QQ{i}.S; + if __is_li(QQ{i}) + ; # nothing to do + elseif __is_multi(QQ{i}) + m(i) = QQ{i}.m; + elseif __is_is(QQ{i}) + m(i) = -1; + else + usage( "Unsupported type \"%s\" for node %d", QQ{i}.node, i ); + endif + endfor + + [U R Q X] = qnopensingle( lambda, S, V, m ); + __prettyprint( 0, lambda, QQ, V, U, R, Q, X ); +endfunction + + +############################################################################## +## Worker function for open, multiclass networks +function [U R Q X] = __qnsolve_open_multi( lambda, QQ, V ) + if ( nargin != 3 ) + print_usage(); + endif + isvector(lambda) && all(lambda > 0) || \ + usage( "lambda must be a vector >0" ); + lambda = lambda(:)'; # make lambda a row vector + iscell(QQ) || \ + usage( "QQ must be a cell array" ); + C = length(lambda); + K = length(QQ); + [C,K] == size(V) || \ + usage( "V size mismatch" ); + all( all( V>= 0 ) ) || \ + usage( "V must be >= 0 " ); + + S = zeros(C,K); + m = ones(1,K); + for i=1:K + QQ{i}.c == C || \ + usage( "Wrong number of classes for center %d (is %d, should be %d)", i, QQ{i}.c, C ); + S(:,i) = QQ{i}.S(:); + if __is_li(QQ{i}) + ; # nothing to do + elseif __is_is(QQ{i}) + m(i) = -1; + else + usage( "Unsupported type \"%s\" for node %d", QQ{i}.node, i ); + endif + endfor + + [U R Q X] = qnopenmulti( lambda, S, V, m ); + __prettyprint( 0, lambda, QQ, V, U, R, Q, X ); +endfunction + + +############################################################################## +## Dispatcher function for closed networks +function [U R Q X] = __qnsolve_closed( N, varargin ) + if ( isscalar(N) ) + [U R Q X] = __qnsolve_closed_single( N, varargin{:} ); + else + [U R Q X] = __qnsolve_closed_multi( N, varargin{:} ); + endif +endfunction + + +############################################################################## +## Worker function for closed, single-class networks +function [U R Q X] = __qnsolve_closed_single( N, QQ, V, Z ) + + if ( nargin < 3 || nargin > 4 ) + usage(); + endif + + isscalar(N) || \ + usage( "Multiclass networks are not supported by this function" ); + + iscell(QQ) || \ + usage( "QQ must be a cell array" ); + + if ( nargin < 4 ) + Z = 0; + else + isscalar(Z) && Z >= 0 || \ + usage( "Z must be >= 0" ); + endif + + K = length(QQ); + + ( isvector(V) && length(V) == K ) || \ + usage( "V must be a vector of length %d", K ); + + ## Initialize vectors + i_single = i_multi = i_delay = i_ld = []; + for i=1:K + ( QQ{i}.c == 1 ) || \ + usage( "Multiclass networks are not supported by this function" ); + if __is_li(QQ{i}) + i_single = [i_single i]; + elseif __is_multi(QQ{i}) + i_multi = [i_multi i]; + elseif __is_is(QQ{i}) + i_delay = [i_delay i]; + elseif __is_ld(QQ{i}) + i_ld = [i_ld i]; + else + usage( "Unsupported type \"%s\" for node %d", QQ{i}.node, i ); + endif + endfor + p = cell( 1, K ); + + for i=i_multi + p{i} = zeros(1,QQ{i}.m+1); # p(i,j+1) is the probability that there are j jobs at server i + p{i}(1) = 1; + endfor + + for i=i_ld + p{i} = zeros(1,N+1); # p(i,j+1) is the probability that there are j jobs at server i + p{i}(1) = 1; + endfor + + U = R = Q = X = zeros( 1, K ); + ## Trivial case of empty population: just return all zeros + if ( N == 0 ) + return; + endif + X_s = 0; # System throughput + + ## Main MVA loop, iterates over the population size + for n=1:N + + ## Single server nodes + for i=i_single + R(i) = QQ{i}.S .* (1 + Q(i)); + endfor + + ## Multiple server nodes + for i=i_multi + j=0:QQ{i}.m-2; + R(i) = QQ{i}.S / QQ{i}.m * (1+Q(i)+dot( QQ{i}.m-j-1, p{i}( 1+j ) ) ); + endfor + + ## General load-dependent nodes + for i=i_ld + j=1:n; + R(i) = sum( j.*QQ{i}.S(j).*p{i}(j) ); + endfor + + ## Delay centers (IS) + for i=i_delay + R(i) = QQ{i}.S; + endfor + + R_s = dot( V, R ); # System response time + X_s = n / ( Z + R_s ); # System Throughput + Q = X_s * ( V .* R ); + + ## prepare for next iteration + lambda_i = V * X_s; # lambda_i(i) is the node i throughput + + ## Update probabilities for multiple server nodes + for i=i_multi + j=1:QQ{i}.m-1; # range + p{i}(j+1) = lambda_i(i) .* QQ{i}.S ./ min( j,QQ{i}.m ) .* p{i}(j); + p{i}(1) = 1 - 1/QQ{i}.m * ... + (V(i)*QQ{i}.S*X_s + dot( QQ{i}.m-j, p{i}(j+1)) ); + endfor + + ## Update probabilities for load-dependent nodes + for i=i_ld + j=1:n; + p{i}(1+j) = X_s * QQ{i}.S(j) .* p{i}(j) * V(i); + p{i}(1) = 1-sum(p{i}(1+j)); + endfor + + endfor + X = X_s * V; # Service centers throughput + + ## Single server or IS nodes + for i=[i_single i_delay] + U(i) = X(i) .* QQ{i}.S; + endfor + + ## Multiple server nodes + for i=i_multi + U(i) = X(i) .* QQ{i}.S ./ QQ{i}.m; + endfor + + ## General load-dependent nodes + for i=i_ld + U(i) = 1-p{i}(1); + endfor + + __prettyprint( N, 0, QQ, V, U, R, Q, X ); +endfunction + +############################################################################## +## Worker function for closed, multi-class networks +function [U R Q X] = __qnsolve_closed_multi( N, QQ, V, Z ) + + if ( nargin < 3 || nargin > 4 ) + print_usage(); + endif + + isvector(N) && all( N>0 ) || \ + usage( "N must be >0" ); + + iscell(QQ) || \ + usage( "QQ must be a cell array" ); + + C = length(N); ## Number of classes + K = length(QQ); ## Number of service centers + size(V) == [C,K] || \ + usage( "V size mismatch" ); + + if ( nargin < 4 ) + Z = zeros(1,C); + else + isvector(Z) && length(Z) == C || \ + usage( "Z size mismatch" ); + endif + + ## Check consistence of parameters + all( all( V >= 0 ) ) || \ + usage( "V must be >=0" ); + + ## Initialize vectors + i_single = i_multi = i_delay = i_ld = []; + S = zeros(C,K); + for i=1:K + ( QQ{i}.c == C ) || \ + usage( "Service center %d has wrong number of classes (is %d, should be %d)", i, QQ{i}.c, C ); + + if __is_li(QQ{i}) + i_single = [i_single i]; + ( !strcmpi( QQ{i}.node, "m/m/m-fcfs" ) || all( QQ{i}.S(1) == QQ{i}.S )) || \ + usage( "Service times at FIFO node %d are not class-independent", i ); + elseif __is_multi(QQ{i}) + i_multi = [i_multi i]; + elseif __is_is(QQ{i}) + i_delay = [i_delay i]; + elseif __is_ld(QQ{i}) + columns( QQ{i}.S ) == sum(N) || \ + usage( "Load-dependent center %d has insufficient data (is %d, should be %d", i, columns(QQ{i}.S), sum(N) ); + i_ld = [i_ld i]; + else + usage( "Unknown or unsupported type \"%s\" for node %d", QQ{i}.node, i ); + endif + endfor + + ## Initialize results + U = R = zeros( C, K ); + X = zeros( 1, C ); + Q_next = Q = sparse( prod(N+1),K ); + p = cell(1,K); + for k=i_multi + ## p{i}(j+1,k+1) is the probability to have j jobs at node i + ## where the network is in state k + p{k} = zeros( QQ{k}.m+1,prod(N+1) ); + p{k}(1,__get_idx( N, 0*N )) = 1; + endfor + + for k=i_ld + ## p{i}(j+1,k+1) is the probability to have j jobs at node i + ## where the network is in state k + p{k} = zeros( columns(QQ{k}.S )+1, prod(N+1) ); + p{k}(1,__get_idx( N, 0*N )) = 1; + endfor + + ## Main loop + for n=1:sum(N) + feasible_set = population_mix( n, N ); + for nn=1:rows(feasible_set) + n_bar = feasible_set(nn,:); + for c=1:C + if ( n_bar(c) > 0 ) + + ## single server nodes + for k=i_single + n_bar_c = __minusonec(n_bar,c); + idx = __get_idx( N, n_bar_c ); + R(c,k) = QQ{k}.S(c)*(1 + Q( idx, k ) ); + ## for FCFS nodes with class-dependent service times, + ## it is possible to use the following approximation + ## (p. 469 Bolch et al.) + ## + ## R(c,k) = S(c,k) + sum( S(:,k) * Q(idx(:), k) ); + endfor + + ## multi server nodes + for k=i_multi + n_bar_c = __minusonec(n_bar,c); + idx = __get_idx( N, n_bar_c ); + j=0:QQ{k}.m-2; # range + R(c,k) = QQ{k}.S(c)/QQ{k}.m*(1 + Q( idx, k ) + ... + dot(QQ{k}.m-j-1,p{k}(j+1,idx) ) ); + endfor + + ## General load-dependent nodes + for k=i_ld + n_bar_c = __minusonec(n_bar,c); + idx = __get_idx( N, n_bar_c ); + j=1:sum(n_bar); # range + R(c,k) = sum( j .* QQ{k}.S(c,j) .* p{k}(j,idx)' ); + endfor + endif + + ## delay centers + for k=i_delay + R(c,k) = QQ{k}.S(c); + endfor + + endfor # c + X = n_bar ./ ( Z .+ dot(R,V,2)' ); # X(c) = N(c) / ( Z(c) + sum_k R(c,k) * V(c,k) ) + + idx = __get_idx( N, n_bar ); + ## Q_k = sum_c X(c) * R(c,k) + for k=1:K + Q_next( idx, k ) = dot( X, R(:,k) .* V(:,k) ); + endfor + + ## Adjust probabilities for multiple server nodes + for k=i_multi + s=0; # it is actually a vector + j=1:QQ{k}.m-1; + for r=find(n_bar>0) # I don't know how to vectorize this + ii = __minusonec(n_bar,r); + s+=QQ{k}.S(r)*V(r,k)*X(r)*p{k}(j,__get_idx(N,ii)); + endfor + p{k}(j+1,idx) = s./j; + p{k}(1,idx) = 1-1/QQ{k}.m*(sum( QQ{k}.S(:) .* V(:,k) .* X(:) ) + ... + dot( QQ{k}.m-j, p{k}(j+1,idx) ) ); + endfor + + ## Adjust probabilities for general load-dependent server nodes + for k=i_ld + s=0; # it is actually a vector + j=1:sum(n_bar); + for r=find(n_bar>0) + ii = __minusonec(n_bar,r); + s+=QQ{k}.S(r,sum(n_bar))*V(r,k)*X(r)*p{k}(j,__get_idx(N,ii)); + endfor + p{k}(j+1,idx) = s; + p{k}(1,idx) = 1-sum(p{k}(1+j,idx)); + endfor + endfor + Q = Q_next; + Q_next = sparse( prod(N+1), K ); + endfor + for k=1:K + if __is_ld(QQ{k}) + U(:,k) = 1-p{k}(1, __get_idx(N,N)); + else + U(:,k) = X(:) .* QQ{k}.S(:) .* V(:,k); # U(c,k) = X(c)*D(c,k) + endif + endfor + Q = (diag(X)*R).*V; # dmult(X,R).*V; + X = diag(X)*V; # dmult(X,V); +endfunction + +############################################################################## +## Compute the linear index corresponding to vector i from a population +## of N. +function idx = __get_idx( N, i ) + i_cell = num2cell( i+1 ); + idx = sub2ind( N+1, i_cell{:} ); +endfunction + +############################################################################## +## Given an input vector n, returns an output vector r which is equal to +## n except that the element at the c-th position is decreased by one: +## r(c) = n(c)-1. Warning: no check is made on the parameters +function r = __minusonec( n, c ) + r = n; r(c) -= 1; +endfunction + + +############################################################################## +## Worker function for mixed networks. This function delegates to qnmix +function [U R Q X] = __qnsolve_mixed( lambda, N, QQ, V ) + if ( nargin != 4 ) + print_usage(); + endif + ( isvector(lambda) && isvector(N) && size_equal(lambda,N) ) || \ + usage( "lambda and N must be vectors of the same size" ); + ( iscell(QQ) && length(QQ) == length(lambda) ) || \ + usage( "QQ size mismatch (is %d, should be %d)", length(QQ), length(lambda) ); + + C = length(lambda); # number of classes + K = length(QQ); # number of service centers + S = zeros(C,K); + m = ones(1,K); + ## fill S matrix + for k=1:K + if __is_ld(QQ{k}) + usage( "General load-dependent service center %d is not supported", k ); + elseif __is_is(QQ{k}) + m(k) = -1; + else + m(k) = QQ{k}.m; + endif + S(:,k) = QQ{k}.S; + endfor + [U R Q X] = qnmix( lambda, N, S, V, m ); + __prettyprint( N, lambda, QQ, V, U, R, Q, X ); +endfunction + +############################################################################## +## return true iff Q is an infinite server (IS) node +function result = __is_is( Q ) + result = strcmp(Q.node, "-/g/inf" ); +endfunction + +############################################################################## +## return true iff Q is a multi-server FIFO node +function result = __is_multi( Q ) + result = (strcmp(Q.node, "m/m/m-fcfs") && Q.m>1); +endfunction + +############################################################################## +## return true iff Q is a single-server, load-dependent node +function result = __is_ld( Q ) + result = ( (strcmp(Q.node, "m/m/m-fcfs") || \ + strcmp(Q.node, "-/g/1-lcfs-pr") || \ + strcmp(Q.node, "-/g/1-ps" ) ) && \ + columns( Q.S ) > 1 ); +endfunction + +############################################################################## +## return ture iff Q is a single-server, load-independent node +function result = __is_li( Q ) + result = ((Q.m==1) && (1 == columns( Q.S )) && !strcmp( Q.node, "-/g/inf" ) ); +endfunction + +############################################################################## +## This function is used to "pretty-print" a solved network. Used for +## debugging +function __prettyprint( N, lambda, QQ, V, U, R, Q, X ) + return; ## immediately return + [errorcode, N, lambda] = common_size( N, lambda ); + if ( errorcode) + usage( "N and lambda are of incompatible size" ); + endif + ( isvector(N) && isvector(lambda) && size_equal(lambda,N) ) || \ + usage( "N and lambda must be vector of the same length" ); + C = length(N); + K = length(QQ); # number of service centers + + [C,K] == size(V) || \ + usage( "V size mismatch" ); + [C,K] == size(U) || \ + usage( "U size mismatch" ); + [C,K] == size(R) || \ + usage( "R size mismatch" ); + [C,K] == size(Q) || \ + usage( "Q size mismatch" ); + [C,K] == size(X) || \ + usage( "X size mismatch" ); + + for c=1:C + printf("\n"); + printf("=== CLASS %d ===\n", c ); + if ( N(c)>0 ) + printf("Type: CLOSED\nPopulation: %d\n", N(c)) + else + printf("Type: OPEN\nRequests arrival rate: %6.2f\n", lambda(c)) + endif + printf("\n"); + printf("+---+---------------+---+------+------+------+------+------+------+\n"); + printf("| i | Node type | m | S(i) | V(i) | U(i) | R(i) | Q(i) | X(i) |\n"); + printf("+---+---------------+---+------+------+------+------+------+------+\n"); + for i=1:K + if ( isscalar(QQ{i}.S(c)) ) + serv = sprintf("%6.2f",QQ{i}.S(c)); + else + serv = "LD"; + endif + printf("|%3d|%-33s| | | | |\n", i, QQ{i}.comment); + printf("| |%15s|%3d|%6s|%6.2f|%6.4f|%6.2f|%6.2f|%6.2f|\n", + QQ{i}.node, QQ{i}.m, serv, V(c,i), U(c,i), R(c,i), Q(c,i), X(c,i) ); + + endfor + printf("+---+---------------+---+------+------+------+------+------+------+\n"); + printf("| THIS CLASS STATISTICS | ---- |%6.2f|%6.2f|%6.2f|\n", + dot(R(c,:),V(c,:)), sum(Q(c,:)), X(c,1)/V(c,1) ); + printf("+---+---------------+---+------+------+------+------+------+------+\n\n"); + endfor +endfunction + +%!test +%! # Example 8.7 p. 349 Bolch et al. +%! N = 3; +%! Q1 = qnmknode( "m/m/m-fcfs", .5, 2 ); +%! Q2 = qnmknode( "m/m/m-fcfs", 1/1.667 ); +%! Q3 = qnmknode( "m/m/m-fcfs", 1/1.25 ); +%! Q4 = qnmknode( "m/m/m-fcfs", 1./[1 2 3] ); +%! V = [ 1 .5 .5 1 ]; +%! [U R Q X] = qnsolve("closed",N, { Q1, Q2, Q3, Q4 }, V); +%! assert( Q, [0.624 0.473 0.686 1.217], 1e-3 ); +%! assert( R, [0.512 0.776 1.127 1], 1e-3 ); + +%!test +%! # Example 8.7 p. 349 Bolch et al. +%! N = 3; +%! Q1 = qnmknode( "m/m/m-fcfs", 1/2, 2 ); +%! Q2 = qnmknode( "m/m/m-fcfs", 1/1.667 ); +%! Q3 = qnmknode( "m/m/m-fcfs", 1/1.25 ); +%! Q4 = qnmknode( "-/g/inf", 1 ); +%! V = [ 1 .5 .5 1 ]; +%! [U R Q X] = qnsolve("closed",N, { Q1, Q2, Q3, Q4 }, V); +%! assert( Q, [0.624 0.473 0.686 1.217], 1e-3 ); +%! assert( R, [0.512 0.776 1.127 1], 1e-3 ); + +%!test +%! # Example 8.4 p. 333 Bolch et al. +%! N = 3; +%! Q1 = qnmknode( "m/m/m-fcfs", .5, 2 ); +%! Q2 = qnmknode( "m/m/m-fcfs", .6 ); +%! Q3 = qnmknode( "m/m/m-fcfs", .8 ); +%! Q4 = qnmknode( "-/g/inf", 1 ); +%! V = [ 1 .5 .5 1 ]; +%! [U R Q X] = qnsolve("closed",N, { Q1, Q2, Q3, Q4 }, V); +%! assert( U(1:3), [.304 .365 .487], 1e-3 ); +%! assert( X, [1.218 0.609 0.609 1.218], 1e-3 ); + +%!test +%! # Same as above, with center 1 replaced with a load-dependent service center +%! N = 3; +%! Q1 = qnmknode( "m/m/m-fcfs", [.5 .25 .25] ); +%! Q2 = qnmknode( "m/m/m-fcfs", .6 ); +%! Q3 = qnmknode( "m/m/m-fcfs", .8 ); +%! Q4 = qnmknode( "m/m/m-fcfs", [1 1/2 1/3] ); +%! V = [ 1 .5 .5 1 ]; +%! [U R Q X] = qnsolve("closed",N, { Q1, Q2, Q3, Q4 }, V); +%! assert( U(2:3), [.365 .487], 1e-3 ); ## NOTE: Utilization U(1) is computed differently from M/M/m nodes and load-dependent M/M/1 nodes +%! assert( X, [1.218 0.609 0.609 1.218], 1e-3 ); + +%!test +%! # Example 7.4 p. 287 Bolch et al. +%! QQ = { qnmknode( "m/m/m-fcfs", 0.04 ), \ +%! qnmknode( "m/m/m-fcfs", 0.03 ), \ +%! qnmknode( "m/m/m-fcfs", 0.06 ), \ +%! qnmknode( "m/m/m-fcfs", 0.05 ) }; +%! P = [ 0 0.5 0.5 0; 1 0 0 0; 0.6 0 0 0; 1 0 0 0 ]; +%! lambda = [0 0 0 4]; +%! [U R Q X] = qnsolve("open", sum(lambda), QQ, qnvisits(P,lambda) ); +%! assert( X, [20 10 10 4], 1e-4 ); +%! assert( U, [0.8 0.3 0.6 0.2], 1e-2 ); +%! assert( R, [0.2 0.043 0.15 0.0625], 1e-3 ); +%! assert( Q, [4, 0.429 1.5 0.25], 1e-3 ); + +%!test +%! V = [1 1; 1 1]; +%! Q1 = qnmknode( "m/m/m-fcfs", [1;2] ); +%! Q2 = qnmknode( "m/m/m-fcfs", [3;4] ); +%! lambda = [3/19 2/19]; +%! [U R Q] = qnsolve("open", lambda, { Q1, Q2 }, V); +%! assert( U(1,1), 3/19, 1e-6 ); +%! assert( U(2,1), 4/19, 1e-6 ); +%! assert( R(1,1), 19/12, 1e-6 ); +%! assert( R(1,2), 57/2, 1e-6 ); +%! assert( Q(1,1), .25, 1e-6 ); + +## Example 9.5 p. 337, Bolch et al. +%!test +%! QQ = { qnmknode( "m/m/m-fcfs", [0.2; 0.2], 2 ), \ +%! qnmknode( "-/g/1-ps", [0.4; 0.6] ), \ +%! qnmknode( "-/g/inf", [1; 2] ) }; +%! V = [ 1 0.6 0.4; 1 0.3 0.7 ]; +%! N = [ 2 1 ]; +%! [U R Q X] = qnsolve( "closed", N, QQ, V ); +%! assert( Q, [ 0.428 0.726 0.845; 0.108 0.158 0.734 ], 1e-3 ); +%! assert( X(1,1), 2.113, 1e-3 ); # CHECK +%! assert( X(2,1), 0.524, 1e-3 ); # CHECK +%! assert( all( all(U(:,[1,2])<=1) ) ); + +## Same as above, but with general load-dependent centers +%!test +%! QQ = { qnmknode( "m/m/m-fcfs", [0.2 0.1 0.1; 0.2 0.1 0.1] ), \ +%! qnmknode( "-/g/1-ps", [0.4; 0.6] ), \ +%! qnmknode( "-/g/inf", [1; 2] ) }; +%! V = [ 1 0.6 0.4; 1 0.3 0.7 ]; +%! N = [ 2 1 ]; +%! [U R Q X] = qnsolve( "closed", N, QQ, V ); +%! assert( Q, [ 0.428 0.726 0.845; 0.108 0.158 0.734 ], 1e-3 ); +%! assert( X(1,1), 2.113, 1e-3 ); # CHECK +%! assert( X(2,1), 0.524, 1e-3 ); # CHECK +%! assert( all( all(U(:,[1,2])<=1) ) ); + +%!test +%! # example p. 26 Schwetman +%! QQ = { qnmknode( "m/m/m-fcfs", [.25; .25] ), +%! qnmknode( "-/g/1-ps", [0; .1] ) }; +%! V = [1 0; 1 1]; +%! lambda = [1 0]; +%! N = [0 3]; +%! [U R Q X] = qnsolve( "mixed", lambda, N, QQ, V ); +%! assert( U(1,1), .25, 1e-3 ); +%! assert( X(1,1), 1.0, 1e-3 ); +%! assert( [R(1,1) R(2,1) R(2,2)], [1.201 0.885 0.135], 1e-3 ); + +%!demo +%! QQ = { qnmknode( "m/m/m-fcfs", [0.2 0.1 0.1; 0.2 0.1 0.1] ), \ +%! qnmknode( "-/g/1-ps", [0.4; 0.6] ), \ +%! qnmknode( "-/g/inf", [1; 2] ) }; +%! V = [ 1 0.6 0.4; \ +%! 1 0.3 0.7 ]; +%! N = [ 2 1 ]; +%! [U R Q X] = qnsolve( "closed", N, QQ, V );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/inst/qnvisits.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,488 @@ +## Copyright (C) 2008, 2009, 2010, 2011, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. +## +## The queueing toolbox is free software: you can redistribute it and/or +## modify it under the terms of the GNU General Public License as +## published by the Free Software Foundation, either version 3 of the +## License, or (at your option) any later version. +## +## The queueing toolbox is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied warranty +## of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with the queueing toolbox. If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## +## @deftypefn {Function File} {[@var{V} @var{ch}] =} qnvisits (@var{P}) +## @deftypefnx {Function File} {@var{V} =} qnvisits (@var{P}, @var{lambda}) +## +## Compute the average number of visits to the service centers of a +## single class, open or closed Queueing Network with @math{N} service +## centers. +## +## @strong{INPUTS} +## +## @table @var +## +## @item P +## Routing probability matrix. For single class networks, +## @code{@var{P}(i,j)} is the probability that a request which completed +## service at center @math{i} is routed to center @math{j}. For closed +## networks it must hold that @code{sum(@var{P},2)==1}. The routing +## graph myst be strongly connected, meaning that it must be possible to +## eventually reach each node starting from each node. For multiple +## class networks, @code{@var{P}(r,i,s,j)} is the probability that a +## class @math{r} request which completed service at center @math{i} is +## routed to center @math{j} as a class @math{s} request. Class switching +## is supported. +## +## @item lambda +## (open networks only) vector of external arrivals. For single class +## networks, @code{@var{lambda}(i)} is the external arrival rate to +## center @math{i}. For multiple class networks, +## @code{@var{lambda}(r,i)} is the arrival rate of class @math{r} +## requests to center @math{i}. If this parameter is omitted, the +## network is assumed to be closed. +## +## @end table +## +## @strong{OUTPUTS} +## +## @table @var +## +## @item V +## For single class networks, @code{@var{V}(i)} is the average number of +## visits to server @math{i}. For multiple class networks, +## @code{@var{V}(r,i)} is the class @math{r} visit ratio at center +## @math{i}. +## +## @item ch +## (For closed networks only). @code{@var{ch}(c,k)} is the +## number of the chain that class @math{c} at center @math{k} belongs to. +## The total number of chains is @code{max(@var{ch})}. +## +## @end table +## +## @end deftypefn + +## Author: Moreno Marzolla <marzolla(at)cs.unibo.it> +## Web: http://www.moreno.marzolla.name/ + +function [V ch] = qnvisits( P, varargin ) + + if ( nargin < 1 || nargin > 2 ) + print_usage(); + endif + + ( ndims(P) == 2 || ndims(P) == 4 ) || \ + usage("P must be a 2- or 4-dimensional matrix"); + + if ( ndims(P) == 2 ) + V = __qnvisitssingle( P, varargin{:} ); + ch = [1]; + else + [V ch] = __qnvisitsmulti( P, varargin{:} ); + endif +endfunction +%!test +%! P = [-1 0; 0 0]; +%! fail( "qnvisits(P)", "not a transition probability" ); +%! P = [1 0; 0.5 0]; +%! fail( "qnvisits(P)", "not a stochastic" ); +%! P = [1 0; 0 1]; lambda=[0 -1]; +%! fail( "qnvisits(P,lambda)", "contains negative" ); + +%!test +%! +%! ## Closed, single class network +%! +%! P = [0 0.3 0.7; 1 0 0; 1 0 0]; +%! V = qnvisits(P); +%! assert( V*P,V,1e-5 ); +%! assert( V, [1 0.3 0.7], 1e-5 ); + +%!test +%! +%! ## Open, single class network +%! +%! P = [0 0.2 0.5; 1 0 0; 1 0 0]; +%! lambda = [ 0.1 0.3 0.2 ]; +%! V = qnvisits(P,lambda); +%! assert( V*P+lambda/sum(lambda),V,1e-5 ); + +%!test +%! +%! ## Test tolerance of the qnvisits() function. +%! ## This test builds random transition probability matrices and tries +%! ## to compute the visit counts on them. +%! +%! for k=[5, 10, 20, 50] +%! P = rand(k,k); +%! nor = sum(P,2); +%! P = diag(1./nor)*P; +%! V = qnvisits(P); +%! assert( V*P, V, 1e-5 ); +%! endfor + +%!test +%! +%! ## Closed, multiclass network +%! +%! C = 2; K = 3; +%! P = zeros(C,K,C,K); +%! P(1,1,1,2) = 1; +%! P(1,2,1,1) = 1; +%! P(2,1,2,3) = 1; +%! P(2,3,2,1) = 1; +%! V = qnvisits(P); +%! for c=1:C +%! for k=1:K +%! assert(V(c,k), sum(sum(V .* P(:,:,c,k))), 1e-5); +%! endfor +%! endfor + +%!test +%! +%! ## Test multiclass network. Example from Schwetman (figure 7, page 9 of +%! ## http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1258&context=cstech +%! ## "Testing network-of-queues software, technical report CSD-TR 330, +%! ## Purdue University). +%! +%! C = 2; K = 4; +%! P = zeros(C,K,C,K); +%! # class 1 routing +%! P(1,1,1,1) = .05; +%! P(1,1,1,2) = .45; +%! P(1,1,1,3) = .5; +%! P(1,2,1,1) = 1; +%! P(1,3,1,1) = 1; +%! # class 2 routing +%! P(2,1,2,1) = .01; +%! P(2,1,2,3) = .5; +%! P(2,1,2,4) = .49; +%! P(2,3,2,1) = 1; +%! P(2,4,2,1) = 1; +%! V = qnvisits(P); +%! for c=1:C +%! for i=1:K +%! assert(V(c,i), sum(sum(V .* P(:,:,c,i))), 1e-5); +%! endfor +%! endfor + +%!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(sum(lambda)); +%! V = qnvisits(P, lambda); +%! assert( all( 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 +%! +%! ## Network with class switching. +%! ## This is example in figure 9 of +%! ## Schwetman, "Implementing the Mean Value Analysis +%! ## Algorithm fort the solution of Queueing Network Models", Technical +%! ## Report CSD-TR-355, Department of Computer Science, Purdue Univrsity, +%! ## Feb 15, 1982 +%! ## http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1285&context=cstech +%! +%! C = 2; K = 3; +%! S = [.01 .07 .10; \ +%! .05 0.7 .10 ]; +%! P = zeros(C,K,C,K); +%! P(1,1,1,2) = .7; +%! P(1,1,1,3) = .2; +%! P(1,1,2,1) = .1; +%! P(2,1,2,2) = .3; +%! P(2,1,2,3) = .5; +%! P(2,1,1,1) = .2; +%! P(1,2,1,1) = P(1,3,1,1) = 1; +%! P(2,2,2,1) = P(2,3,2,1) = 1; +%! N = [3 0]; +%! V = qnvisits(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] = qnvisits(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] = qnvisits(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( "qnvisits(P)", "different"); + +%!test +%! +%! ## Network with two classes representing independent chains. +%! ## This is example in figure 8 of +%! ## Schwetman, "Implementing the Mean Value Analysis +%! ## Algorithm fort the solution of Queueing Network Models", Technical +%! ## Report CSD-TR-355, Department of Computer Science, Purdue Univrsity, +%! ## Feb 15, 1982 +%! ## http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1285&context=cstech +%! +%! C = 2; K = 2; +%! P = zeros(C,K,C,K); +%! P(1,1,1,3) = P(1,3,1,1) = 1; +%! P(2,2,2,3) = P(2,3,2,2) = 1; +%! V = qnvisits(P); +%! assert( V, [1 0 1; 0 1 1], 1e-5 ); + +%!demo +%! P = [ 0 0.4 0.6 0; \ +%! 0.2 0 0.2 0.6; \ +%! 0 0 0 1; \ +%! 0 0 0 0 ]; +%! lambda = [0.1 0 0 0.3]; +%! V = qnvisits(P,lambda); +%! S = [2 1 2 1.8]; +%! m = [3 1 1 2]; +%! [U R Q X] = qnopensingle( sum(lambda), S, V, m ); + +############################################################################## +## Solve the visit equation for multiclass networks with class switching +## P(r,i,s,j) is the probability that a class-r customer on service +## center i moves to service center j as a class-s customer. lambda(r,i) +## is the arrival rate of class-r customers on service center i +function [V chains] = __qnvisitsmulti( P, lambda ) + [C, K, C2, K2] = size( P ); + (K == K2 && C == C2) || \ + usage( "P must be a [C,K,C,K] matrix"); + + chains = []; + + if ( nargin == 1 ) + ## closed network: solve the traffic equations: + ## V(s,j) = sum_r sum_i V(r,i) * P(r,i,s,j), for all s,j + ## V(s,1) = 1 for all s + ## + ## FIXME: the constraint V(s,1) = 1 assumes that all customer + ## classes visit center 1, which in general could not be the case. + ## A better idea would be to set V(s,i) = 1 for any center i which + ## is visited by class s requests. + A = reshape(P,[K*C K*C])-eye(K*C); + b = zeros(1,K*C); + + CH = __scc(reshape(P,[C*K C*K])>0); + nCH = max(CH); # number of chains + CH = reshape(CH,C,K); # chains + + chains = zeros(1,C); + + for k=1:K + for c=1:C + if ( chains(c) == 0 ) + chains(c) = CH(c,k); + else + ( CH(c,k) == 0 || chains(c) == CH(c,k) ) || \ + error("Class %d belongs to different chains",c); + endif + endfor + endfor + + ## Since there may be queueing centers which are never + ## visited by some chain(s), we must be careful here. Consider the + ## following example: + + ## +---------------------------+ + ## | +---+ +---+ +---+ | Class 1 + ## +--| |----| |----| |--+ + ## | 1 | | 2 | | 3 | + ## | | ..| |....| |.. + ## +---+ . +---+ +---+ . Class 2 + ## .................. + + ## There are two classes, 1 and 2. These must correspond to two + ## chains; note that server 1 is never visited by class 2. In the + ## situation above, CH(2,1) = 0. Obviously, we also have V(2,1) = 0. + + ## To find a solution to the linear system V(s,j) = sum_r sum_i + ## V(r,i) P(r,i,s,j) we must set some constraints (otherwise the + ## system may be under defined). If node k is never visited by class + ## c, we set the constraint V(c,k) = 0; If node k is visited by + ## class c as part of chain q, we set constraints(q)=1, and let + ## V(c,k) = 1. + + constraints = zeros(1,nCH); # we put one constraint per chain + + for c=1:C + for k=1:K + cc = CH(c,k); + if ( cc == 0 || constraints(cc) == 0 ) + ii = sub2ind([C K],c,k); + A(:,ii) = 0; + A(ii,ii) = 1; + if ( cc > 0 ) + ## we put one constraint for this chain + constraints(cc) = 1; + b(ii) = 1; + else + b(ii) = 0; + endif + endif + endfor + endfor + V = reshape(b/A, C, K); + else + ## open network: solve the traffic equations: V(s,j) = lambda(s,j) / + ## lambda + sum_r sum_i V(r,i) * P(r,i,s,j), for all s,j where + ## lambda is defined as sum_r sum_i lambda(r,i) + + [C,K] == size(lambda) || \ + usage( "lambda size mismatch" ); + + ## solve the traffic equation + A = eye(K*C) - reshape(P,[K*C K*C]); + b = reshape(lambda / sum(sum(lambda)), [1,K*C]); + V = reshape(b/A, [C, K]); + endif + ## Make sure that no negative values appear (sometimes, numerical + ## errors produce tiny negative values instead of zeros) + V = max(0,V); +endfunction + +## compute strongly connected components using Kosaraju's algorithm. +## This is not as efficient as Tarjan's algorithm, as it requires two +## graph visits. +## +## In this implementation, an isolated node without self loops will NOT +## belong to any SCC. Although this is not formally correct from the +## graph theoretic point of view, it is necessary to compute chains +## correctly. +function s = __scc(G) + assert(issquare(G)); + N = rows(G); + GF = (G>0); + GB = (G'>0); + s = zeros(N,1); + c=1; + for n=1:N + if (s(n) == 0) + fw = __dfs(GF,n); + bw = __dfs(GB,n); + r = (fw & bw); + s(r) = c++; + endif + endfor +endfunction + +## Executes a dfs visit on graph G, starting from source node s +function v = __dfs(G, s) + assert( issquare(G) ); + N = rows(G); + v = stack = zeros(1,N); ## v(i) == 1 iff node i has been visited + q = 1; # first empty slot in queue + stack(q++) = s; + ## Note: node s is NOT marked as visited; it will me marked as visited + ## only if we visit it again. This is necessary to ensure that + ## isolated nodes without self loops will not belong to any SCC. + while( q>1 ) + n = stack(--q); + ## explore neighbors of n: all f in G(n,:) such that v(f) == 0 + + ## The following instruction is equivalent to: + ## for f=find(G(n,:)) + ## if ( v(f) == 0 ) + for f = find ( G(n,:) & (v==0) ) + stack(q++) = f; + v(f) = 1; + endfor + endwhile +endfunction + +############################################################################## +## Solve the visit equation for single class networks. +function V = __qnvisitssingle( P, lambda ) + + issquare(P) || \ + usage( "P must be a square matrix" ); + + N = size(P,1); + V = zeros(N,N); + + all( all(P>=0) ) && all( sum(P,2)<=1+1e-5 ) || \ + usage( "P is not a transition probability matrix" ); + + if ( nargin < 2 ) + ## + ## Closed network + ## + all( abs( sum(P,2)-1 ) < 1e-5 ) || \ + error( "P is not a stochastic matrix for closed networks" ); + + A = P-eye(N); + b = zeros(1,N); + i = 1; # reference station + A(:,i) = 0; A(i,i) = 1; + b(i) = 1; + V = b/A; + else + ## Open network + ( isvector(lambda) && length(lambda) == N ) || \ + usage( "lambda size mismatch" ); + all( lambda>= 0 ) || \ + usage( "lambda contains negative values" ); + + A = eye(N)-P; + b = lambda / sum(lambda); + V = b/A; + endif + ## Make sure that no negative values appear (sometimes, numerical + ## errors produce tiny negative values instead of zeros) + V = max(0,V); +endfunction +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/scripts/Makefile Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,31 @@ +DISTFILES=gethelp.cc munge-texi.cc Makefile mkdoc pmva.y pmva.l test.pmva + +.PHONY: clean + +ALL: gethelp munge-texi + +gethelp: gethelp.cc + +munge-texi: munge-texi.cc + +dist: + ln $(DISTFILES) ../`cat ../fname`/scripts/ + +clean: + \rm -f *~ *.o y.tab.* lex.yy.* + +distclean: clean + \rm -f gethelp munge-texi + +pmva: y.tab.o lex.yy.o + $(CC) y.tab.o lex.yy.o -o $@ + +lex.yy.o: lex.yy.c y.tab.h + +y.tab.o: y.tab.c y.tab.h pmva.h + +y.tab.c y.tab.h: pmva.y + bison -y -l -d $< + +lex.yy.c: pmva.l + flex -L $<
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/scripts/gethelp.cc Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,162 @@ +/* + +Copyright (C) 1999, 2000, 2003, 2007 John W. Eaton +Copyright (C) 2011 Moreno Marzolla + +This file is part of the queueing toolbox. + +The queueing toolbox is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 3 of the +License, or (at your option) any later version. + +The queueing toolbox is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +#if defined (__DECCXX) +#define __USE_STD_IOSTREAM +#endif + +#include <string> +#include <iostream> +#include <cstdio> + +#ifndef NPOS +#define NPOS std::string::npos +#endif + +static bool +looks_like_octave_copyright (const std::string& s) +{ + // Perhaps someday we will want to do more here, so leave this as a + // separate function. + + return (s.substr (0, 9) == "Copyright"); +} + +// Eat whitespace and comments from FFILE, returning the text of the +// first block of comments that doesn't look like a copyright notice, + +static std::string +extract_help_text (void) +{ + std::string help_txt; + + bool first_comments_seen = false; + bool begin_comment = false; + bool have_help_text = false; + bool in_comment = false; + bool discard_space = true; + int c; + + while ((c = std::cin.get ()) != EOF) + { + if (begin_comment) + { + if (c == '%' || c == '#') + continue; + else if (discard_space && c == ' ') + { + discard_space = false; + continue; + } + else + begin_comment = false; + } + + if (in_comment) + { + if (! have_help_text) + { + first_comments_seen = true; + help_txt += (char) c; + } + + if (c == '\n') + { + in_comment = false; + discard_space = true; + + if ((c = std::cin.get ()) != EOF) + { + if (c == '\n') + break; + } + else + break; + } + } + else + { + switch (c) + { + case ' ': + case '\t': + if (first_comments_seen) + have_help_text = true; + break; + + case '\n': + if (first_comments_seen) + have_help_text = true; + continue; + + case '%': + case '#': + begin_comment = true; + in_comment = true; + break; + + default: + goto done; + } + } + } + + done: + + if (! help_txt.empty ()) + { + if (looks_like_octave_copyright (help_txt)) + help_txt.resize (0); + + if (help_txt.empty ()) + help_txt = extract_help_text (); + } + + return help_txt; +} + +int +main (int argc, char **argv) +{ + std::string name; + + if (argc != 2) + { + std::cerr << "usage: gethelp name\n"; + return 1; + } + else + name = argv[1]; + + std::string help_text = extract_help_text (); + + if (! help_text.empty ()) + { + std::cout << "" << name << "\n" << help_text; + + if (help_text[help_text.length () - 1] != '\n') + std::cout << "\n"; + } + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/scripts/mkdoc Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,45 @@ +#! /bin/sh +# +# Copyright (C) 1999, 2002, 2005, 2007 John W. Eaton +# +# This file is part of Octave. +# +# Octave is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# Octave is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with Octave; see the file COPYING. If not, see +# <http://www.gnu.org/licenses/>. + +# Adapted to the queueing toolbox by Moreno Marzolla <marzolla (at) cs.unibo.it>, august 2008. + +set -e + +if test $# != 1; then + d=. +else + d=$1 +fi + +if test -f gethelp; then + cat << EOF +### DO NOT EDIT! +### +### This file is generated automatically from the qnetwork sources. +### Edit those files instead and run make to update this file. + +EOF + find $d -name '*.m' | \ + sed "s,\(.*\)/\(.*\)\.m,./gethelp \2 < & | sed 's/^ *@/@/'," | \ + /bin/sh +else + echo "gethelp program seems to be missing!" 1>&2 + exit 1 +fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/scripts/munge-texi.cc Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,244 @@ +/* + +Copyright (C) 1999, 2000, 2002, 2003, 2005, 2007 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +<http://www.gnu.org/licenses/>. + +*/ + +#if defined (__DECCXX) +#define __USE_STD_IOSTREAM +#endif + +#include <cctype> +#include <iostream> +#include <fstream> +#include <string> +#include <map> + +#include <cstdlib> +#include <cstring> + +static const char doc_delim = ''; + +static std::map<std::string, std::string> help_text; + +static void +fatal (const std::string& msg) +{ + std::cerr << msg << "\n"; + exit (1); +} + +static void +usage (void) +{ + std::cerr << "usage: munge-texi -d DOCSTRING-FILE file ...\n"; + exit (1); +} + +static std::string +extract_symbol_name (std::istream& is) +{ + std::string symbol_name; + + int c; + while ((c = is.get ()) != EOF && c != '\n') + symbol_name += (char) c; + + return symbol_name; +} + +static std::string +extract_docstring (std::istream& is) +{ + std::string doc; + + int c; + while ((c = is.get ()) != EOF && c != doc_delim) + doc += (char) c; + + return doc; +} + +static void +skip_comments (std::ifstream& is) +{ + int c; + + bool in_comment = false; + + while ((c = is.get ()) != EOF) + { + if (c == '#') + in_comment = true; + else if (c == '\n') + in_comment = false; + else if (! (in_comment || ::isspace (c))) + { + is.putback (c); + break; + } + } +} + +static void +process_doc_file (const std::string& fname) +{ + std::ifstream infile (fname.c_str ()); + + if (infile) + { + skip_comments (infile); + + if (infile.get () != doc_delim) + fatal ("invalid doc file format"); + + std::string symbol_name; + + do + { + symbol_name = extract_symbol_name (infile); + + if (! symbol_name.empty ()) + { + std::string doc_string = extract_docstring (infile); + + if (help_text.find (symbol_name) != help_text.end ()) + std::cerr << "ignoring duplicate entry for " + << symbol_name << "\n"; + else + help_text[symbol_name] = doc_string; + } + } + while (! symbol_name.empty ()); + } + else + fatal ("unable to open docfile"); +} + +static void +process_texi_input_file (std::istream& is, std::ostream& os) +{ + os << "@c DO NOT EDIT! Generated automatically by munge-texi.\n\n"; + + bool bol = true; + + int c; + while ((c = is.get ()) != EOF) + { + if (bol) + { + if (c == '@') + { + std::string symbol_name; + + char buf[16]; + int i = 0; + buf[i++] = c; + + if ((buf[i++] = (char) is.get ()) == 'D' + && (buf[i++] = (char) is.get ()) == 'O' + && (buf[i++] = (char) is.get ()) == 'C' + && (buf[i++] = (char) is.get ()) == 'S' + && (buf[i++] = (char) is.get ()) == 'T' + && (buf[i++] = (char) is.get ()) == 'R' + && (buf[i++] = (char) is.get ()) == 'I' + && (buf[i++] = (char) is.get ()) == 'N' + && (buf[i++] = (char) is.get ()) == 'G' + && (buf[i++] = (char) is.get ()) == '(') + { + while ((c = is.get ()) != EOF && c != ')') + symbol_name += (char) c; + + if (is.eof ()) + fatal ("end of file while reading @DOCSTRING command"); + else + { + std::string doc_string = help_text[symbol_name]; + + int j = 0; + while (doc_string[j] == ' ') + j++; + + if (doc_string.substr (j, 15) == "-*- texinfo -*-") + { + j += 15; + + while (isspace (doc_string[j])) + j++; + + // Make `see also' references in functions + // possible using @anchor{TAG} (new with + // Texinfo 4.0). + + os << "@anchor{doc-" << symbol_name << "}\n"; + + os << doc_string.substr (j); + } + else + os << doc_string; + } + } + else + { + buf[i] = '\0'; + os << buf; + + if (buf[i - 1] == '\n') + bol = true; + } + } + else + os.put ((char) c); + } + else + { + if (c == '\n') + bol = true; + + os.put ((char) (c)); + } + } +} + +int +main (int argc, char **argv) +{ + while (*++argv) + { + if (! strcmp (*argv, "-d")) + { + if (*++argv) + process_doc_file (*argv); + else + usage (); + } + else + break; + } + + process_texi_input_file (std::cin, std::cout); + + return 0; +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/scripts/pmva.l Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,78 @@ +/**************************************************************************** + * + * pmva.l + * + * Lexer for the PMVA notation. + * + * Copyright (C) 2011 Moreno Marzolla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ****************************************************************************/ + +/* + * See pmva.y for details + */ +%{ +#include "stdio.h" +#include "pmva.h" +#include "y.tab.h" +int linenum=1; +%} + +DIGITS [0-9]+ +ID [a-zA-Z][A-Za-z0-9_]* +WS [ \t]+ +LF [\r\n] +FLOAT {DIGITS}?\.{DIGITS} +INT {DIGITS} + +%% + +{WS} /* nothing to do */ +{LF} { linenum++; } +classes { return TOK_CLASSES; } +servers { return TOK_SERVERS; } +routing { return TOK_ROUTING; } +network { return TOK_NETWORK; } +end { return TOK_END; } +FCFS { return TOK_FCFS; } +PS { return TOK_PS; } +IS { return TOK_IS; } +LI { return TOK_LI; } +MS { return TOK_MS; } +LD { return TOK_LD; } +POP { return TOK_POP; } +MVA { return TOK_MVA; } +ASYMP { return TOK_ASYMP; } +"=>" { return TOK_ARROW; } +{FLOAT} { return TOK_FLOAT; } +{INT} { yylval.ival = atoi(yytext); return TOK_INT; } +{ID} { + if ((yylval.id=malloc(yyleng+1)) == NULL) { + fprintf(stderr, "malloc() failed for id*\n"); + exit(1); + } + strncpy(yylval.id, yytext, yyleng); + yylval.id[yyleng] = '\0'; + return TOK_ID; + } +. { return yytext[0]; } + +%% +int yywrap( void ) +{ +return 1; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/scripts/pmva.y Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,271 @@ +/**************************************************************************** + * + * pmva.y + * + * This grammar recognizes the PMVA notation for describing + * queueing network models. This file is part of the queueing toolbox. + * + * Copyright (C) 2011, 2012 Moreno Marzolla + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ****************************************************************************/ + +/* + * PMVA (Purdue Mean Value Analysis program) is described in + * Jeff Brumfield, "PMVA - Purdue Mean Value Analysis Program User's Guide" + * Technical Report CSD-TR-383, april 1981, Purdue University: + * + * http://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1309&context=cstech + * + * This file contains a grammar for PMVA, according to the specification + * above. At the moment, this grammar is only used to implement a parser + * which does absolutely nothing (apart recognizing PMVA models). + * Eventually, this grammar will evolve in a suitable software tool + * for generating an Octave model suitable for analysis with + * the queueing toolbox. + */ +%{ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "pmva.h" + +extern int linenum; +extern FILE *yyin, *yyout; + +#define YYERROR_VERBOSE 1 +%} + +%union{ + int ival; + float fval; + char* id; +}; + +%token <id> TOK_ID +%token <ival> TOK_INT +%token <fval> TOK_FLOAT +%token TOK_CLASSES +%token TOK_SERVERS +%token TOK_ROUTING +%token TOK_FCFS +%token TOK_PS +%token TOK_IS +%token TOK_LCFS +%token TOK_LI +%token TOK_MS +%token TOK_LD +%token TOK_ARROW +%token TOK_NETWORK +%token TOK_END +%token TOK_MVA +%token TOK_ASYMP +%token TOK_POP + +%left ',' +%left TOK_ARROW + +%% /* The grammar follows */ + +input: /* empty */ +| TOK_NETWORK ';' blocks TOK_END ';' solution_block +; + +blocks: /* empty */ +| blocks block +; + +block: TOK_CLASSES class_list ';' +| TOK_SERVERS server_list ';' +| TOK_ROUTING routing_node_list ';' +; + +class_list: /* empty */ +| TOK_ID { push_class($1); } +| class_list ',' TOK_ID { push_class($3); } +; + +server_list: /* empty */ +| server +| server_list ',' server +; + +server: TOK_ID { push_server($1); } queueing_discipline server_type service_times +; + +queueing_discipline: /* empty (assume FCFS) */ +| TOK_FCFS { server_list->queueing_discipline = FCFS; } +| TOK_PS { server_list->queueing_discipline = PS; } +| TOK_IS { server_list->queueing_discipline = IS; printf("m(%d) = -1;\n", n_servers); } +| TOK_LCFS { server_list->queueing_discipline = LCFS; } +; + +server_type: { printf("m(%d) = 1;\n", n_servers); } /* if not specified, assume LI */ +| TOK_LI { server_list->server_type = LI; printf("m(%d) = 1;\n", n_servers); } +| TOK_MS TOK_INT { server_list->server_type = MS; server_list->num_servers = $2; printf("m(%d) = %d;\n", n_servers, $2); } +| TOK_LD { server_list->server_type = LD; printf("m(%d) = 1;\n", n_servers); } +; + +service_times: service_time_spec +| service_times service_time_spec +; + +service_time_spec: class_name visit_ratio service_time +; + +class_name: /* empty */ { if (n_classes > 1) { printf("Class spwcified for server %s must be given for multiclass networks\n", server_list->name); exit(-1); } } +| TOK_ID '=' +; + +visit_ratio: /* empty */ +| '[' TOK_FLOAT ']' +; + +service_time: TOK_FLOAT +| '(' serv_time_list ')' +; + +serv_time_list: TOK_FLOAT +| serv_time_list ',' TOK_FLOAT +; + +routing_node_list: /* empty */ +| nonempty_routing_spec +| routing_node_list ',' nonempty_routing_spec +; + +nonempty_routing_spec: node_list +| nonempty_routing_spec TOK_ARROW node_list +; + +node_list: TOK_ID opt_class_name opt_routing_prob +| node_list TOK_ID opt_class_name opt_routing_prob +; + +opt_class_name: /* empty */ +| '/' TOK_ID +; + +opt_routing_prob: /* empty */ +| '(' TOK_FLOAT ')' +; + +solution_block: /* empty */ +| TOK_ASYMP ';' +| TOK_MVA pop_description ';' +; + +pop_description: TOK_POP '=' TOK_INT +| TOK_POP '=' '(' pop_list ')' +; + +pop_list: TOK_INT +| pop_list ',' TOK_INT +; + +%% + +server_node_t* server_list = 0; +class_node_t* class_list = 0; + +int n_servers = 0; +int n_classes = 0; + +/* + * Push a new server in front of the server list. Return the new head + * of the list (the global variable server_list is also updated to + * point to the newly created object). The caller transfers ownership + * of the pointer name. + */ +server_node_t* push_server( const char* name ) +{ + server_node_t* server = malloc( sizeof(server_node_t) ); + server->id = ++n_servers; + server->name = name; + server->queueing_discipline = FCFS; + server->server_type = LI; + server->num_servers = 1; + server->next = server_list; + server_list = server; + printf("servers{%d} = \"%s\";\n", n_servers, name ); + return server; +} + +class_node_t* push_class( const char* name ) +{ + class_node_t* class = malloc( sizeof(class_node_t) ); + class->id = ++n_classes; + class->name = name; + class->next = class_list; + class_list = class; + printf("classes{%d}=\"%s\";\n", n_classes, name); + return class; +} + +void dump_server_list( void ) +{ + server_node_t* server = server_list; + while ( server ) { + printf("[%d] %s ",server->id, server->name); + + switch ( server->server_type ) { + case LI: printf("LI "); break; + case LD: printf("LD "); break; + case MS: printf("MS %d ", server->num_servers); break; + default: printf("Unrecognized server type %d\n", server->server_type); + exit(-1); + } + + switch ( server->queueing_discipline ) { + case FCFS: printf("FCFS "); break; + case PS: printf("PS "); break; + case LCFS: printf("LCFS "); break; + case IS: printf("IS "); break; + default: printf("Unrecognized queueing discipline %d\n", server->queueing_discipline ); + exit(-1); + } + printf("\n"); + server = server->next; + } +} + +void dump_class_list( void ) +{ + class_node_t* class = class_list; + while( class ) { + printf("[%d] %s\n", class->id, class->name ); + class = class->next; + } +} + +void yyerror(char const *s) +{ + fprintf(stderr, "line %d, %s\n", linenum, s); + /*fprintf(stderr, "%s: (Error) line %d: %s\n", nomefile, linea, s); */ +} + +int main( int argc, char **argv ) +{ + int res; + ++argv, --argc; /* skip over program name */ + if ( argc > 0 ) + yyin = fopen( argv[0], "r" ); + else + yyin = stdin; + + res = yyparse(); + /* dump_server_list(); + dump_class_list(); */ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/scripts/test.pmva Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,15 @@ +network; +classes A, B, C; +classes D, E, F; +servers terminals IS LI 1.0; +servers cpu2 PS MS 2 BATCH=20.0; +servers + terminals IS LI 4.0, + cpu PS LI 0.025, + disk FCFS LI 0.050, + tape FCFS LI 0.150, + cpu2 PS MS 2 BATCH=0.064 INTERACTIVE=(0.4 , 0.4, 0.3), + disk2 FCFS LD ALL=(0.0250, 0.0225, 0.0214, 0.0208); +routing + terminals/FOO => cpu / BAR (0.9) disk / BAZ (0.1) => tape / ID; +end;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/test/Makefile Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,16 @@ +DISTFILES=Makefile fntests.m + +.PHONY: check dist clean + +ALL: + +check: + cd ../inst && octave -q ../test/fntests.m + +dist: + ln $(DISTFILES) ../`cat ../fname`/test/ + +clean: + \rm -f *~ fntests.log + +distclean: clean
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main/queueing/test/fntests.m Fri Feb 03 12:07:15 2012 +0000 @@ -0,0 +1,246 @@ +## Copyright (C) 2005, 2006, 2007 David Bateman +## Modifications Copyright (C) 2009, 2012 Moreno Marzolla +## +## This file is part of the queueing toolbox. It is based on the fntests.m +## script included in GNU Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## <http://www.gnu.org/licenses/>. + +clear all; + +global files_with_no_tests = {}; +global files_with_tests = {}; +global topsrcdir; +global topbuilddir; +global skip_files; + +currdir = canonicalize_file_name ("."); + +if (nargin == 1) + xdir = argv(){1}; +else + xdir = "."; +endif + +srcdir = canonicalize_file_name (xdir); +topsrcdir = canonicalize_file_name (fullfile (xdir, "..")); +topbuilddir = canonicalize_file_name (fullfile (currdir, "..")); + +if (strcmp (currdir, srcdir)) + testdirs = {srcdir}; +else + testdirs = {currdir, srcdir}; +endif + +#src_tree = canonicalize_file_name (fullfile (topsrcdir, "src")); +#liboctave_tree = canonicalize_file_name (fullfile (topsrcdir, "liboctave")); +script_tree = canonicalize_file_name (fullfile (topsrcdir, "inst")); +#local_script_tree = canonicalize_file_name (fullfile (currdir, "../scripts")); + +fundirs = {script_tree}; +skip_files = { "lee_et_al_98.m" }; + +# if (! strcmp (currdir, srcdir)) +# fundirs{end+1} = local_script_tree; +# endif + +function print_test_file_name (nm) + filler = repmat (".", 1, 55-length (nm)); + printf (" %s %s", nm, filler); +endfunction + +function print_pass_fail (n, p) + if (n > 0) + printf (" PASS %4d/%-4d", p, n); + nfail = n - p; + if (nfail > 0) + printf (" FAIL %d", nfail); + endif + endif + printf ("\n"); +endfunction + +function y = hastests (f) + fid = fopen (f); + str = fscanf (fid, "%s"); + fclose (fid); + y = (findstr (str, "%!test") || findstr (str, "%!assert") + || findstr (str, "%!error") || findstr (str, "%!warning")); +endfunction + +function r = skip(nm) + global skip_files; + r = 0; + for sk=skip_files + if ( strcmp(nm,skip_files) ) + r = 1; + break; + endif + endfor +endfunction + +function [dp, dn, dxf, dsk] = run_test_dir (fid, d); + global files_with_tests; + global files_with_no_tests; + lst = dir (d); + dp = dn = dxf = dsk = 0; + for i = 1:length (lst) + nm = lst(i).name; + if (length (nm) > 5 && strcmp (nm(1:5), "test_") + && strcmp (nm((end-1):end), ".m")) + p = n = 0; + ffnm = fullfile (d, nm); + if (hastests (ffnm)) + print_test_file_name (nm); + [p, n, xf, sk] = test (nm(1:(end-2)), "quiet", fid); + print_pass_fail (n, p); + files_with_tests(end+1) = ffnm; + else + files_with_no_tests(end+1) = ffnm; + endif + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endif + endfor +endfunction + +function [dp, dn, dxf, dsk] = run_test_script (fid, d); + global files_with_tests; + global files_with_no_tests; + global topsrcdir; + global topbuilddir; + lst = dir (d); + dp = dn = dxf = dsk = 0; + for i = 1:length (lst) + nm = lst(i).name; + if (lst(i).isdir && ! strcmp (nm, ".") && ! strcmp (nm, "..") + && ! strcmp (nm, "CVS")) + [p, n, xf, sk] = run_test_script (fid, [d, "/", nm]); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endif + endfor + for i = 1:length (lst) + nm = lst(i).name; + if (((length (nm) > 3 && strcmp (nm((end-2):end), ".cc")) + || (length (nm) > 2 && strcmp (nm((end-1):end), ".m"))) + && !skip(nm)) + f = fullfile (d, nm); + p = n = xf = 0; + ## Only run if it contains %!test, %!assert %!error or %!warning + if (hastests (f)) + tmp = strrep (f, [topsrcdir, "/"], ""); + tmp = strrep (tmp, [topbuilddir, "/"], "../"); + print_test_file_name (tmp); + [p, n, xf, sk] = test (f, "quiet", fid); + print_pass_fail (n, p); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + files_with_tests(end+1) = f; + else + files_with_no_tests(end+1) = f; + endif + endif + endfor + ## printf("%s%s -> passes %d of %d tests\n", ident, d, dp, dn); +endfunction + +function printf_assert (varargin) + global _assert_printf; + _assert_printf = cat (2, _assert_printf, sprintf (varargin{:})); +endfunction + +function ret = prog_output_assert (str) + global _assert_printf; + if (isempty (_assert_printf)) + ret = isempty (str); + elseif (_assert_printf(end) == "\n") + ret = strcmp (_assert_printf(1:(end-1)), str); + else + ret = strcmp (_assert_printf, str); + endif + _assert_printf = ""; +endfunction + +pso = page_screen_output (); +warn_state = warning ("query", "quiet"); +warning ("on", "quiet"); +try + page_screen_output (0); + fid = fopen ("fntests.log", "wt"); + if (fid < 0) + error ("could not open fntests.log for writing"); + endif + test ("", "explain", fid); + dp = dn = dxf = dsk = 0; + printf ("\nIntegrated test scripts:\n\n"); + for i = 1:length (fundirs) + [p, n, xf, sk] = run_test_script (fid, fundirs{i}); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endfor + printf ("\nFixed test scripts:\n\n"); + for i = 1:length (testdirs) + [p, n, xf, sk] = run_test_dir (fid, testdirs{i}); + dp += p; + dn += n; + dxf += xf; + dsk += sk; + endfor + printf ("\nSummary:\n\n PASS %6d\n", dp); + nfail = dn - dp; + printf (" FAIL %6d\n", nfail); + if (dxf > 0) + if (dxf > 1) + t1 = "were"; + t2 = "failures"; + else + t1 = "was"; + t2 = "failure"; + endif + printf ("\nThere %s %d expected %s (see fntests.log for details).\n", + t1, dxf, t2); + printf ("\nExpected failures are known bugs. Please help improve\n"); + printf ("the queueing toolbox by contributing fixes for them.\n"); + endif + if (dsk > 0) + printf ("\nThere were %d skipped tests (see fntest.log for details).\n", dsk); + printf ("Skipped tests are features that are disabled in this version\n"); + printf ("of the queueing toolbox\n"); + endif + + n_files_with_no_tests = length (files_with_no_tests); + n_files = n_files_with_no_tests + length (files_with_tests); + printf ("\n%d (of %d) files have no tests. Please help improve the queueing toolbox by\n", + n_files_with_no_tests, n_files); + printf ("contributing tests for these files (see the list in the file fntests.log).\n"); + fprintf (fid, "\nFiles with no tests:\n\n%s", + list_in_columns (files_with_no_tests, 80)); + fclose (fid); + page_screen_output (pso); + warning (warn_state.state, "quiet"); +catch + page_screen_output (pso); + warning (warn_state.state, "quiet"); + disp (lasterr ()); +end_try_catch