diff --git a/LICENSE b/LICENSE index 8ea588b718a3ac4a024f3054043ec84b21d40c8b..f7cf088fccd26ec0b14ef565092720a3ccdefbbd 100644 --- a/LICENSE +++ b/LICENSE @@ -1 +1,677 @@ -We need a license here \ No newline at end of file + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://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. + + WiseMove: A Framework for Safe Deep Reinforcement Learning + for Autonomous Driving + Copyright (C) 2018 Jaeyoung Lee, Aravind Balakrishnan, Ashish Gaurav, + and Sean Sedwards + + 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 <https://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: + + WiseMove Copyright (C) 2018 Jaeyoung Lee, Aravind Balakrishnan, + Ashish Gaurav and Sean Sedwards + 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 +<https://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 +<https://www.gnu.org/licenses/why-not-lgpl.html>. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index cb266844c7451b37886c1f4b5878ed486b277173..0000000000000000000000000000000000000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -We need some helpful information here \ No newline at end of file diff --git a/README.rst b/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..6c1d197d73951697a330b996dcdcb028962f087a --- /dev/null +++ b/README.rst @@ -0,0 +1,48 @@ +WiseMove is safe reinforcement learning framework that combines hierarchical reinforcement learning and model-checking using temporal logic constraints. + +Requirements +============ + +* Python 3.6 +* `requirements.txt <../requirements.txt>`_ for package list. + + +Installation +============ + +* Run the install script: :code:`scripts/install.sh` + +Documentation +============= + +* For documentation, we use *Sphinx* + * If `install.sh` was run, use :code:`scripts/generate_doc.sh launch` to view documentation or open `index.html <./documentation/index.html>`_ . + * If not, use :code:`scripts/generate_doc.sh build` to generate documentation first. + +Replicate Results +================= +These are the minimum steps required to replicate the results for simple_intersection environment. For a detailed user guide, it is recommended to view the documentation. + +* Run `scripts/install.sh` +* Low-level policies: + * To train all low-level policies from scratch: `python low_level_policy_main.py --train` + * To train a single low-level, for example wait: `python low_level_policy_main.py --option=wait --train` + * To test these trained low-level policies: `python low_level_policy_main.py --test --saved_policy_in_root` + * To test one of these trained low-level policies, for example wait: `python low_level_policy_main.py --option=wait --test --saved_policy_in_root` +* High-level policy: + * To train high-level policy from scratch using the given low-level policies: `python high_level_policy_main.py --train` + * To evaluate this trained high-level policy: `python high_level_policy_main.py --evaluate --saved_policy_in_root` +* To run MCTS using the high-level policy: `python mcts.py` + +Coding Standards +================ + +We follow PEP8 style guidelines for coding and PEP257 for documentation. +It is not necessary to keep these in mind while coding, but before +submitting a pull request, do these two steps for each python file you +have modified. + +1. :code:`yapf -i YOUR_MODIFIED_FILE.py` +2. :code:`docformatter --in-place YOUR_MODIFIED_FILE.py` + +:code:`yapf` formats the code and :code:`docformatter` formats the docstrings. \ No newline at end of file diff --git a/backends/__init__.py b/backends/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7293f55df582d9ad8351f269618069f20a6a39b6 --- /dev/null +++ b/backends/__init__.py @@ -0,0 +1,5 @@ +from .manual_policy import ManualPolicy +from .mcts_learner import MCTSLearner +from .rl_controller import RLController +from .kerasrl_learner import DDPGLearner, DQNLearner +from .online_mcts_controller import OnlineMCTSController \ No newline at end of file diff --git a/backends/baselines_learner.py b/backends/baselines_learner.py new file mode 100644 index 0000000000000000000000000000000000000000..1e696588e52d3a1081e8d35f1bd11f26099ec88e --- /dev/null +++ b/backends/baselines_learner.py @@ -0,0 +1,120 @@ +from .learner_base import LearnerBase + +# TODO: make sure that the package for PPO2 is installed. +from stable_baselines import PPO2 +from stable_baselines.common.vec_env import DummyVecEnv +from stable_baselines.common.policies import MlpPolicy + +import numpy as np + + +class PPO2Agent(LearnerBase): + def __init__(self, + input_shape, + nb_actions, + env, + policy=None, + tensorboard=False, + log_path="./logs", + **kwargs): + """The constructor which sets the properties of the class. + + Args: + input_shape: Shape of observation space, e.g (10,); + nb_actions: number of values in action space; + env: env on which the agent learns + policy: stable_baselines Policy object. default is MlpPolicy + tensorboard: whether to integrate tensorboard or not + log_path="./logs", + **kwargs: other optional key-value arguments with defaults defined in property_defaults + """ + super(PPO2Agent, self).__init__(input_shape, nb_actions, **kwargs) + + if policy is None: + policy = self.get_default_policy() + + self.log_path = log_path + + self.env = DummyVecEnv([lambda: env]) #PPO2 requried a vectorized environment for parallel training + self.agent_model = self.create_agent(policy, tensorboard) + + def get_default_policy(self): + """Creates the default policy. + + Returns: stable_baselines Policy object. default is MlpPolicy + """ + return MlpPolicy + + def create_agent(self, policy, tensorboard): + """Creates a PPO agent + + Returns: + stable_baselines PPO2 object + """ + if tensorboard: + return PPO2(policy, self.env, verbose=1, tensorboard_log=self.log_path) + else: + return PPO2(policy, self.env, verbose=1) + + def fit(self, + env=None, + nb_steps=1000000, + visualize=False, + nb_max_episode_steps=200): + + # PPO2 callback is only called each episode (not step) so cannot render whole episode + # To render each step, add self.env.render() in at Runner class method run() in stable_baselines ppo2.py + callback = self.__render_env_while_learning if visualize else None + self.agent_model.learn(total_timesteps=nb_steps, callback=callback) + + @staticmethod + def __render_env_while_learning(_locals, _globals): + _locals['self'].env.render() + + def save_weights(self, file_name="test_weights.h5f", overwrite=True): + self.agent_model.save(file_name) + + def test_model(self, + env=None, + nb_episodes=50, + visualize=True, + nb_max_episode_steps=200): + + episode_rewards = [0.0] + obs = self.env.reset() + current_episode = 1 + current_step = 0 + while current_episode <= nb_episodes: + # _states are only useful when using LSTM policies + action, _states = self.agent_model.predict(obs) + + # here, action, rewards and dones are arrays + # because we are using vectorized env + obs, rewards, dones, info = self.env.step(action) + current_step += 1 + + if visualize: + self.env.render() + + # Stats + episode_rewards[-1] += rewards[0] + if dones[0] or current_step > nb_max_episode_steps: + obs = self.env.reset() + print ("Episode ", current_episode, "reward: ", episode_rewards[-1]) + episode_rewards.append(0.0) + current_episode += 1 + current_step = 0 + + # Compute mean reward for the last 100 episodes + mean_100ep_reward = round(np.mean(episode_rewards[-100:]), 1) + print("Mean reward over last 100 episodes:", mean_100ep_reward) + + def load_weights(self, file_name="test_weights.h5f"): + self.agent_model = PPO2.load(file_name) + + def forward(self, observation): + return self.agent_model.predict(observation) + + def set_environment(self, env): + self.env = DummyVecEnv([lambda: env]) + self.agent_model.set_env(self.env) diff --git a/backends/controller_base.py b/backends/controller_base.py new file mode 100644 index 0000000000000000000000000000000000000000..56508c045702bafc51c4755c52ef543566ad5e9b --- /dev/null +++ b/backends/controller_base.py @@ -0,0 +1,78 @@ +from .policy_base import PolicyBase + + +class ControllerBase(PolicyBase): + """Abstract class for controllers.""" + + def __init__(self, env, low_level_policies, start_node_alias): + self.env = env + self.low_level_policies = low_level_policies + + # TODO: Move an intermediate class so that base class can be clean + self.current_node = self.low_level_policies[start_node_alias] + self.node_terminal_state_reached = False + self.controller_args_defaults = {} + + def set_controller_args(self, **kwargs): + for (prop, default) in self.controller_args_defaults.items(): + setattr(self, prop, kwargs.get(prop, default)) + + def can_transition(self): + """Returns boolean signifying whether we can transition. To be + implemented in subclass. + """ + + raise NotImplemented(self.__class__.__name__ + \ + "can_transition is not implemented.") + + def do_transition(self, observation): + """Do a transition, assuming we can transition. To be + implemented in subclass. + + Args: + observation: final observation from episodic step + """ + + raise NotImplemented(self.__class__.__name__ + \ + "do_transition is not implemented.") + + def set_current_node(self, node_alias): + """Sets the current node which is being executed + + Args: + node: node alias of the node to be set + """ + raise NotImplemented(self.__class__.__name__ + \ + "set_current_node is not implemented.") + + # TODO: Looks generic. Move to an intermediate class/highlevel manager so that base class can be clean + ''' Executes the current node until node termination condition is reached + + Returns state at end of node execution, total reward, epsiode_termination_flag, info + ''' + def step_current_node(self, visualize_low_level_steps=False): + total_reward = 0 + self.node_terminal_state_reached = False + while not self.node_terminal_state_reached: + observation, reward, terminal, info = self.low_level_step_current_node() + if visualize_low_level_steps: + self.env.render() + total_reward += reward + + total_reward += self.current_node.high_level_extra_reward + + # TODO for info + return observation, total_reward, self.env.termination_condition, info + + # TODO: Looks generic. Move to an intermediate class/highlevel manager so that base class can be clean + ''' Executes one step of current node. Sets node_terminal_state_reached flag if node termination condition + has been reached. + + Returns state after one step, step reward, episode_termination_flag, info + ''' + def low_level_step_current_node(self): + + u_ego = self.current_node.low_level_policy(self.current_node.get_reduced_features_tuple()) + feature, R, terminal, info = self.current_node.step(u_ego) + self.node_terminal_state_reached = terminal + return self.env.get_features_tuple(), R, self.env.termination_condition, info diff --git a/backends/kerasrl_learner.py b/backends/kerasrl_learner.py new file mode 100644 index 0000000000000000000000000000000000000000..a6b2d150c86ad61414e5f135ab18e049057bb3e5 --- /dev/null +++ b/backends/kerasrl_learner.py @@ -0,0 +1,439 @@ +from .learner_base import LearnerBase + +from keras.models import Sequential, Model +from keras.layers import Dense, Activation, Flatten, Input, Concatenate +from keras.optimizers import Adam +from keras.callbacks import TensorBoard + +from rl.agents import DDPGAgent, DQNAgent +from rl.memory import SequentialMemory +from rl.random import OrnsteinUhlenbeckProcess +from rl.policy import BoltzmannQPolicy, MaxBoltzmannQPolicy + +from rl.callbacks import ModelIntervalCheckpoint + +import numpy as np + + +class DDPGLearner(LearnerBase): + def __init__(self, + input_shape=(48, ), + nb_actions=2, + actor=None, + critic=None, + critic_action_input=None, + memory=None, + random_process=None, + **kwargs): + """The constructor which sets the properties of the class. + + Args: + input_shape: Shape of observation space, e.g (10,); + nb_actions: number of values in action space; + actor: Keras Model of actor which takes observation as input and outputs actions. Uses default if not given + critic: Keras Model of critic which takes concatenation of observation and action and outputs a single + value. Uses default if not given + critic_action_input: Keras Input which was used in creating action input of the critic model. + Uses default critic and action_input if not specified + memory: KerasRL Memory. Uses default SequentialMemory if not given + random_process: KerasRL random process. Uses default OrnsteinUhlenbeckProcess if not given + **kwargs: other optional key-value arguments with defaults defined in property_defaults + """ + super(DDPGLearner, self).__init__(input_shape, nb_actions, **kwargs) + property_defaults = { + "mem_size": 100000, # size of memory + "mem_window_length": 1, # window length of memory + "oup_theta": 0.15, # OrnsteinUhlenbeckProcess theta + "oup_mu": 0, # OrnsteinUhlenbeckProcess mu + "oup_sigma": 1, # OrnsteinUhlenbeckProcess sigma + "oup_sigma_min": 0.5, # OrnsteinUhlenbeckProcess sigma min + "oup_annealing_steps": 500000, # OrnsteinUhlenbeckProcess n-step annealing + "nb_steps_warmup_critic": 100, # steps for critic to warmup + "nb_steps_warmup_actor": 100, # steps for actor to warmup + "target_model_update": 1e-3 # target model update frequency + } + + for (prop, default) in property_defaults.items(): + setattr(self, prop, kwargs.get(prop, default)) + + if actor is None: + actor = self.get_default_actor_model() + if critic is None or critic_action_input is None: + critic, critic_action_input = self.get_default_critic_model() + if memory is None: + memory = self.get_default_memory() + if random_process is None: + random_process = self.get_default_randomprocess() + + #TODO: Add output scaling + self.agent_model = self.create_agent( + actor, critic, critic_action_input, memory, random_process) + + def get_default_actor_model(self): + """Creates the default actor model. + + Returns: Keras Model object of actor + """ + actor = Sequential() + actor.add(Flatten(input_shape=(1, ) + self.input_shape)) + actor.add(Dense(64, use_bias=False)) + actor.add(Activation('relu')) + actor.add(Dense(64, use_bias=False)) + actor.add(Activation('relu')) + actor.add(Dense(self.nb_actions, use_bias=True)) + actor.add(Activation('tanh')) + + # print(actor.summary()) + + return actor + + def get_default_critic_model(self): + """Creates the default critic model. + + Returns: Keras Model object of critic + """ + action_input = Input(shape=(self.nb_actions, ), name='action_input') + observation_input = Input( + shape=(1, ) + self.input_shape, name='observation_input') + flattened_observation = Flatten()(observation_input) + x = Concatenate()([action_input, flattened_observation]) + x = Dense(64, use_bias=False)(x) + x = Activation('relu')(x) + x = Dense(64, use_bias=False)(x) + x = Activation('relu')(x) + x = Dense(64, use_bias=False)(x) + x = Activation('relu')(x) + x = Dense(1, use_bias=True)(x) + #x = Activation('linear')(x) + critic = Model(inputs=[action_input, observation_input], outputs=x) + # print(critic.summary()) + + return critic, action_input + + def get_default_randomprocess(self): + """Creates the default random process model. + + Returns: KerasRL OrnsteinUhlenbeckProcess object + """ + random_process = OrnsteinUhlenbeckProcess( + size=self.nb_actions, + theta=self.oup_theta, + mu=self.oup_mu, + sigma=self.oup_sigma, + sigma_min=self.oup_sigma_min, + n_steps_annealing=self.oup_annealing_steps) + return random_process + + def get_default_memory(self): + """Creates the default memory model. + + Returns: KerasRL SequentialMemory object + """ + memory = SequentialMemory( + limit=self.mem_size, window_length=self.mem_window_length) + return memory + + def create_agent(self, actor, critic, critic_action_input, memory, + random_process): + """Creates a KerasRL DDPGAgent with given components. + + Args: + actor: Keras Model of actor which takes observation as input and outputs actions. + critic: Keras Model of critic that takes concatenation of observation and action and outputs a single value. + critic_action_input: Keras Input which was used in creating action input of the critic model. + memory: KerasRL Memory. + random_process: KerasRL random process. + + Returns: + KerasRL DDPGAgent object + """ + agent = DDPGAgent( + nb_actions=self.nb_actions, + actor=actor, + critic=critic, + critic_action_input=critic_action_input, + memory=memory, + nb_steps_warmup_critic=self.nb_steps_warmup_critic, + nb_steps_warmup_actor=self.nb_steps_warmup_actor, + random_process=random_process, + gamma=self.gamma, + target_model_update=1e-3) + + # TODO: give params like lr_actor and lr_critic to set different lr of Actor and Critic. + agent.compile([Adam(lr=self.lr*1e-2, clipnorm=1.), Adam(lr=self.lr, clipnorm=1.)], metrics=['mae']) + + return agent + + def train(self, + env, + nb_steps=1000000, + visualize=False, + verbose=1, + log_interval=10000, + nb_max_episode_steps=200, + model_checkpoints=False, + checkpoint_interval=100000, + tensorboard=False): + + callbacks = [] + if model_checkpoints: + callbacks += [ModelIntervalCheckpoint('./checkpoints/checkpoint_weights.h5f', interval=checkpoint_interval)] + if tensorboard: + callbacks += [TensorBoard(log_dir='./logs')] + + self.agent_model.fit( + env, + nb_steps=nb_steps, + visualize=visualize, + verbose=verbose, + log_interval=log_interval, + nb_max_episode_steps=nb_max_episode_steps, + callbacks=callbacks) + + def save_model(self, file_name="test_weights.h5f", overwrite=True): + self.agent_model.save_weights(file_name, overwrite=True) + + def test_model(self, + env, + nb_episodes=50, + visualize=True, + nb_max_episode_steps=200): + self.agent_model.test( + env, + nb_episodes=nb_episodes, + visualize=visualize, + nb_max_episode_steps=nb_max_episode_steps) + + def load_model(self, file_name="test_weights.h5f"): + self.agent_model.load_weights(file_name) + + def predict(self, observation): + return self.agent_model.forward(observation) + + +class DQNLearner(LearnerBase): + def __init__(self, + input_shape=(48, ), + nb_actions=5, + low_level_policies=None, + model=None, + policy=None, + memory=None, + **kwargs): + """The constructor which sets the properties of the class. + + Args: + input_shape: Shape of observation space, e.g (10,); + nb_actions: number of values in action space; + model: Keras Model of actor which takes observation as input and outputs actions. Uses default if not given + policy: KerasRL Policy. Uses default SequentialMemory if not given + memory: KerasRL Memory. Uses default BoltzmannQPolicy if not given + **kwargs: other optional key-value arguments with defaults defined in property_defaults + """ + super(DQNLearner, self).__init__(input_shape, nb_actions, **kwargs) + property_defaults = { + "mem_size": 100000, # size of memory + "mem_window_length": 1, # window length of memory + "target_model_update": 1e-3, # target model update frequency + "nb_steps_warmup": 100, # steps for model to warmup + } + + for (prop, default) in property_defaults.items(): + setattr(self, prop, kwargs.get(prop, default)) + + if model is None: + model = self.get_default_model() + if policy is None: + policy = self.get_default_policy() + if memory is None: + memory = self.get_default_memory() + + self.low_level_policies = low_level_policies + + self.agent_model = self.create_agent(model, policy, memory) + + def get_default_model(self): + """Creates the default model. + + Returns: Keras Model object of actor + """ + model = Sequential() + model.add(Flatten(input_shape=(1, ) + self.input_shape)) + model.add(Dense(32)) + model.add(Activation('relu')) + model.add(Dense(32)) + model.add(Activation('relu')) + model.add(Dense(self.nb_actions)) + model.add(Activation('linear')) + # print(model.summary()) + + return model + + def get_default_policy(self): + return MaxBoltzmannQPolicy(eps=0.3) + + def get_default_memory(self): + """Creates the default memory model. + + Returns: KerasRL SequentialMemory object + """ + memory = SequentialMemory( + limit=self.mem_size, window_length=self.mem_window_length) + return memory + + def create_agent(self, model, policy, memory): + """Creates a KerasRL DDPGAgent with given components. + + Args: + model: Keras Model of model which takes observation as input and outputs discrete actions. + memory: KerasRL Memory. + + Returns: + KerasRL DQN object + """ + agent = DQNAgentOverOptions(model=model, low_level_policies=self.low_level_policies, + nb_actions=self.nb_actions, memory=memory, + nb_steps_warmup=self.nb_steps_warmup, target_model_update=self.target_model_update, + policy=policy, enable_dueling_network=True) + + + agent.compile(Adam(lr=self.lr), metrics=['mae']) + + return agent + + def train(self, + env, + nb_steps=1000000, + visualize=False, + nb_max_episode_steps=200, + tensorboard=False, + model_checkpoints=False, + checkpoint_interval=10000): + + callbacks = [] + if model_checkpoints: + callbacks += [ModelIntervalCheckpoint('./checkpoints/checkpoint_weights.h5f', interval=checkpoint_interval)] + if tensorboard: + callbacks += [TensorBoard(log_dir='./logs')] + + self.agent_model.fit( + env, + nb_steps=nb_steps, + visualize=visualize, + verbose=1, + nb_max_episode_steps=nb_max_episode_steps, + callbacks=callbacks) + + def save_model(self, file_name="test_weights.h5f", overwrite=True): + self.agent_model.save_weights(file_name, overwrite=True) + + # TODO: very environment specific. Make it general + def test_model(self, + env, + nb_episodes=5, + visualize=True, + nb_max_episode_steps=400, + success_reward_threshold = 100): + + print("Testing for {} episodes".format(nb_episodes)) + success_count = 0 + termination_reason_counter = {} + for n in range(nb_episodes): + env.reset() + terminal = False + step = 0 + episode_reward = 0 + while not terminal and step <= nb_max_episode_steps: + if visualize: + env.render() + features, R, terminal, info = env.execute_controller_policy() + step += 1 + episode_reward += R + if terminal: + if 'episode_termination_reason' in info: + termination_reason = info['episode_termination_reason'] + if termination_reason in termination_reason_counter: + termination_reason_counter[termination_reason] += 1 + else: + termination_reason_counter[termination_reason] = 1 + env.reset() + if episode_reward >= success_reward_threshold: + success_count += 1 + print("Episode {}: steps:{}, reward:{}".format(n+1, step, episode_reward)) + + print ("\nPolicy succeeded {} times!".format(success_count)) + print ("Failures due to:") + print (termination_reason_counter) + + return [success_count,termination_reason_counter] + + def load_model(self, file_name="test_weights.h5f"): + self.agent_model.load_weights(file_name) + + def predict(self, observation): + return self.agent_model.forward(observation) + + def get_q_value(self, observation, action): + return self.agent_model.get_modified_q_values(observation)[action] + + def get_q_value_using_option_alias(self, observation, option_alias): + action_num = self.agent_model.low_level_policy_aliases.index(option_alias) + return self.agent_model.get_modified_q_values(observation)[action_num] + + def get_softq_value_using_option_alias(self, observation, option_alias): + action_num = self.agent_model.low_level_policy_aliases.index(option_alias) + q_values = self.agent_model.get_modified_q_values(observation) + max_q_value = np.abs(np.max(q_values)) + q_values = [np.exp(q_value/max_q_value) for q_value in q_values] + relevant = q_values[action_num]/np.sum(q_values) + return relevant + +class DQNAgentOverOptions(DQNAgent): + + def __init__(self, model, low_level_policies, policy=None, test_policy=None, enable_double_dqn=True, enable_dueling_network=False, + dueling_type='avg', *args, **kwargs): + super(DQNAgentOverOptions, self).__init__(model, policy, test_policy, enable_double_dqn, enable_dueling_network, + dueling_type, *args, **kwargs) + + self.low_level_policies = low_level_policies + if low_level_policies is not None: + self.low_level_policy_aliases = list(self.low_level_policies.keys()) + + def __get_invalid_node_indices(self): + """Returns a list of option indices that are invalid according to initiation conditions. + """ + invalid_node_indices = list() + for index, option_alias in enumerate(self.low_level_policy_aliases): + self.low_level_policies[option_alias].reset_maneuver() + if not self.low_level_policies[option_alias].initiation_condition: + invalid_node_indices.append(index) + + return invalid_node_indices + + def forward(self, observation): + q_values = self.get_modified_q_values(observation) + + if self.training: + action = self.policy.select_action(q_values=q_values) + else: + action = self.test_policy.select_action(q_values=q_values) + + # Book-keeping. + self.recent_observation = observation + self.recent_action = action + + return action + + def get_modified_q_values(self, observation): + state = self.memory.get_recent_state(observation) + q_values = self.compute_q_values(state) + + if self.low_level_policies is not None: + invalid_node_indices = self.__get_invalid_node_indices() + + for node_index in invalid_node_indices: + q_values[node_index] = -np.inf + + return q_values + + diff --git a/backends/learner_base.py b/backends/learner_base.py new file mode 100644 index 0000000000000000000000000000000000000000..50c08cfe7b464077cd6de404854a2b05110dbce0 --- /dev/null +++ b/backends/learner_base.py @@ -0,0 +1,80 @@ +from.policy_base import PolicyBase +import numpy as np + + +class LearnerBase(PolicyBase): + """The abstract class from which each learning policy backend is defined + and inherited.""" + + def __init__(self, input_shape=(10, ), nb_actions=2, **kwargs): + """The constructor which sets the properties of the class. + + Args: + input_shape: Shape of observation space, e.g (10,); + nb_actions: number of values in action space; + **kwargs: other optional key-value arguments with defaults defined in property_defaults + """ + self.input_shape = input_shape + self.nb_actions = nb_actions + + property_defaults = {"lr": 0.001, "gamma": 0.99} + + for (prop, default) in property_defaults.items(): + setattr(self, prop, kwargs.get(prop, default)) + + def train(self, + env, + nb_steps=50000, + visualize=False, + nb_max_episode_steps=200): + """Train the learning agent on the environment. + + Args: + env: the environment instance. Should contain step() and reset() methods and optionally render() + nb_steps: the total number of steps to train + visualize: If True, visualizes the training. Works only if render() is present in env + nb_max_episode_steps: Maximum number of steps per episode + """ + return # do nothing unless specified in the subclass + + def save_model(self, file_name, overwrite=True): + """Save the weights of the agent. To be used after learning. + + Args: + file_name: filename to be used when saving + overwrite: If True, overwrites existing file + """ + return # do nothing unless specified in the subclass + + def load_model(self, file_name): + """Load the weights of an agent. + + Args: + file_name: filename to be used when loading + """ + return # do nothing unless specified in the subclass + + def test_model(self, + env, + nb_episodes=5, + visualize=True, + nb_max_episode_steps=200): + """Test the agent on the environment. + + Args: + env: the environment instance. Should contain step(), reset() and optionally, render() + nb_episodes: Number of episodes to run + visualize: If True, visualizes the test. Works only if render() is present in env + nb_max_episode_steps: Maximum number of steps per episode + """ + return # do nothing unless specified in the subclass + + def predict(self, observation): + """Perform a forward pass and return next action by agent based on + current observation. + + Args: + observation: the current observation. Shape should be same as self.input_shape + Returns: The action taken by agent depending on given observation + """ + return # do nothing unless specified in the subclass diff --git a/backends/manual_policy.py b/backends/manual_policy.py new file mode 100644 index 0000000000000000000000000000000000000000..236eb1271ad3543a8a79ba1e5594f801244e0865 --- /dev/null +++ b/backends/manual_policy.py @@ -0,0 +1,53 @@ +from .controller_base import ControllerBase + +class ManualPolicy(ControllerBase): + """Manual policy execution using nodes and edges.""" + + def __init__(self, env, low_level_policies, transition_adj, start_node_alias): + """Constructor for manual policy execution. + + Args: + env: env instance + low_level_policies: low level policies dictionary + transition_adj: adjacent edges dictionary that contains transitions + start_node: starting node + """ + + super(ManualPolicy, self).__init__(env, low_level_policies, start_node_alias) + self.adj = transition_adj + + def _transition(self): + """Check if the current node's termination condition is met and if + it is possible to transition to another node, i.e. its initiation + condition is met. This is an internal function. + + Returns the new node if a transition can happen, None otherwise + """ + + new_node = None + if self.low_level_policies[self.current_node].termination_condition: + for next_node in self.adj[self.current_node]: + if self.low_level_policies[next_node].initiation_condition: + new_node = next_node + break # change current_node to the highest priority next node + + return new_node + + def can_transition(self): + """Check if we can transition. + + Returns True if we can, false if we cannot. + """ + + return self._transition() is not None + + def do_transition(self, observation): + """Do a singular transition using the specified edges. + + Args: + observation: final observation from episodic step (not used) + """ + + new_node = self._transition() + if new_node is not None: + self.current_node = new_node \ No newline at end of file diff --git a/backends/mcts_learner.py b/backends/mcts_learner.py new file mode 100644 index 0000000000000000000000000000000000000000..6da52d788f0db567b517ca83553db84a36891216 --- /dev/null +++ b/backends/mcts_learner.py @@ -0,0 +1,371 @@ +from .controller_base import ControllerBase +import numpy as np +import pickle + +class MCTSLearner(ControllerBase): + """Monte Carlo Tree Search implementation using the UCB1 and + progressive widening approach as explained in Paxton et al (2017). + """ + + _ucb_vals = set() + + def __init__(self, env, low_level_policies, + start_node_alias, max_depth=10): + """Constructor for MCTSLearner. + + Args: + env: env instance + low_level_policies: low level policies dictionary + start_node: starting node + predictor: P(s, o) learner class; forward pass should + return the entire value from state s and option o + max_depth: max depth of the MCTS tree; default 10 levels + """ + + super(MCTSLearner, self).__init__(env, low_level_policies, start_node_alias) + + self.controller_args_defaults = { + "predictor": None #P(s, o) learner class; forward pass should return the entire value from state s and option o + } + self.max_depth = max_depth + #: store current node alias + self.curr_node_alias = start_node_alias + #: store current node's id + self.curr_node_num = 0 + #: when a new node is created, it has this id; + # afterwards this number is updated + self.new_node_num = 0 + #: visitation count of discrete observations + self.N = {} + #: visitation count of discrete observation with option + self.M = {} + #: total reward from given discrete observation with option + self.TR = {} + #: node properties + self.nodes = {} + #: adjacency list + self.adj = {} + # populate root node + root_node_num, root_node_info = self._create_node(self.curr_node_alias) + self.nodes[root_node_num] = root_node_info + self.adj[root_node_num] = set() # no children + + def save_model(self, file_name="mcts.pickle"): + to_backup = {'N': self.N, 'M': self.M, 'TR': self.TR, 'nodes': self.nodes, + 'adj': self.adj, 'new_node_num': self.new_node_num} + with open(file_name, 'wb') as handle: + pickle.dump(to_backup, handle, protocol=pickle.HIGHEST_PROTOCOL) + + def load_model(self, file_name='mcts.pickle'): + with open(file_name, 'rb') as handle: + to_restore = pickle.load(handle) + self.N = to_restore['N'] + self.M = to_restore['M'] + self.TR = to_restore['TR'] + self.nodes = to_restore['nodes'] + self.adj = to_restore['adj'] + self.new_node_num = to_restore['new_node_num'] + + def _create_node(self, low_level_policy): + """Create the node associated with curr_node_num, using the + given low level policy. + + Args: + low_level_policy: the option's alias + + Returns new node id, and dict with all the node properties of + the created node. + """ + + # print('Creating new node %d:%s' % (self.new_node_num, low_level_policy)) + created_node_num = self.new_node_num + self.new_node_num += 1 + return created_node_num, {"policy": low_level_policy} + + def _to_discrete(self, observation): + """Converts observation to a discrete observation tuple. Also + append (a) whether we are following a vehicle, and (b) whether + there is a vehicle in the opposite lane in the approximately + the same x position. These values will be useful for Follow + and ChangeLane maneuvers. + + Args: + observation: observation tuple from the environment + + Returns the discrete observation + """ + dis_observation = '' + for item in observation[12:20]: + if type(item)==bool: + dis_observation += '1' if item is True else '0' + if type(item)==int and item in [0, 1]: + dis_observation += str(item) + + env = self.current_node.env + + # Are we following a vehicle? + target_veh_i, V2V_dist = env.get_V2V_distance() + if target_veh_i is not None and V2V_dist <= 30: + dis_observation += '1' + else: + dis_observation += '0' + + # Is there a vehicle in the opposite lane in approximately the + # same x position? + delta_x = 15 + ego = env.vehs[0] + possible_collision = '0' + for veh in env.vehs[1:]: + abs_delta_x = abs(ego.x - veh.x) + opp_lane = ego.APs['lane'] != veh.APs['lane'] + is_horizontal = veh.APs['on_route'] + if abs_delta_x <= delta_x and opp_lane and is_horizontal: + possible_collision = '1' + break + dis_observation += possible_collision + + return dis_observation + + def _get_visitation_count(self, observation, option=None): + """Finds the visitation count of the discrete form of the observation. + If discrete observation not found, then inserted into self.N with + value 0. Auto converts the observation into discrete form. If option + is not None, then this uses self.M instead of self.N + + Args: + observation: observation tuple from the environment + option: option alias + + Returns N(discrete form of the observation) or N(observation, option) + depending on usage + """ + + dis_observation = self._to_discrete(observation) + if option is None: + if dis_observation not in self.N: + self.N[dis_observation] = 0 + return self.N[dis_observation] + else: + if (dis_observation, option) not in self.M: + self.M[(dis_observation, option)] = 0 + return self.M[(dis_observation, option)] + + def _get_q_star(self, observation, option): + """Compute average value of discrete observation - option pair. + + Args: + observation: observation tuple from the environment + option: option alias + + Returns Q_star(discrete form of the observation, option) + """ + + dis_observation = self._to_discrete(observation) + if (dis_observation, option) not in self.TR: + self.TR[(dis_observation, option)] = 0 + return self.TR[(dis_observation, option)] / (1+self._get_visitation_count(observation, option)) + + def _get_possible_options(self): + """Returns a set of options that can be taken from the current node. + Goes through adjacency set of current node and finds which next nodes' + initiation condition is met. + """ + + all_options = set(self.low_level_policies.keys()) + + # Filter nodes whose initiation condition are true + filtered_options = set() + for option_alias in all_options: + self.low_level_policies[option_alias].reset_maneuver() + if self.low_level_policies[option_alias].initiation_condition: + filtered_options.add(option_alias) + + return filtered_options + + def _get_already_visited_options(self, node_num): + """Returns a set of options that have already been tried at least once + from the given node. + + Args: + node_num: node number of the node from which the return set has to + be computed + + Returns a set of aliases of already visited options from node_num + """ + + visited_aliases = set() + for already_existing_node_num in self.adj[node_num]: + already_existing_node = self.nodes[already_existing_node_num] + node_alias = already_existing_node["policy"] + visited_aliases.add(node_alias) + return visited_aliases + + def _ucb_adjusted_q(self, observation, C=1): + """Computes Q_star(observation, option_i) plus the UCB term, which + is C*[predictor(observation, option_i)]/[1+N(observation, option_i)], + for all option_i in the adjacency set of the current node. + + Args: + observation: observation tuple from the environment + C: UCB constant, experimentally defined + + Returns Q values for next nodes + """ + + Q = {} + Q1, Q2 = {}, {} # debug + dis_observation = self._to_discrete(observation) + next_option_nums = self.adj[self.curr_node_num] + for next_option_num in next_option_nums: + next_option = self.nodes[next_option_num]["policy"] + Q1[next_option] = (self._get_q_star(observation, next_option)+200)/400 + Q[(dis_observation, next_option)] = \ + Q1[next_option] + Q2[next_option] = C * \ + (self.predictor(observation, next_option)) / \ + (1 + self._get_visitation_count(observation, next_option)) + self._ucb_vals.add(Q2[next_option]) + Q[(dis_observation, next_option)] += \ + Q2[next_option] + return Q, Q1, Q2 + + def _value(self, observation): + """Computes the value function v(s) by computing sum of all + TR[dis_observation, option_i] divided by N[dis_observation] + + Args: + observation: observation tuple from the environment + + Returns v(s) + """ + + dis_observation = self._to_discrete(observation) + relevant_rewards = [value for key, value in self.TR.items() \ + if key[0] == dis_observation] + sum_rewards = np.sum(relevant_rewards) + return sum_rewards / (1+self._get_visitation_count(observation)) + + def _select(self, observation, depth=0, visualize=False): + """MCTS selection function. For representation, we only use + the discrete part of the observation. + + Args: + observation: observation tuple from the environment + depth: current depth, starts from root node, hence 0 by default + visualize: whether or not to visualize low level steps + + Returns the sum of values from the given observation. + """ + + # First compute whether the observation is terminal or not + env = self.current_node.env + is_terminal = env.is_terminal() + max_depth_reached = depth >= self.max_depth + dis_observation = self._to_discrete(observation) + # print('Depth %d:\t %s' % (depth, dis_observation)) + + if is_terminal or max_depth_reached: + # print('MCTS went %d nodes deep' % depth) + return self._value(observation), 0 # TODO: replace with final goal reward + + Ns = self._get_visitation_count(observation) + Nchildren = len(self.adj[self.curr_node_num]) + + if Ns == 0 or Nchildren < np.sqrt(Ns): + # Add new edge + new_options = self._get_possible_options() + # Randomly choose option + new_option = np.random.choice(list(new_options)) + # Does the chosen option already exist? + already_visted_options = self._get_already_visited_options(\ + self.curr_node_num) + already_chosen_once = new_option in already_visted_options + # If not visited, create it + if not already_chosen_once: + new_node_num, new_node_info = self._create_node(new_option) + self.nodes[new_node_num] = new_node_info + self.adj[new_node_num] = set() + self.adj[self.curr_node_num].add(new_node_num) + + # Find o_star and do a transition, i.e. update curr_node + # Simulate / lookup; first change next + next_observation, episode_R, o_star = self.do_transition(observation, + visualize=visualize) + + # Recursively select next node + remaining_v, all_ep_R = self._select(next_observation, depth+1, visualize=visualize) + + # Update values + self.N[dis_observation] += 1 + self.M[(dis_observation, o_star)] += 1 + self.TR[(dis_observation, o_star)] += (episode_R + remaining_v) + + return self._value(observation), all_ep_R+episode_R + + def traverse(self, observation, visualize=False): + """Do a complete traversal from root to leaf. Assumes the + environment is reset and we are at the root node. + + Args: + observation: observation from the environment + visualize: whether or not to visualize low level steps + + Returns value of root node + """ + + return self._select(observation, visualize=visualize) + + def do_transition(self, observation, visualize=False): + """Do a transition using UCB metric, with the latest observation + from the episodic step. + + Args: + observation: final observation from episodic step + visualize: whether or not to visualize low level steps + + Returns o_star using UCB metric + """ + + # Choose an option to expand using UCB metric + Q, Q1, Q2 = self._ucb_adjusted_q(observation, C=1) + # Compute o_star = argmax_o Q(s, o) + next_keys, next_values = list(Q.keys()), list(Q.values()) + _, o_star = next_keys[np.argmax(next_values)] + # print('Current state: %s' % self._to_discrete(observation)) + # print('Choosing %s: %f, %f, sum:%f' % (o_star, Q1[o_star], Q2[o_star], np.max(next_values))) + # Change current_option to reflect this o_star + self.set_current_node(o_star) + next_obs, eps_R, _, _ = self.step_current_node(\ + visualize_low_level_steps=visualize) + return next_obs, eps_R, o_star + + def set_current_node(self, new_node_alias): + next_option_nums = self.adj[self.curr_node_num] + found_next_node = False + for next_option_num in next_option_nums: + next_option = self.nodes[next_option_num]["policy"] + if next_option == new_node_alias: + # print('Currently at %d:%s, switching to %d:%s' % (self.curr_node_num, self.curr_node_alias, next_option_num, new_node_alias)) + self.curr_node_num = next_option_num + found_next_node = True + break + if self.curr_node_num != 0: + assert found_next_node, "Couldn't transition to next node (%s) "\ + "from current_node (%s)" % (new_node_alias, self.curr_node_alias) + self.curr_node_alias = new_node_alias + self.current_node = self.low_level_policies[self.curr_node_alias] + self.current_node.reset_maneuver() + self.env.set_ego_info_text(self.curr_node_alias) + + def get_best_node(self, observation, use_ucb=False): + # Return node alias for best node from current node + Q, Q1, Q2 = self._ucb_adjusted_q(observation, C=1) + if use_ucb: + next_keys, next_values = list(Q.keys()), list(Q.values()) + _, o_star = next_keys[np.argmax(next_values)] + print(Q) + else: + next_keys, next_values = list(Q1.keys()), list(Q1.values()) + o_star = next_keys[np.argmax(next_values)] + print(Q1) + return o_star \ No newline at end of file diff --git a/backends/online_mcts_controller.py b/backends/online_mcts_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..c35b5532544e38bf9bf99a82fc21085693e8adaa --- /dev/null +++ b/backends/online_mcts_controller.py @@ -0,0 +1,68 @@ +from .controller_base import ControllerBase +from .mcts_learner import MCTSLearner +import tqdm +import numpy as np + +class OnlineMCTSController(ControllerBase): + """Online MCTS""" + + def __init__(self, env, low_level_policies, start_node_alias): + """Constructor for manual policy execution. + + Args: + env: env instance + low_level_policies: low level policies dictionary + """ + super(OnlineMCTSController, self).__init__(env, low_level_policies, start_node_alias) + self.curr_node_alias = start_node_alias + self.controller_args_defaults = { + "predictor": None, + "max_depth": 5, # MCTS depth + "nb_traversals": 30, # MCTS traversals before decision + } + + def set_current_node(self, node_alias): + self.current_node = self.low_level_policies[node_alias] + self.curr_node_alias = node_alias + self.current_node.reset_maneuver() + self.env.set_ego_info_text(node_alias) + + def change_low_level_references(self, env_copy): + # Create a copy of the environment and change references in low level policies. + self.env = env_copy + for policy in self.low_level_policies.values(): + policy.env = env_copy + + def can_transition(self): + return not self.env.is_terminal() + + def do_transition(self): + # Require a predictor function + if self.predictor is None: + raise Exception(self.__class__.__name__ + \ + "predictor is not set. Use set_controller_args().") + # Store the env at this point + orig_env = self.env + np.random.seed() + # Change low level references before init MCTSLearner instance + env_before_mcts = orig_env.copy() + self.change_low_level_references(env_before_mcts) + print('Current Node: %s' % self.curr_node_alias) + mcts = MCTSLearner(self.env, self.low_level_policies, self.curr_node_alias) + mcts.max_depth = self.max_depth + mcts.set_controller_args(predictor = self.predictor) + # Do nb_traversals number of traversals, reset env to this point every time + # print('Doing MCTS with params: max_depth = %d, nb_traversals = %d' % (self.max_depth, self.nb_traversals)) + for num_epoch in range(self.nb_traversals): # tqdm.tqdm(range(self.nb_traversals)): + mcts.curr_node_num = 0 + env_begin_epoch = env_before_mcts.copy() + self.change_low_level_references(env_begin_epoch) + init_obs = self.env.get_features_tuple() + v, all_ep_R = mcts.traverse(init_obs) + self.change_low_level_references(orig_env) + # Find the nodes from the root node + mcts.curr_node_num = 0 + print('%s' % mcts._to_discrete(self.env.get_features_tuple())) + node_after_transition = mcts.get_best_node(self.env.get_features_tuple(), use_ucb=False) + print('MCTS suggested next option: %s' % node_after_transition) + self.set_current_node(node_after_transition) \ No newline at end of file diff --git a/backends/policy_base.py b/backends/policy_base.py new file mode 100644 index 0000000000000000000000000000000000000000..1c8f1bd38aee3327e271ceb7d5b358b3d3b1a33f --- /dev/null +++ b/backends/policy_base.py @@ -0,0 +1,3 @@ +class PolicyBase: + """Abstract policy base from which every policy backend is defined + and inherited.""" \ No newline at end of file diff --git a/backends/rl_controller.py b/backends/rl_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..8fd6c0ece6566307a03ebb612eb08978a1258032 --- /dev/null +++ b/backends/rl_controller.py @@ -0,0 +1,37 @@ +from .controller_base import ControllerBase + + +class RLController(ControllerBase): + """RL controller using a trained policy.""" + + def __init__(self, env, low_level_policies, start_node_alias): + """Constructor for manual policy execution. + + Args: + env: env instance + low_level_policies: low level policies dictionary + """ + super(RLController, self).__init__(env, low_level_policies, start_node_alias) + self.low_level_policy_aliases = list(self.low_level_policies.keys()) + self.trained_policy = None + self.node_terminal_state_reached = False + + # TODO: move this to controller_base? + def set_current_node(self, node_alias): + self.current_node = self.low_level_policies[node_alias] + self.current_node.reset_maneuver() + self.env.set_ego_info_text(node_alias) + + def set_trained_policy(self, policy): + self.trained_policy = policy + + def can_transition(self): + return self.node_terminal_state_reached + + def do_transition(self): + if self.trained_policy is None: + raise Exception(self.__class__.__name__ + \ + "trained_policy is not set. Use set_trained_policy().") + node_index_after_transition = self.trained_policy(self.env.get_features_tuple()) + self.set_current_node(self.low_level_policy_aliases[node_index_after_transition]) + self.node_terminal_state_reached = False \ No newline at end of file diff --git a/backends/trained_policies/0.1mil_weights/changelane_weights_actor.h5f b/backends/trained_policies/0.1mil_weights/changelane_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..739298c51cfa43433ff21b4962cbba17170ee7a9 Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/changelane_weights_actor.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/changelane_weights_critic.h5f b/backends/trained_policies/0.1mil_weights/changelane_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..681b967fa6dbd6a2aaf46413891ca7f9229efeeb Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/changelane_weights_critic.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/follow_weights_actor.h5f b/backends/trained_policies/0.1mil_weights/follow_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..fa417a1dc40b3f5e953e687315f960f2b1ad3e92 Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/follow_weights_actor.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/follow_weights_critic.h5f b/backends/trained_policies/0.1mil_weights/follow_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..0105de348166a4cbaa29998174f5e89e82b3b86e Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/follow_weights_critic.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/keeplane_weights_actor.h5f b/backends/trained_policies/0.1mil_weights/keeplane_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..639fdd5b1889a604f6a61b4ad11b18ee9f703ea1 Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/keeplane_weights_actor.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/keeplane_weights_critic.h5f b/backends/trained_policies/0.1mil_weights/keeplane_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..bc791095159a0f5656381a1c2458bb5cab227c4c Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/keeplane_weights_critic.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/stop_weights_actor.h5f b/backends/trained_policies/0.1mil_weights/stop_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..ee1d2af63e8812fc52a977d1db63342ffb5b0148 Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/stop_weights_actor.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/stop_weights_critic.h5f b/backends/trained_policies/0.1mil_weights/stop_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..ad2e374269254b3fe6151f484ba04b5b9c29af91 Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/stop_weights_critic.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/wait_weights_actor.h5f b/backends/trained_policies/0.1mil_weights/wait_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..a861c76ca25171a7644cb2fe3f75772fe7c5d6ae Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/wait_weights_actor.h5f differ diff --git a/backends/trained_policies/0.1mil_weights/wait_weights_critic.h5f b/backends/trained_policies/0.1mil_weights/wait_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..b20d0e3209408f46f31f2c46e6b6b51ce23b2b65 Binary files /dev/null and b/backends/trained_policies/0.1mil_weights/wait_weights_critic.h5f differ diff --git a/backends/trained_policies/changelane/changelane_weights_actor.h5f b/backends/trained_policies/changelane/changelane_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..0a7ae9e96102f399e64dc83c4cc77e9e3b7a44cd Binary files /dev/null and b/backends/trained_policies/changelane/changelane_weights_actor.h5f differ diff --git a/backends/trained_policies/changelane/changelane_weights_critic.h5f b/backends/trained_policies/changelane/changelane_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..40ca3a83088d8984002bc0a4546020174e9cd431 Binary files /dev/null and b/backends/trained_policies/changelane/changelane_weights_critic.h5f differ diff --git a/backends/trained_policies/follow/follow_weights_actor.h5f b/backends/trained_policies/follow/follow_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..bcb0af7c5012216d05eb966550600c28a3bc322c Binary files /dev/null and b/backends/trained_policies/follow/follow_weights_actor.h5f differ diff --git a/backends/trained_policies/follow/follow_weights_critic.h5f b/backends/trained_policies/follow/follow_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..f6258b53c8589db6a04382245c31f20d7f0915dc Binary files /dev/null and b/backends/trained_policies/follow/follow_weights_critic.h5f differ diff --git a/backends/trained_policies/highlevel/highlevel_weights.h5f b/backends/trained_policies/highlevel/highlevel_weights.h5f new file mode 100644 index 0000000000000000000000000000000000000000..6dcc7ba4718d82e329f833ff23a8c68595309c61 Binary files /dev/null and b/backends/trained_policies/highlevel/highlevel_weights.h5f differ diff --git a/backends/trained_policies/highlevel/highlevel_weights_772.h5f b/backends/trained_policies/highlevel/highlevel_weights_772.h5f new file mode 100644 index 0000000000000000000000000000000000000000..7b986c74005a62b1dc11cbdd3022105ec5317d37 Binary files /dev/null and b/backends/trained_policies/highlevel/highlevel_weights_772.h5f differ diff --git a/backends/trained_policies/keeplane/keeplane_weights_actor.h5f b/backends/trained_policies/keeplane/keeplane_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..d9224714ec7717274033cb3f778800e6cacb690f Binary files /dev/null and b/backends/trained_policies/keeplane/keeplane_weights_actor.h5f differ diff --git a/backends/trained_policies/keeplane/keeplane_weights_critic.h5f b/backends/trained_policies/keeplane/keeplane_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..e5b4bf77af956cdae29a45518d768738fe647b6c Binary files /dev/null and b/backends/trained_policies/keeplane/keeplane_weights_critic.h5f differ diff --git a/backends/trained_policies/mcts/mcts.pickle b/backends/trained_policies/mcts/mcts.pickle new file mode 100644 index 0000000000000000000000000000000000000000..fe3df54930bbdc69e8c9ae8fdc862bf3886a7be8 Binary files /dev/null and b/backends/trained_policies/mcts/mcts.pickle differ diff --git a/backends/trained_policies/stop/stop_weights_actor.h5f b/backends/trained_policies/stop/stop_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..7ef9b12a24464c9c9c4d0ca0bd625b6d1875efb9 Binary files /dev/null and b/backends/trained_policies/stop/stop_weights_actor.h5f differ diff --git a/backends/trained_policies/stop/stop_weights_critic.h5f b/backends/trained_policies/stop/stop_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..41a357a5e68aac591dea24edb47f5339960c0c90 Binary files /dev/null and b/backends/trained_policies/stop/stop_weights_critic.h5f differ diff --git a/backends/trained_policies/wait/wait_weights_actor.h5f b/backends/trained_policies/wait/wait_weights_actor.h5f new file mode 100644 index 0000000000000000000000000000000000000000..00703d9cc1931bc31083f9a77575598a030f92c3 Binary files /dev/null and b/backends/trained_policies/wait/wait_weights_actor.h5f differ diff --git a/backends/trained_policies/wait/wait_weights_critic.h5f b/backends/trained_policies/wait/wait_weights_critic.h5f new file mode 100644 index 0000000000000000000000000000000000000000..330e90c08e129f18a05e2a54882f8bb9fffc1957 Binary files /dev/null and b/backends/trained_policies/wait/wait_weights_critic.h5f differ diff --git a/config.json b/config.json new file mode 100644 index 0000000000000000000000000000000000000000..b8d9b1c65aeebae2c3a2ccf40f6f9c6b4b6de70d --- /dev/null +++ b/config.json @@ -0,0 +1,15 @@ +{ + "nodes": { + "wait": "Wait", + "follow": "Follow", + "stop": "Stop", + "changelane": "ChangeLane", + "keeplane": "KeepLane" + }, + + "edges": { + "keeplane": "keeplane" + }, + "start_node": "keeplane", + "method": "rl" +} \ No newline at end of file diff --git a/documentation/figures/maneuver_geometry.eps b/documentation/figures/maneuver_geometry.eps new file mode 100644 index 0000000000000000000000000000000000000000..14553b4a8a1704d05884949b2c2e0064c038b14e Binary files /dev/null and b/documentation/figures/maneuver_geometry.eps differ diff --git a/documentation/figures/road_geometry.eps b/documentation/figures/road_geometry.eps new file mode 100644 index 0000000000000000000000000000000000000000..7a753bdfa62b9cc7aa0842ae1f7ac9c96bf05560 Binary files /dev/null and b/documentation/figures/road_geometry.eps differ diff --git a/documentation/index.html b/documentation/index.html new file mode 120000 index 0000000000000000000000000000000000000000..993c92c218562bfa6ee35332d9e2ac8045c94e0f --- /dev/null +++ b/documentation/index.html @@ -0,0 +1 @@ +sphinx/.build/index.html \ No newline at end of file diff --git a/documentation/sphinx/.build/.buildinfo b/documentation/sphinx/.build/.buildinfo new file mode 100644 index 0000000000000000000000000000000000000000..c44415553b1833f55f8ad8ad4bed6b2b82ed8086 --- /dev/null +++ b/documentation/sphinx/.build/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: aa9b388d303cad18faf5c75ada457b3d +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/documentation/sphinx/.build/.doc/backends.html b/documentation/sphinx/.build/.doc/backends.html new file mode 100644 index 0000000000000000000000000000000000000000..ffc37fa577b3379e6e713902af2fc773ec15cd2b --- /dev/null +++ b/documentation/sphinx/.build/.doc/backends.html @@ -0,0 +1,883 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>backends package — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>backends package</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="backends-package"> +<h1>backends package<a class="headerlink" href="#backends-package" title="Permalink to this headline">¶</a></h1> +<div class="section" id="submodules"> +<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="module-backends.baselines_learner"> +<span id="backends-baselines-learner-module"></span><h2>backends.baselines_learner module<a class="headerlink" href="#module-backends.baselines_learner" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.baselines_learner.PPO2Agent"> +<em class="property">class </em><code class="descclassname">backends.baselines_learner.</code><code class="descname">PPO2Agent</code><span class="sig-paren">(</span><em>input_shape</em>, <em>nb_actions</em>, <em>env</em>, <em>policy=None</em>, <em>tensorboard=False</em>, <em>log_path='./logs'</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.learner_base.LearnerBase" title="backends.learner_base.LearnerBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.learner_base.LearnerBase</span></code></a></p> +<dl class="method"> +<dt id="backends.baselines_learner.PPO2Agent.create_agent"> +<code class="descname">create_agent</code><span class="sig-paren">(</span><em>policy</em>, <em>tensorboard</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent.create_agent" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates a PPO agent</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Returns:</th><td class="field-body">stable_baselines PPO2 object</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.baselines_learner.PPO2Agent.fit"> +<code class="descname">fit</code><span class="sig-paren">(</span><em>env=None</em>, <em>nb_steps=1000000</em>, <em>visualize=False</em>, <em>nb_max_episode_steps=200</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent.fit" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.baselines_learner.PPO2Agent.forward"> +<code class="descname">forward</code><span class="sig-paren">(</span><em>observation</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent.forward" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.baselines_learner.PPO2Agent.get_default_policy"> +<code class="descname">get_default_policy</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent.get_default_policy" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates the default policy.</p> +<p>Returns: stable_baselines Policy object. default is MlpPolicy</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.baselines_learner.PPO2Agent.load_weights"> +<code class="descname">load_weights</code><span class="sig-paren">(</span><em>file_name='test_weights.h5f'</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent.load_weights" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.baselines_learner.PPO2Agent.save_weights"> +<code class="descname">save_weights</code><span class="sig-paren">(</span><em>file_name='test_weights.h5f'</em>, <em>overwrite=True</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent.save_weights" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.baselines_learner.PPO2Agent.set_environment"> +<code class="descname">set_environment</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent.set_environment" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.baselines_learner.PPO2Agent.test_model"> +<code class="descname">test_model</code><span class="sig-paren">(</span><em>env=None</em>, <em>nb_episodes=50</em>, <em>visualize=True</em>, <em>nb_max_episode_steps=200</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.baselines_learner.PPO2Agent.test_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Test the agent on the environment.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>env</strong> – the environment instance. Should contain step(), reset() and optionally, render()</li> +<li><strong>nb_episodes</strong> – Number of episodes to run</li> +<li><strong>visualize</strong> – If True, visualizes the test. Works only if render() is present in env</li> +<li><strong>nb_max_episode_steps</strong> – Maximum number of steps per episode</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-backends.controller_base"> +<span id="backends-controller-base-module"></span><h2>backends.controller_base module<a class="headerlink" href="#module-backends.controller_base" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.controller_base.ControllerBase"> +<em class="property">class </em><code class="descclassname">backends.controller_base.</code><code class="descname">ControllerBase</code><span class="sig-paren">(</span><em>env</em>, <em>low_level_policies</em>, <em>start_node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.controller_base.ControllerBase" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.policy_base.PolicyBase" title="backends.policy_base.PolicyBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.policy_base.PolicyBase</span></code></a></p> +<p>Abstract class for controllers.</p> +<dl class="method"> +<dt id="backends.controller_base.ControllerBase.can_transition"> +<code class="descname">can_transition</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.controller_base.ControllerBase.can_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Returns boolean signifying whether we can transition. To be +implemented in subclass.</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.controller_base.ControllerBase.do_transition"> +<code class="descname">do_transition</code><span class="sig-paren">(</span><em>observation</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.controller_base.ControllerBase.do_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Do a transition, assuming we can transition. To be +implemented in subclass.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>observation</strong> – final observation from episodic step</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.controller_base.ControllerBase.low_level_step_current_node"> +<code class="descname">low_level_step_current_node</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.controller_base.ControllerBase.low_level_step_current_node" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.controller_base.ControllerBase.set_controller_args"> +<code class="descname">set_controller_args</code><span class="sig-paren">(</span><em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.controller_base.ControllerBase.set_controller_args" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.controller_base.ControllerBase.set_current_node"> +<code class="descname">set_current_node</code><span class="sig-paren">(</span><em>node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.controller_base.ControllerBase.set_current_node" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets the current node which is being executed</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>node</strong> – node alias of the node to be set</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.controller_base.ControllerBase.step_current_node"> +<code class="descname">step_current_node</code><span class="sig-paren">(</span><em>visualize_low_level_steps=False</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.controller_base.ControllerBase.step_current_node" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-backends.kerasrl_learner"> +<span id="backends-kerasrl-learner-module"></span><h2>backends.kerasrl_learner module<a class="headerlink" href="#module-backends.kerasrl_learner" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.kerasrl_learner.DDPGLearner"> +<em class="property">class </em><code class="descclassname">backends.kerasrl_learner.</code><code class="descname">DDPGLearner</code><span class="sig-paren">(</span><em>input_shape=(48</em>, <em>)</em>, <em>nb_actions=2</em>, <em>actor=None</em>, <em>critic=None</em>, <em>critic_action_input=None</em>, <em>memory=None</em>, <em>random_process=None</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.learner_base.LearnerBase" title="backends.learner_base.LearnerBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.learner_base.LearnerBase</span></code></a></p> +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.create_agent"> +<code class="descname">create_agent</code><span class="sig-paren">(</span><em>actor</em>, <em>critic</em>, <em>critic_action_input</em>, <em>memory</em>, <em>random_process</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.create_agent" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates a KerasRL DDPGAgent with given components.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>actor</strong> – Keras Model of actor which takes observation as input and outputs actions.</li> +<li><strong>critic</strong> – Keras Model of critic that takes concatenation of observation and action and outputs a single value.</li> +<li><strong>critic_action_input</strong> – Keras Input which was used in creating action input of the critic model.</li> +<li><strong>memory</strong> – KerasRL Memory.</li> +<li><strong>random_process</strong> – KerasRL random process.</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">KerasRL DDPGAgent object</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.get_default_actor_model"> +<code class="descname">get_default_actor_model</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.get_default_actor_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates the default actor model.</p> +<p>Returns: Keras Model object of actor</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.get_default_critic_model"> +<code class="descname">get_default_critic_model</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.get_default_critic_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates the default critic model.</p> +<p>Returns: Keras Model object of critic</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.get_default_memory"> +<code class="descname">get_default_memory</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.get_default_memory" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates the default memory model.</p> +<p>Returns: KerasRL SequentialMemory object</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.get_default_randomprocess"> +<code class="descname">get_default_randomprocess</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.get_default_randomprocess" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates the default random process model.</p> +<p>Returns: KerasRL OrnsteinUhlenbeckProcess object</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.load_model"> +<code class="descname">load_model</code><span class="sig-paren">(</span><em>file_name='test_weights.h5f'</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.load_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Load the weights of an agent.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>file_name</strong> – filename to be used when loading</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.predict"> +<code class="descname">predict</code><span class="sig-paren">(</span><em>observation</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.predict" title="Permalink to this definition">¶</a></dt> +<dd><p>Perform a forward pass and return next action by agent based on +current observation.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>observation</strong> – the current observation. Shape should be same as self.input_shape</td> +</tr> +</tbody> +</table> +<p>Returns: The action taken by agent depending on given observation</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.save_model"> +<code class="descname">save_model</code><span class="sig-paren">(</span><em>file_name='test_weights.h5f'</em>, <em>overwrite=True</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.save_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Save the weights of the agent. To be used after learning.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>file_name</strong> – filename to be used when saving</li> +<li><strong>overwrite</strong> – If True, overwrites existing file</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.test_model"> +<code class="descname">test_model</code><span class="sig-paren">(</span><em>env</em>, <em>nb_episodes=50</em>, <em>visualize=True</em>, <em>nb_max_episode_steps=200</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.test_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Test the agent on the environment.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>env</strong> – the environment instance. Should contain step(), reset() and optionally, render()</li> +<li><strong>nb_episodes</strong> – Number of episodes to run</li> +<li><strong>visualize</strong> – If True, visualizes the test. Works only if render() is present in env</li> +<li><strong>nb_max_episode_steps</strong> – Maximum number of steps per episode</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DDPGLearner.train"> +<code class="descname">train</code><span class="sig-paren">(</span><em>env</em>, <em>nb_steps=1000000</em>, <em>visualize=False</em>, <em>verbose=1</em>, <em>log_interval=10000</em>, <em>nb_max_episode_steps=200</em>, <em>model_checkpoints=False</em>, <em>checkpoint_interval=100000</em>, <em>tensorboard=False</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DDPGLearner.train" title="Permalink to this definition">¶</a></dt> +<dd><p>Train the learning agent on the environment.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>env</strong> – the environment instance. Should contain step() and reset() methods and optionally render()</li> +<li><strong>nb_steps</strong> – the total number of steps to train</li> +<li><strong>visualize</strong> – If True, visualizes the training. Works only if render() is present in env</li> +<li><strong>nb_max_episode_steps</strong> – Maximum number of steps per episode</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="backends.kerasrl_learner.DQNAgentOverOptions"> +<em class="property">class </em><code class="descclassname">backends.kerasrl_learner.</code><code class="descname">DQNAgentOverOptions</code><span class="sig-paren">(</span><em>model</em>, <em>low_level_policies</em>, <em>policy=None</em>, <em>test_policy=None</em>, <em>enable_double_dqn=True</em>, <em>enable_dueling_network=False</em>, <em>dueling_type='avg'</em>, <em>*args</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNAgentOverOptions" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">rl.agents.dqn.DQNAgent</span></code></p> +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNAgentOverOptions.forward"> +<code class="descname">forward</code><span class="sig-paren">(</span><em>observation</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNAgentOverOptions.forward" title="Permalink to this definition">¶</a></dt> +<dd><p>Takes the an observation from the environment and returns the action to be taken next. +If the policy is implemented by a neural network, this corresponds to a forward (inference) pass.</p> +<dl class="docutils"> +<dt># Argument</dt> +<dd>observation (object): The current observation from the environment.</dd> +<dt># Returns</dt> +<dd>The next action to be executed in the environment.</dd> +</dl> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNAgentOverOptions.get_modified_q_values"> +<code class="descname">get_modified_q_values</code><span class="sig-paren">(</span><em>observation</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNAgentOverOptions.get_modified_q_values" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="backends.kerasrl_learner.DQNLearner"> +<em class="property">class </em><code class="descclassname">backends.kerasrl_learner.</code><code class="descname">DQNLearner</code><span class="sig-paren">(</span><em>input_shape=(48</em>, <em>)</em>, <em>nb_actions=5</em>, <em>low_level_policies=None</em>, <em>model=None</em>, <em>policy=None</em>, <em>memory=None</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.learner_base.LearnerBase" title="backends.learner_base.LearnerBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.learner_base.LearnerBase</span></code></a></p> +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.create_agent"> +<code class="descname">create_agent</code><span class="sig-paren">(</span><em>model</em>, <em>policy</em>, <em>memory</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.create_agent" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates a KerasRL DDPGAgent with given components.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>model</strong> – Keras Model of model which takes observation as input and outputs discrete actions.</li> +<li><strong>memory</strong> – KerasRL Memory.</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">KerasRL DQN object</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.get_default_memory"> +<code class="descname">get_default_memory</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.get_default_memory" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates the default memory model.</p> +<p>Returns: KerasRL SequentialMemory object</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.get_default_model"> +<code class="descname">get_default_model</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.get_default_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Creates the default model.</p> +<p>Returns: Keras Model object of actor</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.get_default_policy"> +<code class="descname">get_default_policy</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.get_default_policy" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.get_q_value"> +<code class="descname">get_q_value</code><span class="sig-paren">(</span><em>observation</em>, <em>action</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.get_q_value" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.get_q_value_using_option_alias"> +<code class="descname">get_q_value_using_option_alias</code><span class="sig-paren">(</span><em>observation</em>, <em>option_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.get_q_value_using_option_alias" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.get_softq_value_using_option_alias"> +<code class="descname">get_softq_value_using_option_alias</code><span class="sig-paren">(</span><em>observation</em>, <em>option_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.get_softq_value_using_option_alias" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.load_model"> +<code class="descname">load_model</code><span class="sig-paren">(</span><em>file_name='test_weights.h5f'</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.load_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Load the weights of an agent.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>file_name</strong> – filename to be used when loading</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.predict"> +<code class="descname">predict</code><span class="sig-paren">(</span><em>observation</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.predict" title="Permalink to this definition">¶</a></dt> +<dd><p>Perform a forward pass and return next action by agent based on +current observation.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>observation</strong> – the current observation. Shape should be same as self.input_shape</td> +</tr> +</tbody> +</table> +<p>Returns: The action taken by agent depending on given observation</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.save_model"> +<code class="descname">save_model</code><span class="sig-paren">(</span><em>file_name='test_weights.h5f'</em>, <em>overwrite=True</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.save_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Save the weights of the agent. To be used after learning.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>file_name</strong> – filename to be used when saving</li> +<li><strong>overwrite</strong> – If True, overwrites existing file</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.test_model"> +<code class="descname">test_model</code><span class="sig-paren">(</span><em>env</em>, <em>nb_episodes=5</em>, <em>visualize=True</em>, <em>nb_max_episode_steps=400</em>, <em>success_reward_threshold=100</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.test_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Test the agent on the environment.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>env</strong> – the environment instance. Should contain step(), reset() and optionally, render()</li> +<li><strong>nb_episodes</strong> – Number of episodes to run</li> +<li><strong>visualize</strong> – If True, visualizes the test. Works only if render() is present in env</li> +<li><strong>nb_max_episode_steps</strong> – Maximum number of steps per episode</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.kerasrl_learner.DQNLearner.train"> +<code class="descname">train</code><span class="sig-paren">(</span><em>env</em>, <em>nb_steps=1000000</em>, <em>visualize=False</em>, <em>nb_max_episode_steps=200</em>, <em>tensorboard=False</em>, <em>model_checkpoints=False</em>, <em>checkpoint_interval=10000</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.kerasrl_learner.DQNLearner.train" title="Permalink to this definition">¶</a></dt> +<dd><p>Train the learning agent on the environment.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>env</strong> – the environment instance. Should contain step() and reset() methods and optionally render()</li> +<li><strong>nb_steps</strong> – the total number of steps to train</li> +<li><strong>visualize</strong> – If True, visualizes the training. Works only if render() is present in env</li> +<li><strong>nb_max_episode_steps</strong> – Maximum number of steps per episode</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-backends.learner_base"> +<span id="backends-learner-base-module"></span><h2>backends.learner_base module<a class="headerlink" href="#module-backends.learner_base" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.learner_base.LearnerBase"> +<em class="property">class </em><code class="descclassname">backends.learner_base.</code><code class="descname">LearnerBase</code><span class="sig-paren">(</span><em>input_shape=(10</em>, <em>)</em>, <em>nb_actions=2</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.learner_base.LearnerBase" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.policy_base.PolicyBase" title="backends.policy_base.PolicyBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.policy_base.PolicyBase</span></code></a></p> +<p>The abstract class from which each learning policy backend is defined +and inherited.</p> +<dl class="method"> +<dt id="backends.learner_base.LearnerBase.load_model"> +<code class="descname">load_model</code><span class="sig-paren">(</span><em>file_name</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.learner_base.LearnerBase.load_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Load the weights of an agent.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>file_name</strong> – filename to be used when loading</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.learner_base.LearnerBase.predict"> +<code class="descname">predict</code><span class="sig-paren">(</span><em>observation</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.learner_base.LearnerBase.predict" title="Permalink to this definition">¶</a></dt> +<dd><p>Perform a forward pass and return next action by agent based on +current observation.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>observation</strong> – the current observation. Shape should be same as self.input_shape</td> +</tr> +</tbody> +</table> +<p>Returns: The action taken by agent depending on given observation</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.learner_base.LearnerBase.save_model"> +<code class="descname">save_model</code><span class="sig-paren">(</span><em>file_name</em>, <em>overwrite=True</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.learner_base.LearnerBase.save_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Save the weights of the agent. To be used after learning.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>file_name</strong> – filename to be used when saving</li> +<li><strong>overwrite</strong> – If True, overwrites existing file</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.learner_base.LearnerBase.test_model"> +<code class="descname">test_model</code><span class="sig-paren">(</span><em>env</em>, <em>nb_episodes=5</em>, <em>visualize=True</em>, <em>nb_max_episode_steps=200</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.learner_base.LearnerBase.test_model" title="Permalink to this definition">¶</a></dt> +<dd><p>Test the agent on the environment.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>env</strong> – the environment instance. Should contain step(), reset() and optionally, render()</li> +<li><strong>nb_episodes</strong> – Number of episodes to run</li> +<li><strong>visualize</strong> – If True, visualizes the test. Works only if render() is present in env</li> +<li><strong>nb_max_episode_steps</strong> – Maximum number of steps per episode</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.learner_base.LearnerBase.train"> +<code class="descname">train</code><span class="sig-paren">(</span><em>env</em>, <em>nb_steps=50000</em>, <em>visualize=False</em>, <em>nb_max_episode_steps=200</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.learner_base.LearnerBase.train" title="Permalink to this definition">¶</a></dt> +<dd><p>Train the learning agent on the environment.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>env</strong> – the environment instance. Should contain step() and reset() methods and optionally render()</li> +<li><strong>nb_steps</strong> – the total number of steps to train</li> +<li><strong>visualize</strong> – If True, visualizes the training. Works only if render() is present in env</li> +<li><strong>nb_max_episode_steps</strong> – Maximum number of steps per episode</li> +</ul> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-backends.manual_policy"> +<span id="backends-manual-policy-module"></span><h2>backends.manual_policy module<a class="headerlink" href="#module-backends.manual_policy" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.manual_policy.ManualPolicy"> +<em class="property">class </em><code class="descclassname">backends.manual_policy.</code><code class="descname">ManualPolicy</code><span class="sig-paren">(</span><em>env</em>, <em>low_level_policies</em>, <em>transition_adj</em>, <em>start_node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.manual_policy.ManualPolicy" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.controller_base.ControllerBase" title="backends.controller_base.ControllerBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.controller_base.ControllerBase</span></code></a></p> +<p>Manual policy execution using nodes and edges.</p> +<dl class="method"> +<dt id="backends.manual_policy.ManualPolicy.can_transition"> +<code class="descname">can_transition</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.manual_policy.ManualPolicy.can_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Check if we can transition.</p> +<p>Returns True if we can, false if we cannot.</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.manual_policy.ManualPolicy.do_transition"> +<code class="descname">do_transition</code><span class="sig-paren">(</span><em>observation</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.manual_policy.ManualPolicy.do_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Do a singular transition using the specified edges.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>observation</strong> – final observation from episodic step (not used)</td> +</tr> +</tbody> +</table> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-backends.mcts_learner"> +<span id="backends-mcts-learner-module"></span><h2>backends.mcts_learner module<a class="headerlink" href="#module-backends.mcts_learner" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.mcts_learner.MCTSLearner"> +<em class="property">class </em><code class="descclassname">backends.mcts_learner.</code><code class="descname">MCTSLearner</code><span class="sig-paren">(</span><em>env</em>, <em>low_level_policies</em>, <em>start_node_alias</em>, <em>max_depth=10</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.mcts_learner.MCTSLearner" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.controller_base.ControllerBase" title="backends.controller_base.ControllerBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.controller_base.ControllerBase</span></code></a></p> +<p>Monte Carlo Tree Search implementation using the UCB1 and +progressive widening approach as explained in Paxton et al (2017).</p> +<dl class="attribute"> +<dt id="backends.mcts_learner.MCTSLearner.M"> +<code class="descname">M</code><em class="property"> = None</em><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.M" title="Permalink to this definition">¶</a></dt> +<dd><p>visitation count of discrete observation with option</p> +</dd></dl> + +<dl class="attribute"> +<dt id="backends.mcts_learner.MCTSLearner.N"> +<code class="descname">N</code><em class="property"> = None</em><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.N" title="Permalink to this definition">¶</a></dt> +<dd><p>visitation count of discrete observations</p> +</dd></dl> + +<dl class="attribute"> +<dt id="backends.mcts_learner.MCTSLearner.TR"> +<code class="descname">TR</code><em class="property"> = None</em><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.TR" title="Permalink to this definition">¶</a></dt> +<dd><p>total reward from given discrete observation with option</p> +</dd></dl> + +<dl class="attribute"> +<dt id="backends.mcts_learner.MCTSLearner.adj"> +<code class="descname">adj</code><em class="property"> = None</em><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.adj" title="Permalink to this definition">¶</a></dt> +<dd><p>adjacency list</p> +</dd></dl> + +<dl class="attribute"> +<dt id="backends.mcts_learner.MCTSLearner.curr_node_alias"> +<code class="descname">curr_node_alias</code><em class="property"> = None</em><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.curr_node_alias" title="Permalink to this definition">¶</a></dt> +<dd><p>store current node alias</p> +</dd></dl> + +<dl class="attribute"> +<dt id="backends.mcts_learner.MCTSLearner.curr_node_num"> +<code class="descname">curr_node_num</code><em class="property"> = None</em><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.curr_node_num" title="Permalink to this definition">¶</a></dt> +<dd><p>store current node’s id</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.mcts_learner.MCTSLearner.do_transition"> +<code class="descname">do_transition</code><span class="sig-paren">(</span><em>observation</em>, <em>visualize=False</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.do_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Do a transition using UCB metric, with the latest observation +from the episodic step.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>observation</strong> – final observation from episodic step</li> +<li><strong>visualize</strong> – whether or not to visualize low level steps</li> +</ul> +</td> +</tr> +</tbody> +</table> +<p>Returns o_star using UCB metric</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.mcts_learner.MCTSLearner.get_best_node"> +<code class="descname">get_best_node</code><span class="sig-paren">(</span><em>observation</em>, <em>use_ucb=False</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.get_best_node" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.mcts_learner.MCTSLearner.load_model"> +<code class="descname">load_model</code><span class="sig-paren">(</span><em>file_name='mcts.pickle'</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.load_model" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="backends.mcts_learner.MCTSLearner.nodes"> +<code class="descname">nodes</code><em class="property"> = None</em><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.nodes" title="Permalink to this definition">¶</a></dt> +<dd><p>node properties</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.mcts_learner.MCTSLearner.save_model"> +<code class="descname">save_model</code><span class="sig-paren">(</span><em>file_name='mcts.pickle'</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.save_model" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.mcts_learner.MCTSLearner.set_current_node"> +<code class="descname">set_current_node</code><span class="sig-paren">(</span><em>new_node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.set_current_node" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets the current node which is being executed</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>node</strong> – node alias of the node to be set</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.mcts_learner.MCTSLearner.traverse"> +<code class="descname">traverse</code><span class="sig-paren">(</span><em>observation</em>, <em>visualize=False</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.mcts_learner.MCTSLearner.traverse" title="Permalink to this definition">¶</a></dt> +<dd><p>Do a complete traversal from root to leaf. Assumes the +environment is reset and we are at the root node.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>observation</strong> – observation from the environment</li> +<li><strong>visualize</strong> – whether or not to visualize low level steps</li> +</ul> +</td> +</tr> +</tbody> +</table> +<p>Returns value of root node</p> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-backends.online_mcts_controller"> +<span id="backends-online-mcts-controller-module"></span><h2>backends.online_mcts_controller module<a class="headerlink" href="#module-backends.online_mcts_controller" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.online_mcts_controller.OnlineMCTSController"> +<em class="property">class </em><code class="descclassname">backends.online_mcts_controller.</code><code class="descname">OnlineMCTSController</code><span class="sig-paren">(</span><em>env</em>, <em>low_level_policies</em>, <em>start_node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.online_mcts_controller.OnlineMCTSController" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.controller_base.ControllerBase" title="backends.controller_base.ControllerBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.controller_base.ControllerBase</span></code></a></p> +<p>Online MCTS</p> +<dl class="method"> +<dt id="backends.online_mcts_controller.OnlineMCTSController.can_transition"> +<code class="descname">can_transition</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.online_mcts_controller.OnlineMCTSController.can_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Returns boolean signifying whether we can transition. To be +implemented in subclass.</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.online_mcts_controller.OnlineMCTSController.change_low_level_references"> +<code class="descname">change_low_level_references</code><span class="sig-paren">(</span><em>env_copy</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.online_mcts_controller.OnlineMCTSController.change_low_level_references" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="backends.online_mcts_controller.OnlineMCTSController.do_transition"> +<code class="descname">do_transition</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.online_mcts_controller.OnlineMCTSController.do_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Do a transition, assuming we can transition. To be +implemented in subclass.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>observation</strong> – final observation from episodic step</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.online_mcts_controller.OnlineMCTSController.set_current_node"> +<code class="descname">set_current_node</code><span class="sig-paren">(</span><em>node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.online_mcts_controller.OnlineMCTSController.set_current_node" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets the current node which is being executed</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>node</strong> – node alias of the node to be set</td> +</tr> +</tbody> +</table> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-backends.policy_base"> +<span id="backends-policy-base-module"></span><h2>backends.policy_base module<a class="headerlink" href="#module-backends.policy_base" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.policy_base.PolicyBase"> +<em class="property">class </em><code class="descclassname">backends.policy_base.</code><code class="descname">PolicyBase</code><a class="headerlink" href="#backends.policy_base.PolicyBase" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>Abstract policy base from which every policy backend is defined +and inherited.</p> +</dd></dl> + +</div> +<div class="section" id="module-backends.rl_controller"> +<span id="backends-rl-controller-module"></span><h2>backends.rl_controller module<a class="headerlink" href="#module-backends.rl_controller" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="backends.rl_controller.RLController"> +<em class="property">class </em><code class="descclassname">backends.rl_controller.</code><code class="descname">RLController</code><span class="sig-paren">(</span><em>env</em>, <em>low_level_policies</em>, <em>start_node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.rl_controller.RLController" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#backends.controller_base.ControllerBase" title="backends.controller_base.ControllerBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">backends.controller_base.ControllerBase</span></code></a></p> +<p>RL controller using a trained policy.</p> +<dl class="method"> +<dt id="backends.rl_controller.RLController.can_transition"> +<code class="descname">can_transition</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.rl_controller.RLController.can_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Returns boolean signifying whether we can transition. To be +implemented in subclass.</p> +</dd></dl> + +<dl class="method"> +<dt id="backends.rl_controller.RLController.do_transition"> +<code class="descname">do_transition</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#backends.rl_controller.RLController.do_transition" title="Permalink to this definition">¶</a></dt> +<dd><p>Do a transition, assuming we can transition. To be +implemented in subclass.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>observation</strong> – final observation from episodic step</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.rl_controller.RLController.set_current_node"> +<code class="descname">set_current_node</code><span class="sig-paren">(</span><em>node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.rl_controller.RLController.set_current_node" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets the current node which is being executed</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>node</strong> – node alias of the node to be set</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="backends.rl_controller.RLController.set_trained_policy"> +<code class="descname">set_trained_policy</code><span class="sig-paren">(</span><em>policy</em><span class="sig-paren">)</span><a class="headerlink" href="#backends.rl_controller.RLController.set_trained_policy" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-backends"> +<span id="module-contents"></span><h2>Module contents<a class="headerlink" href="#module-backends" title="Permalink to this headline">¶</a></h2> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/env.html b/documentation/sphinx/.build/.doc/env.html new file mode 100644 index 0000000000000000000000000000000000000000..c6b76ef48d6c77bdc491defd42e96fb17e168865 --- /dev/null +++ b/documentation/sphinx/.build/.doc/env.html @@ -0,0 +1,183 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>env package — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>env package</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="env-package"> +<h1>env package<a class="headerlink" href="#env-package" title="Permalink to this headline">¶</a></h1> +<div class="section" id="subpackages"> +<h2>Subpackages<a class="headerlink" href="#subpackages" title="Permalink to this headline">¶</a></h2> +<div class="toctree-wrapper compound"> +<ul> +<li class="toctree-l1"><a class="reference internal" href="env.simple_intersection.html">env.simple_intersection package</a><ul> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#submodules">Submodules</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.constants">env.simple_intersection.constants module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.features">env.simple_intersection.features module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.road_geokinemetry">env.simple_intersection.road_geokinemetry module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.road_networks">env.simple_intersection.road_networks module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.shapes">env.simple_intersection.shapes module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.simple_intersection_env">env.simple_intersection.simple_intersection_env module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.utilities">env.simple_intersection.utilities module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.vehicle_networks">env.simple_intersection.vehicle_networks module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.vehicles">env.simple_intersection.vehicles module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection">Module contents</a></li> +</ul> +</li> +</ul> +</div> +</div> +<div class="section" id="submodules"> +<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="module-env.env_base"> +<span id="env-env-base-module"></span><h2>env.env_base module<a class="headerlink" href="#module-env.env_base" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.env_base.EpisodicEnvBase"> +<em class="property">class </em><code class="descclassname">env.env_base.</code><code class="descname">EpisodicEnvBase</code><a class="headerlink" href="#env.env_base.EpisodicEnvBase" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#env.env_base.GymCompliantEnvBase" title="env.env_base.GymCompliantEnvBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.env_base.GymCompliantEnvBase</span></code></a></p> +<dl class="method"> +<dt id="env.env_base.EpisodicEnvBase.current_model_checking_result"> +<code class="descname">current_model_checking_result</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.env_base.EpisodicEnvBase.current_model_checking_result" title="Permalink to this definition">¶</a></dt> +<dd><p>Returns whether or not any of the conditions is currently violated.</p> +</dd></dl> + +<dl class="method"> +<dt id="env.env_base.EpisodicEnvBase.disable_LTL_preconditions"> +<code class="descname">disable_LTL_preconditions</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.env_base.EpisodicEnvBase.disable_LTL_preconditions" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.env_base.EpisodicEnvBase.enable_LTL_preconditions"> +<code class="descname">enable_LTL_preconditions</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.env_base.EpisodicEnvBase.enable_LTL_preconditions" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="env.env_base.EpisodicEnvBase.goal_achieved"> +<code class="descname">goal_achieved</code><a class="headerlink" href="#env.env_base.EpisodicEnvBase.goal_achieved" title="Permalink to this definition">¶</a></dt> +<dd><p>Check whether the ego vehicle achieves the goal of the maneuver or +not.</p> +<p>By default, there is no goal, so the ego vehicle never achieves +it (i.e., goal_achieved is always False).</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.env_base.EpisodicEnvBase.r_terminal"> +<code class="descname">r_terminal</code><a class="headerlink" href="#env.env_base.EpisodicEnvBase.r_terminal" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.env_base.EpisodicEnvBase.step"> +<code class="descname">step</code><span class="sig-paren">(</span><em>u</em><span class="sig-paren">)</span><a class="headerlink" href="#env.env_base.EpisodicEnvBase.step" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant step function which +will be implemented in the subclass.</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.env_base.EpisodicEnvBase.terminal_reward_type"> +<code class="descname">terminal_reward_type</code><em class="property"> = 'max'</em><a class="headerlink" href="#env.env_base.EpisodicEnvBase.terminal_reward_type" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="env.env_base.EpisodicEnvBase.termination_condition"> +<code class="descname">termination_condition</code><a class="headerlink" href="#env.env_base.EpisodicEnvBase.termination_condition" title="Permalink to this definition">¶</a></dt> +<dd><p>In the subclass, specify the condition for termination of the episode +(or the maneuver).</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.env_base.EpisodicEnvBase.violation_happened"> +<code class="descname">violation_happened</code><a class="headerlink" href="#env.env_base.EpisodicEnvBase.violation_happened" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="env.env_base.GymCompliantEnvBase"> +<em class="property">class </em><code class="descclassname">env.env_base.</code><code class="descname">GymCompliantEnvBase</code><a class="headerlink" href="#env.env_base.GymCompliantEnvBase" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<dl class="method"> +<dt id="env.env_base.GymCompliantEnvBase.render"> +<code class="descname">render</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.env_base.GymCompliantEnvBase.render" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant step function which +will be implemented in the subclass.</p> +</dd></dl> + +<dl class="method"> +<dt id="env.env_base.GymCompliantEnvBase.reset"> +<code class="descname">reset</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.env_base.GymCompliantEnvBase.reset" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant reset function which +will be implemented in the subclass.</p> +</dd></dl> + +<dl class="method"> +<dt id="env.env_base.GymCompliantEnvBase.step"> +<code class="descname">step</code><span class="sig-paren">(</span><em>action</em><span class="sig-paren">)</span><a class="headerlink" href="#env.env_base.GymCompliantEnvBase.step" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant step function which +will be implemented in the subclass.</p> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-env.road_env"> +<span id="env-road-env-module"></span><h2>env.road_env module<a class="headerlink" href="#module-env.road_env" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.road_env.RoadEnv"> +<em class="property">class </em><code class="descclassname">env.road_env.</code><code class="descname">RoadEnv</code><a class="headerlink" href="#env.road_env.RoadEnv" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>The generic road env</p> +<p>TODO: Implement this generic road env for plugging-in other road envs. +TODO: roadEnv also having a step() function can cause a problem.</p> +</dd></dl> + +</div> +<div class="section" id="module-env"> +<span id="module-contents"></span><h2>Module contents<a class="headerlink" href="#module-env" title="Permalink to this headline">¶</a></h2> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/env.simple_intersection.html b/documentation/sphinx/.build/.doc/env.simple_intersection.html new file mode 100644 index 0000000000000000000000000000000000000000..61459cf480d757d891957fbab6ae64b4b9808638 --- /dev/null +++ b/documentation/sphinx/.build/.doc/env.simple_intersection.html @@ -0,0 +1,1245 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>env.simple_intersection package — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>env.simple_intersection package</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="env-simple-intersection-package"> +<h1>env.simple_intersection package<a class="headerlink" href="#env-simple-intersection-package" title="Permalink to this headline">¶</a></h1> +<div class="section" id="submodules"> +<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="module-env.simple_intersection.constants"> +<span id="env-simple-intersection-constants-module"></span><h2>env.simple_intersection.constants module<a class="headerlink" href="#module-env.simple_intersection.constants" title="Permalink to this headline">¶</a></h2> +<dl class="data"> +<dt id="env.simple_intersection.constants.DT"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">DT</code><em class="property"> = 0.1</em><a class="headerlink" href="#env.simple_intersection.constants.DT" title="Permalink to this definition">¶</a></dt> +<dd><p>the time difference btw. the current and the next time steps.</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.DT_over_2"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">DT_over_2</code><em class="property"> = 0.05</em><a class="headerlink" href="#env.simple_intersection.constants.DT_over_2" title="Permalink to this definition">¶</a></dt> +<dd><p>Constants for state-constrained Runge-Kutta 4 method in vehicles.py</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.EGO_INDEX"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">EGO_INDEX</code><em class="property"> = 0</em><a class="headerlink" href="#env.simple_intersection.constants.EGO_INDEX" title="Permalink to this definition">¶</a></dt> +<dd><p>Index of the ego vehicle in the vehicles list</p> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.constants.H_CAR_SCALE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">H_CAR_SCALE</code><span class="sig-paren">(</span><em>w</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.constants.H_CAR_SCALE" title="Permalink to this definition">¶</a></dt> +<dd><p>Lambda function that takes in car width and returns scale_x for car</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.H_SPACE_SCALE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">H_SPACE_SCALE</code><em class="property"> = 5.565217391304348</em><a class="headerlink" href="#env.simple_intersection.constants.H_SPACE_SCALE" title="Permalink to this definition">¶</a></dt> +<dd><p>Horizontal space scale</p> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.constants.H_TILE_SCALE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">H_TILE_SCALE</code><span class="sig-paren">(</span><em>w</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.constants.H_TILE_SCALE" title="Permalink to this definition">¶</a></dt> +<dd><p>Lambda function that takes in tile width and returns scale_x for road tile</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.LANE_SEPARATOR_HALF_WIDTH"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">LANE_SEPARATOR_HALF_WIDTH</code><em class="property"> = 1</em><a class="headerlink" href="#env.simple_intersection.constants.LANE_SEPARATOR_HALF_WIDTH" title="Permalink to this definition">¶</a></dt> +<dd><p>Lane separator width</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.LANE_WIDTH"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">LANE_WIDTH</code><em class="property"> = 22.772727272727273</em><a class="headerlink" href="#env.simple_intersection.constants.LANE_WIDTH" title="Permalink to this definition">¶</a></dt> +<dd><p>Lane width</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.MAX_ACCELERATION"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">MAX_ACCELERATION</code><em class="property"> = 2.0</em><a class="headerlink" href="#env.simple_intersection.constants.MAX_ACCELERATION" title="Permalink to this definition">¶</a></dt> +<dd><p>maximum acceleration</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.MAX_NUM_VEHICLES"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">MAX_NUM_VEHICLES</code><em class="property"> = 6</em><a class="headerlink" href="#env.simple_intersection.constants.MAX_NUM_VEHICLES" title="Permalink to this definition">¶</a></dt> +<dd><p>MAX NUMBER OF VEHICLES</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.MAX_STEERING_ANGLE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">MAX_STEERING_ANGLE</code><em class="property"> = 0.9599310885968813</em><a class="headerlink" href="#env.simple_intersection.constants.MAX_STEERING_ANGLE" title="Permalink to this definition">¶</a></dt> +<dd><p><em>maximum steering angle - 33 deg. (extreme case</em> – 53 deg.)</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.MAX_STEERING_ANGLE_RATE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">MAX_STEERING_ANGLE_RATE</code><em class="property"> = 1.0</em><a class="headerlink" href="#env.simple_intersection.constants.MAX_STEERING_ANGLE_RATE" title="Permalink to this definition">¶</a></dt> +<dd><p>maximum rate of change of steering angle</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.NUM_HPIXELS"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">NUM_HPIXELS</code><em class="property"> = 640</em><a class="headerlink" href="#env.simple_intersection.constants.NUM_HPIXELS" title="Permalink to this definition">¶</a></dt> +<dd><p>Number of pixels in the horizontal direction</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.NUM_HTILES"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">NUM_HTILES</code><em class="property"> = 14</em><a class="headerlink" href="#env.simple_intersection.constants.NUM_HTILES" title="Permalink to this definition">¶</a></dt> +<dd><p>Number of horizontal tiles</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.NUM_VPIXELS"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">NUM_VPIXELS</code><em class="property"> = 501</em><a class="headerlink" href="#env.simple_intersection.constants.NUM_VPIXELS" title="Permalink to this definition">¶</a></dt> +<dd><p>Number of pixels in the vertical direction</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.NUM_VTILES"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">NUM_VTILES</code><em class="property"> = 11</em><a class="headerlink" href="#env.simple_intersection.constants.NUM_VTILES" title="Permalink to this definition">¶</a></dt> +<dd><p>Number of horizontal tiles</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.ROAD_TILE_IMAGE_DIM"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">ROAD_TILE_IMAGE_DIM</code><em class="property"> = 300</em><a class="headerlink" href="#env.simple_intersection.constants.ROAD_TILE_IMAGE_DIM" title="Permalink to this definition">¶</a></dt> +<dd><p>Road tile image dimension</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.VEHICLE_WHEEL_BASE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">VEHICLE_WHEEL_BASE</code><em class="property"> = 1.7</em><a class="headerlink" href="#env.simple_intersection.constants.VEHICLE_WHEEL_BASE" title="Permalink to this definition">¶</a></dt> +<dd><p>vehicle wheel base ( = L in the paper)</p> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.constants.V_CAR_SCALE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">V_CAR_SCALE</code><span class="sig-paren">(</span><em>h</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.constants.V_CAR_SCALE" title="Permalink to this definition">¶</a></dt> +<dd><p>Lambda function that takes in car height and returns scale_y for car</p> +</dd></dl> + +<dl class="data"> +<dt id="env.simple_intersection.constants.V_SPACE_SCALE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">V_SPACE_SCALE</code><em class="property"> = 5.566666666666666</em><a class="headerlink" href="#env.simple_intersection.constants.V_SPACE_SCALE" title="Permalink to this definition">¶</a></dt> +<dd><p>Vertical space scale</p> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.constants.V_TILE_SCALE"> +<code class="descclassname">env.simple_intersection.constants.</code><code class="descname">V_TILE_SCALE</code><span class="sig-paren">(</span><em>h</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.constants.V_TILE_SCALE" title="Permalink to this definition">¶</a></dt> +<dd><p>Lambda function that takes in tile height and returns scale_y for road tile</p> +</dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection.features"> +<span id="env-simple-intersection-features-module"></span><h2>env.simple_intersection.features module<a class="headerlink" href="#module-env.simple_intersection.features" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.simple_intersection.features.Features"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.features.</code><code class="descname">Features</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.features.Features" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<dl class="method"> +<dt id="env.simple_intersection.features.Features.get_features_tuple"> +<code class="descname">get_features_tuple</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.features.Features.get_features_tuple" title="Permalink to this definition">¶</a></dt> +<dd><p>continuous + discrete features</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.features.Features.reset"> +<code class="descname">reset</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.features.Features.reset" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="env.simple_intersection.features.OtherVehFeatures"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.features.</code><code class="descname">OtherVehFeatures</code><span class="sig-paren">(</span><em>rel_x</em>, <em>rel_y</em>, <em>v</em>, <em>acc</em>, <em>waited_time</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.features.OtherVehFeatures" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.features.extract_ego_features"> +<code class="descclassname">env.simple_intersection.features.</code><code class="descname">extract_ego_features</code><span class="sig-paren">(</span><em>features_tuple</em>, <em>*args</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.features.extract_ego_features" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.features.extract_other_veh_features"> +<code class="descclassname">env.simple_intersection.features.</code><code class="descname">extract_other_veh_features</code><span class="sig-paren">(</span><em>features_tuple</em>, <em>veh_index</em>, <em>*args</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.features.extract_other_veh_features" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection.road_geokinemetry"> +<span id="env-simple-intersection-road-geokinemetry-module"></span><h2>env.simple_intersection.road_geokinemetry module<a class="headerlink" href="#module-env.simple_intersection.road_geokinemetry" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.simple_intersection.road_geokinemetry.Route"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.road_geokinemetry.</code><code class="descname">Route</code><span class="sig-paren">(</span><em>direction</em>, <em>n_lanes</em>, <em>start_pos</em>, <em>end_pos</em>, <em>width</em>, <em>centres</em>, <em>stop_region</em>, <em>near_stop_region</em>, <em>sidewalks</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.road_geokinemetry.Route" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>A class that contains the lane(s) information for each route (‘h’ for +horizontal or ‘v’ for vertical).</p> +<p>The current implementation is tested when the number of lanes is “2â€.</p> +<dl class="docutils"> +<dt>Properties:</dt> +<dd><ul class="first last simple"> +<li>direction: ‘h’ for hlanes or ‘v’ for vlanes</li> +<li>n_lanes: the number of lanes (has to be multiples of 2)</li> +<li>start_pos: the position that the route starts</li> +<li>end_pos: the position that the route ends</li> +<li>min_pos: the minimum value of the position on the route</li> +<li>max_pos: the maximum value of the position on the route</li> +<li>middle_pos: the center value of the position on the route</li> +<li>length: the length of the route</li> +<li>width: the width of each lane</li> +<li>centres: an array containing each lane’s center point</li> +<li>stop_region: an array defining the stop region on the route</li> +<li><dl class="first docutils"> +<dt>near_stop_region: the position before stop_region[1] defining</dt> +<dd>the region near the stop region</dd> +</dl> +</li> +<li>stop_region_centre: the center position of the stop region</li> +<li>sidewalks: the side walk points of the route</li> +<li>total_width: the width of the route</li> +<li>total_centre: the center of the route</li> +</ul> +</dd> +</dl> +<dl class="attribute"> +<dt id="env.simple_intersection.road_geokinemetry.Route.pos_range"> +<code class="descname">pos_range</code><a class="headerlink" href="#env.simple_intersection.road_geokinemetry.Route.pos_range" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection.road_networks"> +<span id="env-simple-intersection-road-networks-module"></span><h2>env.simple_intersection.road_networks module<a class="headerlink" href="#module-env.simple_intersection.road_networks" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.simple_intersection.road_networks.RoadNetworkCross"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.road_networks.</code><code class="descname">RoadNetworkCross</code><span class="sig-paren">(</span><em>image_url</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.road_networks.RoadNetworkCross" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#env.simple_intersection.shapes.Shape" title="env.simple_intersection.shapes.Shape"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.simple_intersection.shapes.Shape</span></code></a></p> +<p>Road network for the cross scenario.</p> +<p>This scenario has just one horizontal lane and one vertical lane. +Relevant constants are used from the constants file.</p> +<dl class="method"> +<dt id="env.simple_intersection.road_networks.RoadNetworkCross.draw"> +<code class="descname">draw</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.road_networks.RoadNetworkCross.draw" title="Permalink to this definition">¶</a></dt> +<dd><p>Draw the horizontal and vertical lane.</p> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection.shapes"> +<span id="env-simple-intersection-shapes-module"></span><h2>env.simple_intersection.shapes module<a class="headerlink" href="#module-env.simple_intersection.shapes" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.simple_intersection.shapes.Image"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.shapes.</code><code class="descname">Image</code><span class="sig-paren">(</span><em>image_url</em>, <em>anchor=None</em>, <em>tile_scale=False</em>, <em>image_type=None</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.shapes.Image" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#env.simple_intersection.shapes.Shape" title="env.simple_intersection.shapes.Shape"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.simple_intersection.shapes.Shape</span></code></a></p> +<p>Holds an image.</p> +<dl class="method"> +<dt id="env.simple_intersection.shapes.Image.draw"> +<code class="descname">draw</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.shapes.Image.draw" title="Permalink to this definition">¶</a></dt> +<dd><p>Draw Image object.</p> +</dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="env.simple_intersection.shapes.Rectangle"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.shapes.</code><code class="descname">Rectangle</code><span class="sig-paren">(</span><em>xmin</em>, <em>xmax</em>, <em>ymin</em>, <em>ymax</em>, <em>color=(0</em>, <em>0</em>, <em>0</em>, <em>255)</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.shapes.Rectangle" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#env.simple_intersection.shapes.Shape" title="env.simple_intersection.shapes.Shape"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.simple_intersection.shapes.Shape</span></code></a></p> +<p>Rectangle using OpenGL.</p> +<dl class="method"> +<dt id="env.simple_intersection.shapes.Rectangle.draw"> +<code class="descname">draw</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.shapes.Rectangle.draw" title="Permalink to this definition">¶</a></dt> +<dd><p>Draw Rectangle object using OpenGL.</p> +</dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="env.simple_intersection.shapes.Shape"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.shapes.</code><code class="descname">Shape</code><a class="headerlink" href="#env.simple_intersection.shapes.Shape" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>Shape abstract class.</p> +</dd></dl> + +<dl class="class"> +<dt id="env.simple_intersection.shapes.Text"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.shapes.</code><code class="descname">Text</code><span class="sig-paren">(</span><em>text</em>, <em>x</em>, <em>y</em>, <em>font_size=12</em>, <em>color=(0</em>, <em>0</em>, <em>0</em>, <em>255)</em>, <em>multiline=False</em>, <em>width=None</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.shapes.Text" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#env.simple_intersection.shapes.Shape" title="env.simple_intersection.shapes.Shape"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.simple_intersection.shapes.Shape</span></code></a></p> +<p>Holds a pyglet label.</p> +<dl class="method"> +<dt id="env.simple_intersection.shapes.Text.draw"> +<code class="descname">draw</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.shapes.Text.draw" title="Permalink to this definition">¶</a></dt> +<dd><p>Draw Text object.</p> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection.simple_intersection_env"> +<span id="env-simple-intersection-simple-intersection-env-module"></span><h2>env.simple_intersection.simple_intersection_env module<a class="headerlink" href="#module-env.simple_intersection.simple_intersection_env" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.simple_intersection_env.</code><code class="descname">SimpleIntersectionEnv</code><span class="sig-paren">(</span><em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="env.html#env.road_env.RoadEnv" title="env.road_env.RoadEnv"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.road_env.RoadEnv</span></code></a>, <a class="reference internal" href="env.html#env.env_base.EpisodicEnvBase" title="env.env_base.EpisodicEnvBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.env_base.EpisodicEnvBase</span></code></a></p> +<p>Road environment corresponding to the cross scenario.</p> +<p>This scenario has just one horizontal lane and one vertical lane. +Relevant constants are used from the constants file.</p> +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.V2V_ref"> +<code class="descname">V2V_ref</code><em class="property"> = 6.0</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.V2V_ref" title="Permalink to this definition">¶</a></dt> +<dd><p>The vehicle-to-vehicle desired distance in the aggressive driving policy</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.action_space"> +<code class="descname">action_space</code><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.action_space" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.aggressive_driving_policy"> +<code class="descname">aggressive_driving_policy</code><span class="sig-paren">(</span><em>veh_index</em>, <em>maneuver_opt=None</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.aggressive_driving_policy" title="Permalink to this definition">¶</a></dt> +<dd><p>Implementation of the aggressive driving policy. Calculate the +(veh_index)-th vehicle’s low-level action (a, dot_phi) using aggressive +driving policy. If using aggressive driving policy for all vehicles, +there is [has to be] no collision.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>veh_index</strong> – the index of the vehicle to calculate the action +(a, dot_phi) via aggressive driving policy.</li> +<li><strong>maneuver_opt</strong> – an option that specifies a maneuver to be executed; it can +be ‘stop’, ‘wait’, etc.</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">current low-level action (a, dot_phi) generated by the +aggressive driving policy for the current state.</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.check_ego_collision"> +<code class="descname">check_ego_collision</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.check_ego_collision" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks if ego collides with any other vehicle in the environment. +Uses bounding boxes to check if a seperating line exists between given +vehicle and each of the other vehicles.</p> +<p>Returns: True if ego collides with another vehicle, False +otherwise</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.check_other_veh_collisions"> +<code class="descname">check_other_veh_collisions</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.check_other_veh_collisions" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks if other vehicles other than ego collide in the environment. +Uses V2V distance for vehicles in same lane, otherwise uses bounding +boxes Checks all vehicles other than ego.</p> +<p>Returns: True if a vehicle collides with another vehicle, False otherwise</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.collision_happened"> +<code class="descname">collision_happened</code><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.collision_happened" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.copy"> +<code class="descname">copy</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.copy" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost"> +<code class="descname">cost</code><span class="sig-paren">(</span><em>u</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost" title="Permalink to this definition">¶</a></dt> +<dd><dl class="docutils"> +<dt>Calculate the driving cost of the ego, i.e.,</dt> +<dd>the negative reward for the ego-driving.</dd> +</dl> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>u</strong> – the low-level input (a, dot_psi) to the ego vehicle.</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><dl class="docutils"> +<dt>the weighted sum of squares of the components in</dt> +<dd>the vector “vec.†Note that a cost is a negative reward.</dd> +</dl> +</td> +</tr> +<tr class="field-odd field"><th class="field-name">Return type:</th><td class="field-body">cost</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost_normalization_ranges"> +<code class="descname">cost_normalization_ranges</code><em class="property"> = [[-3.5, 3.5], [-6.2, 6.2], [-10.081044753473748, -10.081044753473748], [-12, 12], [0, 12], [-2, 2], [-16, 16], [-2, 2]]</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost_normalization_ranges" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost_weights"> +<code class="descname">cost_weights</code><em class="property"> = (1.0, 0.25, 0.1, 1.0, 100.0, 0.1, 0.25, 0.1)</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost_weights" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.draw"> +<code class="descname">draw</code><span class="sig-paren">(</span><em>info=None</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.draw" title="Permalink to this definition">¶</a></dt> +<dd><p>Draw the background, road network and vehicle network. Also show +information as passed on by info.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>info</strong> – the information string to be shown on the window</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.ego"> +<code class="descname">ego</code><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.ego" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.ego_info_text"> +<code class="descname">ego_info_text</code><em class="property"> = None</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.ego_info_text" title="Permalink to this definition">¶</a></dt> +<dd><p>info for displaying on top of ego</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.generate_scenario"> +<code class="descname">generate_scenario</code><span class="sig-paren">(</span><em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.generate_scenario" title="Permalink to this definition">¶</a></dt> +<dd><p>Randomly generate a road scenario with</p> +<blockquote> +<div>“the N-number of vehicles + an ego vehicleâ€</div></blockquote> +<p>(n_others_range[0] <= N <= n_others_range[1]), +all of whose speeds are also set randomly (or deterministically depending +on the options) between 0 and the speed limit of the road environment. +The position and speed of the vehicles are set (some of them randomly) but +not in a way that causes inevitable collision or violation. The ego vehicle is +always posed on a horizontal lane and there is initially no or only one +vehicle posed in the intersection.</p> +<p>TODO: More debugging +TODO: Add more comments for each block within the function for comprehensive understanding. +TODO: restructure the code by making private method for each part for a certain option.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple"> +<li><strong>n_others_range</strong> – a tuple (n1, n2), which gives the range of the vehicles +on the road, excluding the ego vehicle, by n1 <= N <= n2.</li> +<li><strong>ego_pos_range</strong> – a tuple or list (x1, x2); the ego’s x-position +will be sampled uniformly in [x1, x2].</li> +<li><strong>ego_v_upper_lim</strong> – the ego’s velocity limit. the ego’s speed +will be sampled uniformly in [0, ego_v_upper_lim]</li> +<li><strong>ego_lane</strong> – the lane in which ego will be initialized</li> +<li><strong>ego_perturb_lim</strong> – <p>a tuple (da, dtheta), where da is the absolute maximum +of the ego’s initial perturbations along the y-axis from the lane +centre; dtheta is the absolute maximum of the ego’s heading angle +perturbation from the horizontal line (the angle parallel to the +horizontal lane). The perturbation along the y-axis is +sampled from</p> +<blockquote> +<div>â€uniform(-ego_perturb_lim[0], ego_perturb_lim[0])â€</div></blockquote> +<p>within the lane boundary. Similarly, the perturbation of the +heading angle is sampled from</p> +<blockquote> +<div>â€uniform(-ego_perturb_lim[1], ego_perturb_lim[1]).â€</div></blockquote> +<p>da is restricted by the width of the road, and dtheta the non- +holonomic constraint;</p> +</li> +<li><strong>ego_heading_towards_lane_centre</strong> – If True, then the ego’s heading angle is +always initialized towards the lane centre.</li> +<li><strong>others_h_pos_range</strong> – the range of the other vehicles that are on the +horizontal route and are not corresponding to the vehicle +generated by the code for a special scenario below.</li> +<li><strong>others_v_pos_range</strong> – the range of the other vehicles that are on the +vertical route and initially not stopped in the stop region.</li> +<li><strong>n_others_stopped_in_stop_region</strong> – the number of the other vehicles +that stopped in the stop region, on the other lanes than that +of the ego. The maximum is 3 (as there are 4-lanes including +ego’s). When this is true, the waited_count of the stopped cars +(except the ego) in the stop region will be set randomly. This +option is useful when generating an initial scenario for Wait +maneuver.</li> +<li><strong>veh_ahead_scenario</strong> – if True, the generated scenario has a vehicle +ahead of the ego within self.veh_ahead_max. This option is useful +in generating an initial scenario for e.g., Follow and Pass.</li> +<li><strong>stopped_car_scenario</strong> – if True, the generated scenario contains a +stopped car located after the intersection but in the same lane as +ego’s TODO: this option is not fully tested and need some debugging.</li> +<li><strong>allow_vehicles_in_ego_lane</strong> – if False, there will be no vehicle in the +same lane to the ego’s. This option is useful when you generate an +initial scenario like those in Default and Finish maneuvers.</li> +<li><strong>v_max_multiplier</strong> – a constant between 0 and 1, used in resetting the speeds +of the vehicles if necessary to make sure that at least an input to +the ego exists to avoid collisions or stop-sign violations. The less +v_max_multiplier, more conservative scenario is generated (but when +v_max_multipler = 1, it could generate a scenario where a collision +is inevitable). 0.9 is a value set by the developer through trial-and- +error and exhaustive testing.</li> +<li><strong>randomize_special_scenarios</strong> – If True, randomizes scenarios such as vehicle_ahead_scenario, +stopped_car_scenario and n_others_stopped_in_stop_region</li> +</ul> +</td> +</tr> +</tbody> +</table> +<dl class="docutils"> +<dt>:returns</dt> +<dd>False if the initial state is Terminal, True if not.</dd> +</dl> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.get_V2V_distance"> +<code class="descname">get_V2V_distance</code><span class="sig-paren">(</span><em>veh_index=0</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.get_V2V_distance" title="Permalink to this definition">¶</a></dt> +<dd><p>Calculate the distance between the target and the nearest adjacent +car in the same lane. The distance is given as a bumper-to-bumper one, +so being it not positive means that the two cars collide.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>veh_index</strong> – <p>the index of the vehicle whose V2V distance is +returned, ranging from 0 to len(self.vehs)</p> +<blockquote> +<div>(with 0 for the index of the ego).</div></blockquote> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">a tuple (i, V2Vdist), where V2Vdist is the V2V distance +from the indexed vehicle to the closest vehicle, with its index i, +on the same route; i is None and V2Vdist == np.infty +when there is no vehicle ahead.</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.get_features_tuple"> +<code class="descname">get_features_tuple</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.get_features_tuple" title="Permalink to this definition">¶</a></dt> +<dd><p>Get/calculate the features wrt. the current state variables</p> +<p>Returns features tuple</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.goal_achieved"> +<code class="descname">goal_achieved</code><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.goal_achieved" title="Permalink to this definition">¶</a></dt> +<dd><p>A property from the base class which is True if the goal +of the road scenario is achieved, otherwise False. This property is +used in both step of EpisodicEnvBase and the implementation of +the high-level reinforcement learning and execution.</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.init_APs"> +<code class="descname">init_APs</code><span class="sig-paren">(</span><em>update_local_APs=True</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.init_APs" title="Permalink to this definition">¶</a></dt> +<dd><p>Initialize the global (and local if update_local_APs is true) atomic +propositions (APs) of each vehicle using the current state. This method +is basically called by “generate_scenario†method. Compared with +update_APs, the way of setting ‘highest_priority’ is different.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>update_local_APs</strong> – True if the local APs are also necessary to +be initialized; False if not, and only the global APs are +required to be initialzied.</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.is_ego_off_road"> +<code class="descname">is_ego_off_road</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.is_ego_off_road" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks if ego goes off-road.</p> +<p>Returns: True if ego goes off-road, False otherwise</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.is_terminal"> +<code class="descname">is_terminal</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.is_terminal" title="Permalink to this definition">¶</a></dt> +<dd><p>Check if the environment is at a terminal state or not.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>env</strong> – environment instance</td> +</tr> +</tbody> +</table> +<p>Returns True if the environment has terminated</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.max_ego_theta"> +<code class="descname">max_ego_theta</code><em class="property"> = 1.0471975511965976</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.max_ego_theta" title="Permalink to this definition">¶</a></dt> +<dd><p>the maximum of the ego’s heading angle</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.n_other_vehs"> +<code class="descname">n_other_vehs</code><em class="property"> = None</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.n_other_vehs" title="Permalink to this definition">¶</a></dt> +<dd><p>the number of the other vehicles, initialized in generate_scenario</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.normalize_cost"> +<code class="descname">normalize_cost</code><em class="property"> = False</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.normalize_cost" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.normalize_tuple"> +<code class="descname">normalize_tuple</code><span class="sig-paren">(</span><em>vec</em>, <em>scale_factor=10</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.normalize_tuple" title="Permalink to this definition">¶</a></dt> +<dd><p>Normalizes each element in a tuple according to ranges defined in self.cost_normalization_ranges. +Normalizes between 0 and 1. And the scales by scale_factor</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>vec</strong> – The tuple to be normalized</li> +<li><strong>scale_factor</strong> – the scaling factor to multiply the normalized values by</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">The normalized tuple</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.observation_space"> +<code class="descname">observation_space</code><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.observation_space" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.render"> +<code class="descname">render</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.render" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant render function.</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.reset"> +<code class="descname">reset</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.reset" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant reset function.</p> +<p>Reinitialize this environment with whatever parameters it was initially +called with.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Returns:</th><td class="field-body">the environment state after reset</td> +</tr> +<tr class="field-even field"><th class="field-name">Return type:</th><td class="field-body">new_state</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.set_ego_info_text"> +<code class="descname">set_ego_info_text</code><span class="sig-paren">(</span><em>info</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.set_ego_info_text" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.step"> +<code class="descname">step</code><span class="sig-paren">(</span><em>u_ego</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.step" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant step function.</p> +<p>Calculate the next continuous and discrete states of every vehicle +using the given action u_ego for ego-vehicle and aggressive driving +policy for the other vehicles. The variables in self.vehs will be +automatically updated. Then, call the options _step and get the reward +and terminal values.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>u_ego</strong> – the low level action [a, dot_phi] of the ego vehicle.</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">the new state of the environment +R: reward obtained +terminal: whether or not the current policy finished, that is, +its termination_condition() is satisfied; TODO - also return +true when the environment’s state indicates the episode is +over. +info: information variables</td> +</tr> +<tr class="field-odd field"><th class="field-name">Return type:</th><td class="field-body">new_state</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.termination_condition"> +<code class="descname">termination_condition</code><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.termination_condition" title="Permalink to this definition">¶</a></dt> +<dd><p>In the subclass, specify the condition for termination of the episode +(or the maneuver).</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.update_APs"> +<code class="descname">update_APs</code><span class="sig-paren">(</span><em>update_local_APs=True</em>, <em>update_highest_priority=True</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.update_APs" title="Permalink to this definition">¶</a></dt> +<dd><p>Update the global (and local if update_local_APs is true) atomic +propositions (APs) of each vehicle using the current state. This method +is basically called by “step†method below after it updates the +vehicle’s continuous state. By a global AP, it means that the state +information of the other cars has to be used to update the AP (whereas +a local AP means that the information of the other cars are not +necessary). For comparison and more details, see also “updateLocalAPs†+method in vehicles module.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>update_local_APs</strong> – True if the local APs are also necessary to +be update; False if not, and only the global APs are required +to be updated.</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.veh_ahead_max"> +<code class="descname">veh_ahead_max</code><em class="property"> = 40.0</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.veh_ahead_max" title="Permalink to this definition">¶</a></dt> +<dd><p>The maximum distance within which self.vehs[i].APs[‘veh_ahead’] = True</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.veh_ahead_min"> +<code class="descname">veh_ahead_min</code><em class="property"> = 2.5</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.veh_ahead_min" title="Permalink to this definition">¶</a></dt> +<dd><p>The minimum distance that every two adjacent vehicles has to be apart from each other.</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.vehicle_network"> +<code class="descname">vehicle_network</code><em class="property"> = None</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.vehicle_network" title="Permalink to this definition">¶</a></dt> +<dd><p>the vehicle_nework for render, initialized in generate_scenario</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.vehs"> +<code class="descname">vehs</code><em class="property"> = None</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.vehs" title="Permalink to this definition">¶</a></dt> +<dd><p>the list of the vehicles, initialized in generate_scenario</p> +</dd></dl> + +<dl class="attribute"> +<dt id="env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.window"> +<code class="descname">window</code><em class="property"> = None</em><a class="headerlink" href="#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.window" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection.utilities"> +<span id="env-simple-intersection-utilities-module"></span><h2>env.simple_intersection.utilities module<a class="headerlink" href="#module-env.simple_intersection.utilities" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.simple_intersection.utilities.BoundingBox"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.utilities.</code><code class="descname">BoundingBox</code><a class="headerlink" href="#env.simple_intersection.utilities.BoundingBox" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>A class that provides utility functions related to bounding boxes.</p> +<ul class="simple"> +<li><dl class="first docutils"> +<dt>Bounding box: ndarray of shape (4,2) containing the vertices of the</dt> +<dd>rectangle in order</dd> +</dl> +</li> +</ul> +<dl class="staticmethod"> +<dt id="env.simple_intersection.utilities.BoundingBox.all_same_sign_in_list"> +<em class="property">static </em><code class="descname">all_same_sign_in_list</code><span class="sig-paren">(</span><em>test_list</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.BoundingBox.all_same_sign_in_list" title="Permalink to this definition">¶</a></dt> +<dd><p>Check if all elements in a list are of the same sign. Zero does not +have a sign.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>test_list</strong> – the python list to be checked</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">1 or -1 depending upon the side w.r.t the edge</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="staticmethod"> +<dt id="env.simple_intersection.utilities.BoundingBox.does_bounding_box_cross_line"> +<em class="property">static </em><code class="descname">does_bounding_box_cross_line</code><span class="sig-paren">(</span><em>line</em>, <em>bb</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.BoundingBox.does_bounding_box_cross_line" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks if bounding box crosses a line. Line is represented by an +np.ndarray of size (2,2) representing two points in it. Works only for +quadrilateral bounding boxes (in 2D).</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>line</strong> – np.ndarray Two points representing the line</li> +<li><strong>bb</strong> – np.ndarray Bounding box</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">true if the bounding box crosses the line</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="staticmethod"> +<dt id="env.simple_intersection.utilities.BoundingBox.does_bounding_box_intersect"> +<em class="property">static </em><code class="descname">does_bounding_box_intersect</code><span class="sig-paren">(</span><em>first_bb</em>, <em>second_bb</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.BoundingBox.does_bounding_box_intersect" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks if bounding boxes intersect using separating axis test: Two +objects don’t intersect if you can find a line that separates the two +objects. Works only for quadrilateral bounding boxes (in 2D).</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>first_bb</strong> – np.ndarray First bounding box</li> +<li><strong>second_bb</strong> – np.ndarray Second bounding box</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">true if there is an intersection</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="staticmethod"> +<dt id="env.simple_intersection.utilities.BoundingBox.localize_bounding_box_wrt_line"> +<em class="property">static </em><code class="descname">localize_bounding_box_wrt_line</code><span class="sig-paren">(</span><em>line</em>, <em>bb</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.BoundingBox.localize_bounding_box_wrt_line" title="Permalink to this definition">¶</a></dt> +<dd><p>Returns the side in which a bounding box is w.r.t a line. Line is +represented by an np.ndarray of size (2,2) representing two points in +it. Works only for quadrilateral bounding boxes (in 2D).</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>line</strong> – np.ndarray Two points representing the line</li> +<li><strong>bb</strong> – np.ndarray Bounding box</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">1 or -1 depending upon the side w.r.t the line. returns 0 if it +intersects the line</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="staticmethod"> +<dt id="env.simple_intersection.utilities.BoundingBox.localize_point_wrt_line"> +<em class="property">static </em><code class="descname">localize_point_wrt_line</code><span class="sig-paren">(</span><em>line</em>, <em>testpoint</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.BoundingBox.localize_point_wrt_line" title="Permalink to this definition">¶</a></dt> +<dd><p>Check the side in which a point lies w.r.t a line.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>line</strong> – np.ndarray Two points representing the line</li> +<li><strong>testpoint</strong> – the point to be checked</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">1 or -1 depending upon the side w.r.t the edge; +returns 0 if it is on the line</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.utilities.calculate_s"> +<code class="descclassname">env.simple_intersection.utilities.</code><code class="descname">calculate_s</code><span class="sig-paren">(</span><em>v</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.calculate_s" title="Permalink to this definition">¶</a></dt> +<dd><dl class="docutils"> +<dt>Calculate the distance traveling when the vehicle is maximally</dt> +<dd>de-accelerating for a complete stop.</dd> +</dl> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>v</strong> – the current speed of the vehicle.</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">the distance traveling when the vehicle is under the maximum +de-acceleration to stop completely.</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.utilities.calculate_v_max"> +<code class="descclassname">env.simple_intersection.utilities.</code><code class="descname">calculate_v_max</code><span class="sig-paren">(</span><em>dist</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.calculate_v_max" title="Permalink to this definition">¶</a></dt> +<dd><p>Calculate the maximum velocity you can reach at the given position ahead.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>dist</strong> – the distance you travel from the current position.</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">the maximum reachable velocity.</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.utilities.config_Pyglet"> +<code class="descclassname">env.simple_intersection.utilities.</code><code class="descname">config_Pyglet</code><span class="sig-paren">(</span><em>pyglet</em>, <em>win_x</em>, <em>win_y</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.config_Pyglet" title="Permalink to this definition">¶</a></dt> +<dd><p>Configure pyglet and return the window that can be used by other pyglet +objects.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>win_x</strong> – x width of the window</li> +<li><strong>win_y</strong> – y width of the window</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">Pyglet window object</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.utilities.draw_all_shapes"> +<code class="descclassname">env.simple_intersection.utilities.</code><code class="descname">draw_all_shapes</code><span class="sig-paren">(</span><em>shapes</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.draw_all_shapes" title="Permalink to this definition">¶</a></dt> +<dd><p>Go through all the shapes and call their draw function.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>shapes</strong> – list of shapes</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.utilities.get_APs"> +<code class="descclassname">env.simple_intersection.utilities.</code><code class="descname">get_APs</code><span class="sig-paren">(</span><em>env</em>, <em>index</em>, <em>*args</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.get_APs" title="Permalink to this definition">¶</a></dt> +<dd><p>Retrieve atomic proposition data from the env.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>env</strong> – SimpleIntersectionEnv object</li> +<li><strong>index</strong> – vehicle index</li> +<li><strong>args</strong> – atomic proposition names (variable arguments)</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">multiline string with the required data</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.utilities.get_veh_attributes"> +<code class="descclassname">env.simple_intersection.utilities.</code><code class="descname">get_veh_attributes</code><span class="sig-paren">(</span><em>env</em>, <em>index</em>, <em>*args</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.get_veh_attributes" title="Permalink to this definition">¶</a></dt> +<dd><p>Retrieve vehicle attributes from env.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>env</strong> – SimpleIntersectionEnv object</li> +<li><strong>index</strong> – vehicle index</li> +<li><strong>args</strong> – atomic proposition names (variable arguments)</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">multiline string with the required data</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="function"> +<dt id="env.simple_intersection.utilities.road2image"> +<code class="descclassname">env.simple_intersection.utilities.</code><code class="descname">road2image</code><span class="sig-paren">(</span><em>pos</em>, <em>which_dir</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.utilities.road2image" title="Permalink to this definition">¶</a></dt> +<dd><p>Transform a 1D point to the 1D point in the graphics coordinate for the +same direction (‘h’ or ‘v’).</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first simple"> +<li><strong>pos</strong> – 1D position in x or y-axis of the road coordinate system</li> +<li><strong>which_dir</strong> – the direction of the coordinate. It has to be either +horizontal (‘h’) or vertical (‘v’).</li> +</ul> +</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body"><p class="first last">the corresponding 1D position in the graphics coordinate.</p> +</td> +</tr> +</tbody> +</table> +</dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection.vehicle_networks"> +<span id="env-simple-intersection-vehicle-networks-module"></span><h2>env.simple_intersection.vehicle_networks module<a class="headerlink" href="#module-env.simple_intersection.vehicle_networks" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.simple_intersection.vehicle_networks.VehicleNetworkCross"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.vehicle_networks.</code><code class="descname">VehicleNetworkCross</code><span class="sig-paren">(</span><em>image_url</em>, <em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicle_networks.VehicleNetworkCross" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#env.simple_intersection.shapes.Shape" title="env.simple_intersection.shapes.Shape"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.simple_intersection.shapes.Shape</span></code></a></p> +<p>Vehicle network for the cross scenario.</p> +<p>This scenario has just one horizontal lane and one vertical lane. +Relevant constants are used from the constants file.</p> +<dl class="method"> +<dt id="env.simple_intersection.vehicle_networks.VehicleNetworkCross.draw"> +<code class="descname">draw</code><span class="sig-paren">(</span><em>ego_info_text</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicle_networks.VehicleNetworkCross.draw" title="Permalink to this definition">¶</a></dt> +<dd><p>Draw the cars. +TODO: add the code for drawing the lines on the road, e.g.,:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">:</span><span class="n">param</span> <span class="n">ego_info</span><span class="p">:</span> <span class="n">_text</span><span class="p">:</span> <span class="n">the</span> <span class="n">text</span> <span class="n">to</span> <span class="n">be</span> <span class="n">displayed</span> <span class="n">above</span> <span class="n">ego</span> +</pre></div> +</div> +<blockquote> +<div>pyglet.graphics.draw(2, pyglet.gl.GL_LINES, (“v2fâ€, (0, 320, 640, 320)))</div></blockquote> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection.vehicles"> +<span id="env-simple-intersection-vehicles-module"></span><h2>env.simple_intersection.vehicles module<a class="headerlink" href="#module-env.simple_intersection.vehicles" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="env.simple_intersection.vehicles.Vehicle"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.vehicles.</code><code class="descname">Vehicle</code><span class="sig-paren">(</span><em>which_dir</em>, <em>lane=None</em>, <em>v_upper_lim=11.176</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.Vehicle" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#env.simple_intersection.vehicles.VehicleState" title="env.simple_intersection.vehicles.VehicleState"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.simple_intersection.vehicles.VehicleState</span></code></a></p> +<p>A vehicle class that inherits VehicleState (so, contains the +(continuous) state info.), and also have discrete state variables. (i.e., +atomic propositions (APs)).</p> +<dl class="docutils"> +<dt>Properties are the same as of VehicleState +</dt> +<dd><ul class="first last simple"> +<li><dl class="first docutils"> +<dt>APs: the class AtomicPropositions that stores all the APs</dt> +<dd>of the vehicle as True or False.</dd> +</dl> +</li> +<li><dl class="first docutils"> +<dt>waited_count: the number of time steps the vehicle stays</dt> +<dd>in the stop region; it is -1 when the car is not in the stop region;</dd> +</dl> +</li> +</ul> +</dd> +</dl> +<dl class="method"> +<dt id="env.simple_intersection.vehicles.Vehicle.init_local_discrete_var"> +<code class="descname">init_local_discrete_var</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.Vehicle.init_local_discrete_var" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.vehicles.Vehicle.is_within_road_boundaries"> +<code class="descname">is_within_road_boundaries</code><span class="sig-paren">(</span><em>route</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.Vehicle.is_within_road_boundaries" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks if this vehicle is within road boundaries given a route.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>route</strong> – route as defined by road_geokinemetry object</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">True if vehicle is within road boundaries, False otherwise</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.vehicles.Vehicle.random_reset"> +<code class="descname">random_reset</code><span class="sig-paren">(</span><em>which_dir</em>, <em>lane=None</em>, <em>v_upper_lim=11.176</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.Vehicle.random_reset" title="Permalink to this definition">¶</a></dt> +<dd><p>Randomly reset the properties of the class including vehicle’s state +variables; the speed is [and the lane number can be] chosen randomly.</p> +<p>The parameters of the method are exactly same as those in the +constructor.</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.vehicles.Vehicle.reset"> +<code class="descname">reset</code><span class="sig-paren">(</span><em>which_dir</em>, <em>lane</em>, <em>pos_in_lane</em>, <em>v</em>, <em>psi</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.Vehicle.reset" title="Permalink to this definition">¶</a></dt> +<dd><p>Reset the properties of the class including vehicle’s state +variables; this reset method updates all the atomic propositions and +the discrete state (i.e., waited_count).</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.vehicles.Vehicle.step"> +<code class="descname">step</code><span class="sig-paren">(</span><em>u</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.Vehicle.step" title="Permalink to this definition">¶</a></dt> +<dd><p>Calculate the next state and update the other properties for the +given input u. NOTE: the global atomic propositions (‘highest_priority’ +and ‘intersection_is_clear’) are not updated.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>u</strong> – a tuple or an array whose first element corresponds to the +acceleration and the second element corresponds to the rate +of change of the steering angle.</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.vehicles.Vehicle.update_local_APs"> +<code class="descname">update_local_APs</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.Vehicle.update_local_APs" title="Permalink to this definition">¶</a></dt> +<dd><p>Update local atomic propositions (related to the vehicle, road +geometry, and road environment); based upon the continuous and the +previous discrete states, all the atomic propositions within the class +are updated, except the global ones (‘highest_priority’, +‘intersection_is_clear’, and ‘veh_ahead’).</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.vehicles.Vehicle.update_waited_count"> +<code class="descname">update_waited_count</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.Vehicle.update_waited_count" title="Permalink to this definition">¶</a></dt> +<dd><p>Increase waited_count if the vehicle is in the stop region on +the same route; otherwise set waited_count = -1.</p> +</dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="env.simple_intersection.vehicles.VehicleState"> +<em class="property">class </em><code class="descclassname">env.simple_intersection.vehicles.</code><code class="descname">VehicleState</code><span class="sig-paren">(</span><em>which_dir</em>, <em>lane</em>, <em>pos_in_lane</em>, <em>v</em>, <em>psi</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.VehicleState" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>A class that defines the vehicle’s (cont.) state variables and provides +a mean to calculate the next state.</p> +<ul class="simple"> +<li><dl class="first docutils"> +<dt>which_dir: the direction of the vehicle. It has to be either horizontal</dt> +<dd>(‘h’) or vertical (‘v’);</dd> +</dl> +</li> +<li>x, y: the x and y position of the vehicle;</li> +<li>theta: the heading angle of the vehicle;</li> +<li>v: the velocity along the heading angle;</li> +<li>psi: the steering angle;</li> +<li><dl class="first docutils"> +<dt>(acc, psi_dot): the acceleration and the rate of change of the</dt> +<dd>steering angle psi. If u = (u[0], u[1]) in step is in the reasonable +range, this is equal to the previous input u at the previous step.</dd> +</dl> +</li> +<li>method: either ‘Euler’ (Euler method) or ‘RK4’ (Runge-Kutta 4th-order)</li> +</ul> +<dl class="method"> +<dt id="env.simple_intersection.vehicles.VehicleState.get_bounding_box"> +<code class="descname">get_bounding_box</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.VehicleState.get_bounding_box" title="Permalink to this definition">¶</a></dt> +<dd><p>Calculate the bounding box of the vehicle.</p> +<p>Returns: the four points of the bounding box depending on +the vehicle’s pose (x,y,theta)</p> +</dd></dl> + +<dl class="method"> +<dt id="env.simple_intersection.vehicles.VehicleState.step"> +<code class="descname">step</code><span class="sig-paren">(</span><em>u</em><span class="sig-paren">)</span><a class="headerlink" href="#env.simple_intersection.vehicles.VehicleState.step" title="Permalink to this definition">¶</a></dt> +<dd><p>Calculate the next state and update the other properties for the +given input u.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>u</strong> – a tuple or an array whose first element corresponds to the +acceleration and the second element corresponds to the rate +of change of the steering angle.</td> +</tr> +</tbody> +</table> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-env.simple_intersection"> +<span id="module-contents"></span><h2>Module contents<a class="headerlink" href="#module-env.simple_intersection" title="Permalink to this headline">¶</a></h2> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/high_level_policy_main.html b/documentation/sphinx/.build/.doc/high_level_policy_main.html new file mode 100644 index 0000000000000000000000000000000000000000..efbdcf75591a6c1dd33bef89b17142f4f9dd504c --- /dev/null +++ b/documentation/sphinx/.build/.doc/high_level_policy_main.html @@ -0,0 +1,80 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>high_level_policy_main module — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>high_level_policy_main module</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="module-high_level_policy_main"> +<span id="high-level-policy-main-module"></span><h1>high_level_policy_main module<a class="headerlink" href="#module-high_level_policy_main" title="Permalink to this headline">¶</a></h1> +<dl class="function"> +<dt id="high_level_policy_main.evaluate_high_level_policy"> +<code class="descclassname">high_level_policy_main.</code><code class="descname">evaluate_high_level_policy</code><span class="sig-paren">(</span><em>nb_episodes_for_test=100</em>, <em>nb_trials=10</em>, <em>trained_agent_file='highlevel_weights.h5f'</em>, <em>pretrained=False</em>, <em>visualize=False</em><span class="sig-paren">)</span><a class="headerlink" href="#high_level_policy_main.evaluate_high_level_policy" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="function"> +<dt id="high_level_policy_main.find_good_high_level_policy"> +<code class="descclassname">high_level_policy_main.</code><code class="descname">find_good_high_level_policy</code><span class="sig-paren">(</span><em>nb_steps=25000</em>, <em>load_weights=False</em>, <em>nb_episodes_for_test=100</em>, <em>visualize=False</em>, <em>tensorboard=False</em>, <em>save_path='./highlevel_weights.h5f'</em><span class="sig-paren">)</span><a class="headerlink" href="#high_level_policy_main.find_good_high_level_policy" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="function"> +<dt id="high_level_policy_main.high_level_policy_testing"> +<code class="descclassname">high_level_policy_main.</code><code class="descname">high_level_policy_testing</code><span class="sig-paren">(</span><em>nb_episodes_for_test=100</em>, <em>trained_agent_file='highlevel_weights.h5f'</em>, <em>pretrained=False</em>, <em>visualize=True</em><span class="sig-paren">)</span><a class="headerlink" href="#high_level_policy_main.high_level_policy_testing" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="function"> +<dt id="high_level_policy_main.high_level_policy_training"> +<code class="descclassname">high_level_policy_main.</code><code class="descname">high_level_policy_training</code><span class="sig-paren">(</span><em>nb_steps=25000</em>, <em>load_weights=False</em>, <em>training=True</em>, <em>testing=True</em>, <em>nb_episodes_for_test=10</em>, <em>max_nb_steps=100</em>, <em>visualize=False</em>, <em>tensorboard=False</em>, <em>save_path='highlevel_weights.h5f'</em><span class="sig-paren">)</span><a class="headerlink" href="#high_level_policy_main.high_level_policy_training" title="Permalink to this definition">¶</a></dt> +<dd><p>Do RL of the high-level policy and test it. +:param nb_steps: the number of steps to perform RL +:param load_weights: True if the pre-learned NN weights are loaded (for initializations of NNs) +:param training: True to enable training +:param testing: True to enable testing +:param nb_episodes_for_test: the number of episodes for testing</p> +</dd></dl> + +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/low_level_policy_main.html b/documentation/sphinx/.build/.doc/low_level_policy_main.html new file mode 100644 index 0000000000000000000000000000000000000000..5867273e07626f31021a60cb2ed14756236c9fed --- /dev/null +++ b/documentation/sphinx/.build/.doc/low_level_policy_main.html @@ -0,0 +1,73 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>low_level_policy_main module — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>low_level_policy_main module</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="module-low_level_policy_main"> +<span id="low-level-policy-main-module"></span><h1>low_level_policy_main module<a class="headerlink" href="#module-low_level_policy_main" title="Permalink to this headline">¶</a></h1> +<dl class="function"> +<dt id="low_level_policy_main.low_level_policy_testing"> +<code class="descclassname">low_level_policy_main.</code><code class="descname">low_level_policy_testing</code><span class="sig-paren">(</span><em>maneuver</em>, <em>pretrained=False</em>, <em>nb_episodes_for_test=20</em><span class="sig-paren">)</span><a class="headerlink" href="#low_level_policy_main.low_level_policy_testing" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="function"> +<dt id="low_level_policy_main.low_level_policy_training"> +<code class="descclassname">low_level_policy_main.</code><code class="descname">low_level_policy_training</code><span class="sig-paren">(</span><em>maneuver</em>, <em>nb_steps</em>, <em>RL_method='DDPG'</em>, <em>load_weights=False</em>, <em>training=True</em>, <em>testing=True</em>, <em>visualize=False</em>, <em>nb_episodes_for_test=10</em>, <em>tensorboard=False</em><span class="sig-paren">)</span><a class="headerlink" href="#low_level_policy_main.low_level_policy_training" title="Permalink to this definition">¶</a></dt> +<dd><p>Do RL of the low-level policy of the given maneuver and test it. +:param maneuver: the name of the maneuver defined in config.json (e.g., ‘default’). +:param nb_steps: the number of steps to perform RL. +:param RL_method: either DDPG or PPO2. +:param load_weights: True if the pre-learned NN weights are loaded (for initializations of NNs). +:param training: True to enable training. +:param testing: True to enable testing. +:param visualize: True to see the graphical outputs during training. +:param nb_episodes_for_test: the number of episodes for testing.</p> +</dd></dl> + +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/mcts.html b/documentation/sphinx/.build/.doc/mcts.html new file mode 100644 index 0000000000000000000000000000000000000000..4f31cb1bc948bef8ba5fb734f6978771ab48cbc7 --- /dev/null +++ b/documentation/sphinx/.build/.doc/mcts.html @@ -0,0 +1,103 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>mcts module — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>mcts module</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="module-mcts"> +<span id="mcts-module"></span><h1>mcts module<a class="headerlink" href="#module-mcts" title="Permalink to this headline">¶</a></h1> +<dl class="class"> +<dt id="mcts.Logger"> +<em class="property">class </em><code class="descclassname">mcts.</code><code class="descname">Logger</code><a class="headerlink" href="#mcts.Logger" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<dl class="method"> +<dt id="mcts.Logger.flush"> +<code class="descname">flush</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#mcts.Logger.flush" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="mcts.Logger.write"> +<code class="descname">write</code><span class="sig-paren">(</span><em>message</em><span class="sig-paren">)</span><a class="headerlink" href="#mcts.Logger.write" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="function"> +<dt id="mcts.evaluate_online_mcts"> +<code class="descclassname">mcts.</code><code class="descname">evaluate_online_mcts</code><span class="sig-paren">(</span><em>nb_episodes=20</em>, <em>nb_trials=5</em><span class="sig-paren">)</span><a class="headerlink" href="#mcts.evaluate_online_mcts" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="function"> +<dt id="mcts.mcts_evaluation"> +<code class="descclassname">mcts.</code><code class="descname">mcts_evaluation</code><span class="sig-paren">(</span><em>nb_traversals</em>, <em>num_trials=5</em>, <em>visualize=False</em><span class="sig-paren">)</span><a class="headerlink" href="#mcts.mcts_evaluation" title="Permalink to this definition">¶</a></dt> +<dd><p>Do RL of the low-level policy of the given maneuver and test it. +:param nb_traversals: number of MCTS traversals +:param save_every: save at every these many traversals +:param visualize: visualization / rendering</p> +</dd></dl> + +<dl class="function"> +<dt id="mcts.mcts_training"> +<code class="descclassname">mcts.</code><code class="descname">mcts_training</code><span class="sig-paren">(</span><em>nb_traversals</em>, <em>save_every=20</em>, <em>visualize=False</em><span class="sig-paren">)</span><a class="headerlink" href="#mcts.mcts_training" title="Permalink to this definition">¶</a></dt> +<dd><p>Do RL of the low-level policy of the given maneuver and test it. +:param nb_traversals: number of MCTS traversals +:param save_every: save at every these many traversals +:param visualize: visualization / rendering</p> +</dd></dl> + +<dl class="function"> +<dt id="mcts.mcts_visualize"> +<code class="descclassname">mcts.</code><code class="descname">mcts_visualize</code><span class="sig-paren">(</span><em>file_name</em><span class="sig-paren">)</span><a class="headerlink" href="#mcts.mcts_visualize" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="function"> +<dt id="mcts.online_mcts"> +<code class="descclassname">mcts.</code><code class="descname">online_mcts</code><span class="sig-paren">(</span><em>nb_episodes=10</em><span class="sig-paren">)</span><a class="headerlink" href="#mcts.online_mcts" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/model_checker.html b/documentation/sphinx/.build/.doc/model_checker.html new file mode 100644 index 0000000000000000000000000000000000000000..eefdd7550dd9ae37cf194e124138f4e726a0bd83 --- /dev/null +++ b/documentation/sphinx/.build/.doc/model_checker.html @@ -0,0 +1,606 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>model_checker package — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>model_checker package</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="model-checker-package"> +<h1>model_checker package<a class="headerlink" href="#model-checker-package" title="Permalink to this headline">¶</a></h1> +<div class="section" id="subpackages"> +<h2>Subpackages<a class="headerlink" href="#subpackages" title="Permalink to this headline">¶</a></h2> +<div class="toctree-wrapper compound"> +<ul> +<li class="toctree-l1"><a class="reference internal" href="model_checker.simple_intersection.html">model_checker.simple_intersection package</a><ul> +<li class="toctree-l2"><a class="reference internal" href="model_checker.simple_intersection.html#submodules">Submodules</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.simple_intersection.html#module-model_checker.simple_intersection.AP_dict">model_checker.simple_intersection.AP_dict module</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.simple_intersection.html#model-checker-simple-intersection-ltl-test-module">model_checker.simple_intersection.LTL_test module</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.simple_intersection.html#module-model_checker.simple_intersection.classes">model_checker.simple_intersection.classes module</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.simple_intersection.html#module-model_checker.simple_intersection">Module contents</a></li> +</ul> +</li> +</ul> +</div> +</div> +<div class="section" id="submodules"> +<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="module-model_checker.LTL_property_base"> +<span id="model-checker-ltl-property-base-module"></span><h2>model_checker.LTL_property_base module<a class="headerlink" href="#module-model_checker.LTL_property_base" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="model_checker.LTL_property_base.LTLPropertyBase"> +<em class="property">class </em><code class="descclassname">model_checker.LTL_property_base.</code><code class="descname">LTLPropertyBase</code><span class="sig-paren">(</span><em>LTL_str</em>, <em>penalty</em>, <em>enabled=True</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.LTL_property_base.LTLPropertyBase" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>This is a base class that contains information of an LTL property.</p> +<p>It encapsulates the model-checking part (see check / check_incremental), +and contains additional information. The subclass needs to describe +specific APdict to be used.</p> +<dl class="attribute"> +<dt id="model_checker.LTL_property_base.LTLPropertyBase.APdict"> +<code class="descname">APdict</code><em class="property"> = None</em><a class="headerlink" href="#model_checker.LTL_property_base.LTLPropertyBase.APdict" title="Permalink to this definition">¶</a></dt> +<dd><p>The atomic propositions dict you must set in the subclass.</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.LTL_property_base.LTLPropertyBase.check"> +<code class="descname">check</code><span class="sig-paren">(</span><em>trace</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.LTL_property_base.LTLPropertyBase.check" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks the LTL property w.r.t. the given trace.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>trace</strong> – a sequence of states</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">result w.r.t. entire trace, in {TRUE, FALSE, UNDECIDED}</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.LTL_property_base.LTLPropertyBase.check_incremental"> +<code class="descname">check_incremental</code><span class="sig-paren">(</span><em>state</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.LTL_property_base.LTLPropertyBase.check_incremental" title="Permalink to this definition">¶</a></dt> +<dd><dl class="docutils"> +<dt>Checks an initialised property w.r.t. the next state in a trace.</dt> +<dd>Assumes init_property or check were previously called.</dd> +</dl> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>state</strong> – next state (an integer)</td> +</tr> +<tr class="field-even field"><th class="field-name">Returns:</th><td class="field-body">incremental result, in {TRUE, FALSE, UNDECIDED}</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="attribute"> +<dt id="model_checker.LTL_property_base.LTLPropertyBase.parser"> +<code class="descname">parser</code><em class="property"> = None</em><a class="headerlink" href="#model_checker.LTL_property_base.LTLPropertyBase.parser" title="Permalink to this definition">¶</a></dt> +<dd><p>This property’s checker virtual machine</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.LTL_property_base.LTLPropertyBase.reset_property"> +<code class="descname">reset_property</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.LTL_property_base.LTLPropertyBase.reset_property" title="Permalink to this definition">¶</a></dt> +<dd><p>Resets existing property so that it can be applied to a new sequence of states. +Assumes init_property or check were previously called.</p> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-model_checker.atomic_propositions_base"> +<span id="model-checker-atomic-propositions-base-module"></span><h2>model_checker.atomic_propositions_base module<a class="headerlink" href="#module-model_checker.atomic_propositions_base" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="model_checker.atomic_propositions_base.AtomicPropositionsBase"> +<em class="property">class </em><code class="descclassname">model_checker.atomic_propositions_base.</code><code class="descname">AtomicPropositionsBase</code><a class="headerlink" href="#model_checker.atomic_propositions_base.AtomicPropositionsBase" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#model_checker.atomic_propositions_base.Bits" title="model_checker.atomic_propositions_base.Bits"><code class="xref py py-class docutils literal notranslate"><span class="pre">model_checker.atomic_propositions_base.Bits</span></code></a></p> +<p>An AP-control base class for AP-wise manipulation. +the dictionary APdict and its length APdict_len has +to be given in the subclass</p> +<dl class="attribute"> +<dt id="model_checker.atomic_propositions_base.AtomicPropositionsBase.APdict"> +<code class="descname">APdict</code><em class="property"> = None</em><a class="headerlink" href="#model_checker.atomic_propositions_base.AtomicPropositionsBase.APdict" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="model_checker.atomic_propositions_base.Bits"> +<em class="property">class </em><code class="descclassname">model_checker.atomic_propositions_base.</code><code class="descname">Bits</code><span class="sig-paren">(</span><em>value=0</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.atomic_propositions_base.Bits" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>A bit-control class that allows us bit-wise manipulation as shown in the +example:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">bits</span> <span class="o">=</span> <span class="n">Bits</span><span class="p">()</span> +<span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span> +<span class="n">bits</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">bits</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> +</pre></div> +</div> +</dd></dl> + +</div> +<div class="section" id="module-model_checker.parser"> +<span id="model-checker-parser-module"></span><h2>model_checker.parser module<a class="headerlink" href="#module-model_checker.parser" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="model_checker.parser.ErrorRec"> +<em class="property">class </em><code class="descclassname">model_checker.parser.</code><code class="descname">ErrorRec</code><span class="sig-paren">(</span><em>l</em>, <em>c</em>, <em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.ErrorRec" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +</dd></dl> + +<dl class="class"> +<dt id="model_checker.parser.Errors"> +<em class="property">class </em><code class="descclassname">model_checker.parser.</code><code class="descname">Errors</code><a class="headerlink" href="#model_checker.parser.Errors" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.Exception"> +<em class="property">static </em><code class="descname">Exception</code><span class="sig-paren">(</span><em>errMsg</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.Exception" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.Init"> +<em class="property">static </em><code class="descname">Init</code><span class="sig-paren">(</span><em>fn</em>, <em>dir</em>, <em>merge</em>, <em>getParsingPos</em>, <em>errorMessages</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.Init" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.SemErr"> +<em class="property">static </em><code class="descname">SemErr</code><span class="sig-paren">(</span><em>errMsg</em>, <em>errPos=None</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.SemErr" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.Summarize"> +<em class="property">static </em><code class="descname">Summarize</code><span class="sig-paren">(</span><em>sourceBuffer</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.Summarize" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.SynErr"> +<em class="property">static </em><code class="descname">SynErr</code><span class="sig-paren">(</span><em>errNum</em>, <em>errPos=None</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.SynErr" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.Warn"> +<em class="property">static </em><code class="descname">Warn</code><span class="sig-paren">(</span><em>errMsg</em>, <em>errPos=None</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.Warn" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.count"> +<code class="descname">count</code><em class="property"> = 0</em><a class="headerlink" href="#model_checker.parser.Errors.count" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.display"> +<em class="property">static </em><code class="descname">display</code><span class="sig-paren">(</span><em>s</em>, <em>e</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.display" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.eof"> +<code class="descname">eof</code><em class="property"> = False</em><a class="headerlink" href="#model_checker.parser.Errors.eof" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.errDist"> +<code class="descname">errDist</code><em class="property"> = 2</em><a class="headerlink" href="#model_checker.parser.Errors.errDist" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.errMsgFormat"> +<code class="descname">errMsgFormat</code><em class="property"> = '%(file)s : (%(line)d, %(col)d) %(text)s\n'</em><a class="headerlink" href="#model_checker.parser.Errors.errMsgFormat" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.errors"> +<code class="descname">errors</code><em class="property"> = []</em><a class="headerlink" href="#model_checker.parser.Errors.errors" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.fileName"> +<code class="descname">fileName</code><em class="property"> = ''</em><a class="headerlink" href="#model_checker.parser.Errors.fileName" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.listName"> +<code class="descname">listName</code><em class="property"> = ''</em><a class="headerlink" href="#model_checker.parser.Errors.listName" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.mergeErrors"> +<code class="descname">mergeErrors</code><em class="property"> = False</em><a class="headerlink" href="#model_checker.parser.Errors.mergeErrors" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.mergedList"> +<code class="descname">mergedList</code><em class="property"> = None</em><a class="headerlink" href="#model_checker.parser.Errors.mergedList" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Errors.minErrDist"> +<code class="descname">minErrDist</code><em class="property"> = 2</em><a class="headerlink" href="#model_checker.parser.Errors.minErrDist" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.printMsg"> +<em class="property">static </em><code class="descname">printMsg</code><span class="sig-paren">(</span><em>fileName</em>, <em>line</em>, <em>column</em>, <em>msg</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.printMsg" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="staticmethod"> +<dt id="model_checker.parser.Errors.storeError"> +<em class="property">static </em><code class="descname">storeError</code><span class="sig-paren">(</span><em>line</em>, <em>col</em>, <em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Errors.storeError" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="model_checker.parser.Parser"> +<em class="property">class </em><code class="descclassname">model_checker.parser.</code><code class="descname">Parser</code><a class="headerlink" href="#model_checker.parser.Parser" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<dl class="method"> +<dt id="model_checker.parser.Parser.Check"> +<code class="descname">Check</code><span class="sig-paren">(</span><em>trace</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Check" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks an entire trace w.r.t. an existing property Scanner. +Includes ResetProperty, but not SetProperty.</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.CheckIncremental"> +<code class="descname">CheckIncremental</code><span class="sig-paren">(</span><em>state</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.CheckIncremental" title="Permalink to this definition">¶</a></dt> +<dd><p>Checks a new state w.r.t. an existing property Scanner. +Constructs a trace from new states using a new or previous trace list. +If a previous trace list is used, states after index self.step are not valid.</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Check_old"> +<code class="descname">Check_old</code><span class="sig-paren">(</span><em>propscanner</em>, <em>trace</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Check_old" title="Permalink to this definition">¶</a></dt> +<dd><p>Deprecated method to check an entire trace with a new property Scanner. +Includes SetProperty, which includes ResetProperty.</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Conjunction"> +<code class="descname">Conjunction</code><span class="sig-paren">(</span><em>index</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Conjunction" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Disjunction"> +<code class="descname">Disjunction</code><span class="sig-paren">(</span><em>index</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Disjunction" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Expect"> +<code class="descname">Expect</code><span class="sig-paren">(</span><em>n</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Expect" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.ExpectWeak"> +<code class="descname">ExpectWeak</code><span class="sig-paren">(</span><em>n</em>, <em>follow</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.ExpectWeak" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.FALSE"> +<code class="descname">FALSE</code><em class="property"> = 0</em><a class="headerlink" href="#model_checker.parser.Parser.FALSE" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Factor"> +<code class="descname">Factor</code><span class="sig-paren">(</span><em>index</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Factor" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Get"> +<code class="descname">Get</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Get" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Implication"> +<code class="descname">Implication</code><span class="sig-paren">(</span><em>index</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Implication" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.LexString"> +<code class="descname">LexString</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.LexString" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.LookAheadString"> +<code class="descname">LookAheadString</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.LookAheadString" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Parse"> +<code class="descname">Parse</code><span class="sig-paren">(</span><em>scanner</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Parse" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Property"> +<code class="descname">Property</code><span class="sig-paren">(</span><em>index</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Property" title="Permalink to this definition">¶</a></dt> +<dd><p>Main property entry point.</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.PyCheck"> +<code class="descname">PyCheck</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.PyCheck" title="Permalink to this definition">¶</a></dt> +<dd><p>Unused dummy method.</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.ResetProperty"> +<code class="descname">ResetProperty</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.ResetProperty" title="Permalink to this definition">¶</a></dt> +<dd><p>Re-iniitializes an existing property Scanner.</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.SemErr"> +<code class="descname">SemErr</code><span class="sig-paren">(</span><em>msg</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.SemErr" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.SetProperty"> +<code class="descname">SetProperty</code><span class="sig-paren">(</span><em>propscanner</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.SetProperty" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets the property Scanner that tokenizes the property.</p> +</dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.StartOf"> +<code class="descname">StartOf</code><span class="sig-paren">(</span><em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.StartOf" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Successful"> +<code class="descname">Successful</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Successful" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.SynErr"> +<code class="descname">SynErr</code><span class="sig-paren">(</span><em>errNum</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.SynErr" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.T"> +<code class="descname">T</code><em class="property"> = True</em><a class="headerlink" href="#model_checker.parser.Parser.T" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.TRUE"> +<code class="descname">TRUE</code><em class="property"> = 2</em><a class="headerlink" href="#model_checker.parser.Parser.TRUE" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.UNDECIDED"> +<code class="descname">UNDECIDED</code><em class="property"> = 1</em><a class="headerlink" href="#model_checker.parser.Parser.UNDECIDED" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.UNDEFINED"> +<code class="descname">UNDEFINED</code><em class="property"> = -1</em><a class="headerlink" href="#model_checker.parser.Parser.UNDEFINED" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.Warning"> +<code class="descname">Warning</code><span class="sig-paren">(</span><em>msg</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.Warning" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.WeakSeparator"> +<code class="descname">WeakSeparator</code><span class="sig-paren">(</span><em>n</em>, <em>syFol</em>, <em>repFol</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.WeakSeparator" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.errorMessages"> +<code class="descname">errorMessages</code><em class="property"> = {0: 'EOF expected', 1: 'proposition expected', 2: '"U" expected', 3: '"F" expected', 4: '"G" expected', 5: '"X" expected', 6: '"=>" expected', 7: '"or" expected', 8: '"and" expected', 9: '"not" expected', 10: '"true" expected', 11: '"false" expected', 12: '"(" expected', 13: '")" expected', 14: '??? expected', 15: 'invalid Property', 16: 'invalid Factor'}</em><a class="headerlink" href="#model_checker.parser.Parser.errorMessages" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.parser.Parser.getParsingPos"> +<code class="descname">getParsingPos</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.parser.Parser.getParsingPos" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.maxT"> +<code class="descname">maxT</code><em class="property"> = 14</em><a class="headerlink" href="#model_checker.parser.Parser.maxT" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.minErrDist"> +<code class="descname">minErrDist</code><em class="property"> = 2</em><a class="headerlink" href="#model_checker.parser.Parser.minErrDist" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.set"> +<code class="descname">set</code><em class="property"> = [[True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False], [False, True, False, False, False, False, False, False, False, True, True, True, True, False, False, False]]</em><a class="headerlink" href="#model_checker.parser.Parser.set" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.parser.Parser.x"> +<code class="descname">x</code><em class="property"> = False</em><a class="headerlink" href="#model_checker.parser.Parser.x" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-model_checker.scanner"> +<span id="model-checker-scanner-module"></span><h2>model_checker.scanner module<a class="headerlink" href="#module-model_checker.scanner" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="model_checker.scanner.Buffer"> +<em class="property">class </em><code class="descclassname">model_checker.scanner.</code><code class="descname">Buffer</code><span class="sig-paren">(</span><em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Buffer" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<dl class="attribute"> +<dt id="model_checker.scanner.Buffer.EOF"> +<code class="descname">EOF</code><em class="property"> = 'Ä€'</em><a class="headerlink" href="#model_checker.scanner.Buffer.EOF" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Buffer.Peek"> +<code class="descname">Peek</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Buffer.Peek" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Buffer.Read"> +<code class="descname">Read</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Buffer.Read" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Buffer.ReadChars"> +<code class="descname">ReadChars</code><span class="sig-paren">(</span><em>numBytes=1</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Buffer.ReadChars" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Buffer.getPos"> +<code class="descname">getPos</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Buffer.getPos" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Buffer.getString"> +<code class="descname">getString</code><span class="sig-paren">(</span><em>beg</em>, <em>end</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Buffer.getString" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Buffer.readPosition"> +<code class="descname">readPosition</code><span class="sig-paren">(</span><em>pos</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Buffer.readPosition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Buffer.setPos"> +<code class="descname">setPos</code><span class="sig-paren">(</span><em>value</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Buffer.setPos" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="model_checker.scanner.Position"> +<em class="property">class </em><code class="descclassname">model_checker.scanner.</code><code class="descname">Position</code><span class="sig-paren">(</span><em>buf</em>, <em>beg</em>, <em>len</em>, <em>col</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Position" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<dl class="method"> +<dt id="model_checker.scanner.Position.getSubstring"> +<code class="descname">getSubstring</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Position.getSubstring" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="model_checker.scanner.Scanner"> +<em class="property">class </em><code class="descclassname">model_checker.scanner.</code><code class="descname">Scanner</code><span class="sig-paren">(</span><em>s</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Scanner" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<dl class="method"> +<dt id="model_checker.scanner.Scanner.CheckLiteral"> +<code class="descname">CheckLiteral</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Scanner.CheckLiteral" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Scanner.Comment0"> +<code class="descname">Comment0</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Scanner.Comment0" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.scanner.Scanner.EOL"> +<code class="descname">EOL</code><em class="property"> = '\n'</em><a class="headerlink" href="#model_checker.scanner.Scanner.EOL" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Scanner.NextCh"> +<code class="descname">NextCh</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Scanner.NextCh" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Scanner.NextToken"> +<code class="descname">NextToken</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Scanner.NextToken" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Scanner.Peek"> +<code class="descname">Peek</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Scanner.Peek" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Scanner.ResetPeek"> +<code class="descname">ResetPeek</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Scanner.ResetPeek" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="model_checker.scanner.Scanner.Scan"> +<code class="descname">Scan</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.scanner.Scanner.Scan" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.scanner.Scanner.charSetSize"> +<code class="descname">charSetSize</code><em class="property"> = 256</em><a class="headerlink" href="#model_checker.scanner.Scanner.charSetSize" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.scanner.Scanner.eofSym"> +<code class="descname">eofSym</code><em class="property"> = 0</em><a class="headerlink" href="#model_checker.scanner.Scanner.eofSym" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.scanner.Scanner.maxT"> +<code class="descname">maxT</code><em class="property"> = 14</em><a class="headerlink" href="#model_checker.scanner.Scanner.maxT" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.scanner.Scanner.noSym"> +<code class="descname">noSym</code><em class="property"> = 14</em><a class="headerlink" href="#model_checker.scanner.Scanner.noSym" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="model_checker.scanner.Scanner.start"> +<code class="descname">start</code><em class="property"> = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1]</em><a class="headerlink" href="#model_checker.scanner.Scanner.start" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="model_checker.scanner.Token"> +<em class="property">class </em><code class="descclassname">model_checker.scanner.</code><code class="descname">Token</code><a class="headerlink" href="#model_checker.scanner.Token" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +</dd></dl> + +</div> +<div class="section" id="module-model_checker"> +<span id="module-contents"></span><h2>Module contents<a class="headerlink" href="#module-model_checker" title="Permalink to this headline">¶</a></h2> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/model_checker.simple_intersection.html b/documentation/sphinx/.build/.doc/model_checker.simple_intersection.html new file mode 100644 index 0000000000000000000000000000000000000000..be797d77d135c3387879762c6f99dd29bc847b4c --- /dev/null +++ b/documentation/sphinx/.build/.doc/model_checker.simple_intersection.html @@ -0,0 +1,108 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>model_checker.simple_intersection package — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>model_checker.simple_intersection package</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="model-checker-simple-intersection-package"> +<h1>model_checker.simple_intersection package<a class="headerlink" href="#model-checker-simple-intersection-package" title="Permalink to this headline">¶</a></h1> +<div class="section" id="submodules"> +<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="module-model_checker.simple_intersection.AP_dict"> +<span id="model-checker-simple-intersection-ap-dict-module"></span><h2>model_checker.simple_intersection.AP_dict module<a class="headerlink" href="#module-model_checker.simple_intersection.AP_dict" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="model-checker-simple-intersection-ltl-test-module"> +<h2>model_checker.simple_intersection.LTL_test module<a class="headerlink" href="#model-checker-simple-intersection-ltl-test-module" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="module-model_checker.simple_intersection.classes"> +<span id="model-checker-simple-intersection-classes-module"></span><h2>model_checker.simple_intersection.classes module<a class="headerlink" href="#module-model_checker.simple_intersection.classes" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="model_checker.simple_intersection.classes.AtomicPropositions"> +<em class="property">class </em><code class="descclassname">model_checker.simple_intersection.classes.</code><code class="descname">AtomicPropositions</code><a class="headerlink" href="#model_checker.simple_intersection.classes.AtomicPropositions" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="model_checker.html#model_checker.atomic_propositions_base.AtomicPropositionsBase" title="model_checker.atomic_propositions_base.AtomicPropositionsBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">model_checker.atomic_propositions_base.AtomicPropositionsBase</span></code></a></p> +<dl class="docutils"> +<dt>An AP-control class for AP-wise manipulation as shown in the</dt> +<dd><p class="first">example:</p> +<p>APs = AtomicPropositions() +APs[0] = False # this is same as</p> +<blockquote> +<div># APs[AP_dict[‘stop_region’]] = False</div></blockquote> +<p class="last">APs[‘in_stop_region’] = False # both expressions are the same</p> +</dd> +<dt>Requires:</dt> +<dd>Index in […] is an integer should be in the range +{0,1,2, …, AP_dict_len}.</dd> +</dl> +<dl class="attribute"> +<dt id="model_checker.simple_intersection.classes.AtomicPropositions.APdict"> +<code class="descname">APdict</code><em class="property"> = {'before_but_close_to_stop_region': 2, 'before_intersection': 13, 'has_entered_stop_region': 1, 'has_stopped_in_stop_region': 4, 'highest_priority': 8, 'in_intersection': 5, 'in_stop_region': 0, 'intersection_is_clear': 9, 'lane': 11, 'on_route': 7, 'over_speed_limit': 6, 'parallel_to_lane': 12, 'stopped_now': 3, 'target_lane': 14, 'veh_ahead': 10, 'veh_ahead_stopped_now': 15, 'veh_ahead_too_close': 16}</em><a class="headerlink" href="#model_checker.simple_intersection.classes.AtomicPropositions.APdict" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="model_checker.simple_intersection.classes.LTLProperty"> +<em class="property">class </em><code class="descclassname">model_checker.simple_intersection.classes.</code><code class="descname">LTLProperty</code><span class="sig-paren">(</span><em>LTL_str</em>, <em>penalty</em>, <em>enabled=True</em><span class="sig-paren">)</span><a class="headerlink" href="#model_checker.simple_intersection.classes.LTLProperty" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="model_checker.html#model_checker.LTL_property_base.LTLPropertyBase" title="model_checker.LTL_property_base.LTLPropertyBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">model_checker.LTL_property_base.LTLPropertyBase</span></code></a></p> +<p>is a class that contains information of an LTL property in +simple_intersection road scenario.</p> +<p>It encapsulates the model-checking part and contains additional +information.</p> +<dl class="attribute"> +<dt id="model_checker.simple_intersection.classes.LTLProperty.APdict"> +<code class="descname">APdict</code><em class="property"> = {'before_but_close_to_stop_region': 2, 'before_intersection': 13, 'has_entered_stop_region': 1, 'has_stopped_in_stop_region': 4, 'highest_priority': 8, 'in_intersection': 5, 'in_stop_region': 0, 'intersection_is_clear': 9, 'lane': 11, 'on_route': 7, 'over_speed_limit': 6, 'parallel_to_lane': 12, 'stopped_now': 3, 'target_lane': 14, 'veh_ahead': 10, 'veh_ahead_stopped_now': 15, 'veh_ahead_too_close': 16}</em><a class="headerlink" href="#model_checker.simple_intersection.classes.LTLProperty.APdict" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-model_checker.simple_intersection"> +<span id="module-contents"></span><h2>Module contents<a class="headerlink" href="#module-model_checker.simple_intersection" title="Permalink to this headline">¶</a></h2> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/modules.html b/documentation/sphinx/.build/.doc/modules.html new file mode 100644 index 0000000000000000000000000000000000000000..6409144b21bb3e9c930fa9da078f0b10d49626ba --- /dev/null +++ b/documentation/sphinx/.build/.doc/modules.html @@ -0,0 +1,137 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>wisemove — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>wisemove</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="wisemove"> +<h1>wisemove<a class="headerlink" href="#wisemove" title="Permalink to this headline">¶</a></h1> +<div class="toctree-wrapper compound"> +<ul> +<li class="toctree-l1"><a class="reference internal" href="backends.html">backends package</a><ul> +<li class="toctree-l2"><a class="reference internal" href="backends.html#submodules">Submodules</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.baselines_learner">backends.baselines_learner module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.controller_base">backends.controller_base module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.kerasrl_learner">backends.kerasrl_learner module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.learner_base">backends.learner_base module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.manual_policy">backends.manual_policy module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.mcts_learner">backends.mcts_learner module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.online_mcts_controller">backends.online_mcts_controller module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.policy_base">backends.policy_base module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends.rl_controller">backends.rl_controller module</a></li> +<li class="toctree-l2"><a class="reference internal" href="backends.html#module-backends">Module contents</a></li> +</ul> +</li> +<li class="toctree-l1"><a class="reference internal" href="env.html">env package</a><ul> +<li class="toctree-l2"><a class="reference internal" href="env.html#subpackages">Subpackages</a><ul> +<li class="toctree-l3"><a class="reference internal" href="env.simple_intersection.html">env.simple_intersection package</a><ul> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#submodules">Submodules</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.constants">env.simple_intersection.constants module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.features">env.simple_intersection.features module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.road_geokinemetry">env.simple_intersection.road_geokinemetry module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.road_networks">env.simple_intersection.road_networks module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.shapes">env.simple_intersection.shapes module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.simple_intersection_env">env.simple_intersection.simple_intersection_env module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.utilities">env.simple_intersection.utilities module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.vehicle_networks">env.simple_intersection.vehicle_networks module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection.vehicles">env.simple_intersection.vehicles module</a></li> +<li class="toctree-l4"><a class="reference internal" href="env.simple_intersection.html#module-env.simple_intersection">Module contents</a></li> +</ul> +</li> +</ul> +</li> +<li class="toctree-l2"><a class="reference internal" href="env.html#submodules">Submodules</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.html#module-env.env_base">env.env_base module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.html#module-env.road_env">env.road_env module</a></li> +<li class="toctree-l2"><a class="reference internal" href="env.html#module-env">Module contents</a></li> +</ul> +</li> +<li class="toctree-l1"><a class="reference internal" href="high_level_policy_main.html">high_level_policy_main module</a></li> +<li class="toctree-l1"><a class="reference internal" href="low_level_policy_main.html">low_level_policy_main module</a></li> +<li class="toctree-l1"><a class="reference internal" href="mcts.html">mcts module</a></li> +<li class="toctree-l1"><a class="reference internal" href="model_checker.html">model_checker package</a><ul> +<li class="toctree-l2"><a class="reference internal" href="model_checker.html#subpackages">Subpackages</a><ul> +<li class="toctree-l3"><a class="reference internal" href="model_checker.simple_intersection.html">model_checker.simple_intersection package</a><ul> +<li class="toctree-l4"><a class="reference internal" href="model_checker.simple_intersection.html#submodules">Submodules</a></li> +<li class="toctree-l4"><a class="reference internal" href="model_checker.simple_intersection.html#module-model_checker.simple_intersection.AP_dict">model_checker.simple_intersection.AP_dict module</a></li> +<li class="toctree-l4"><a class="reference internal" href="model_checker.simple_intersection.html#model-checker-simple-intersection-ltl-test-module">model_checker.simple_intersection.LTL_test module</a></li> +<li class="toctree-l4"><a class="reference internal" href="model_checker.simple_intersection.html#module-model_checker.simple_intersection.classes">model_checker.simple_intersection.classes module</a></li> +<li class="toctree-l4"><a class="reference internal" href="model_checker.simple_intersection.html#module-model_checker.simple_intersection">Module contents</a></li> +</ul> +</li> +</ul> +</li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.html#submodules">Submodules</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.html#module-model_checker.LTL_property_base">model_checker.LTL_property_base module</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.html#module-model_checker.atomic_propositions_base">model_checker.atomic_propositions_base module</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.html#module-model_checker.parser">model_checker.parser module</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.html#module-model_checker.scanner">model_checker.scanner module</a></li> +<li class="toctree-l2"><a class="reference internal" href="model_checker.html#module-model_checker">Module contents</a></li> +</ul> +</li> +<li class="toctree-l1"><a class="reference internal" href="options.html">options package</a><ul> +<li class="toctree-l2"><a class="reference internal" href="options.html#subpackages">Subpackages</a><ul> +<li class="toctree-l3"><a class="reference internal" href="options.simple_intersection.html">options.simple_intersection package</a><ul> +<li class="toctree-l4"><a class="reference internal" href="options.simple_intersection.html#submodules">Submodules</a></li> +<li class="toctree-l4"><a class="reference internal" href="options.simple_intersection.html#module-options.simple_intersection.maneuver_base">options.simple_intersection.maneuver_base module</a></li> +<li class="toctree-l4"><a class="reference internal" href="options.simple_intersection.html#module-options.simple_intersection.maneuvers">options.simple_intersection.maneuvers module</a></li> +<li class="toctree-l4"><a class="reference internal" href="options.simple_intersection.html#module-options.simple_intersection.mcts_maneuvers">options.simple_intersection.mcts_maneuvers module</a></li> +<li class="toctree-l4"><a class="reference internal" href="options.simple_intersection.html#module-options.simple_intersection">Module contents</a></li> +</ul> +</li> +</ul> +</li> +<li class="toctree-l2"><a class="reference internal" href="options.html#submodules">Submodules</a></li> +<li class="toctree-l2"><a class="reference internal" href="options.html#module-options.options_loader">options.options_loader module</a></li> +<li class="toctree-l2"><a class="reference internal" href="options.html#module-options">Module contents</a></li> +</ul> +</li> +<li class="toctree-l1"><a class="reference internal" href="ppo2_training.html">ppo2_training module</a></li> +</ul> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/options.html b/documentation/sphinx/.build/.doc/options.html new file mode 100644 index 0000000000000000000000000000000000000000..f00be8017c85259629e55f0636f60f3f59a14aa0 --- /dev/null +++ b/documentation/sphinx/.build/.doc/options.html @@ -0,0 +1,214 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>options package — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>options package</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="options-package"> +<h1>options package<a class="headerlink" href="#options-package" title="Permalink to this headline">¶</a></h1> +<div class="section" id="subpackages"> +<h2>Subpackages<a class="headerlink" href="#subpackages" title="Permalink to this headline">¶</a></h2> +<div class="toctree-wrapper compound"> +<ul> +<li class="toctree-l1"><a class="reference internal" href="options.simple_intersection.html">options.simple_intersection package</a><ul> +<li class="toctree-l2"><a class="reference internal" href="options.simple_intersection.html#submodules">Submodules</a></li> +<li class="toctree-l2"><a class="reference internal" href="options.simple_intersection.html#module-options.simple_intersection.maneuver_base">options.simple_intersection.maneuver_base module</a></li> +<li class="toctree-l2"><a class="reference internal" href="options.simple_intersection.html#module-options.simple_intersection.maneuvers">options.simple_intersection.maneuvers module</a></li> +<li class="toctree-l2"><a class="reference internal" href="options.simple_intersection.html#module-options.simple_intersection.mcts_maneuvers">options.simple_intersection.mcts_maneuvers module</a></li> +<li class="toctree-l2"><a class="reference internal" href="options.simple_intersection.html#module-options.simple_intersection">Module contents</a></li> +</ul> +</li> +</ul> +</div> +</div> +<div class="section" id="submodules"> +<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="module-options.options_loader"> +<span id="options-options-loader-module"></span><h2>options.options_loader module<a class="headerlink" href="#module-options.options_loader" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="options.options_loader.OptionsGraph"> +<em class="property">class </em><code class="descclassname">options.options_loader.</code><code class="descname">OptionsGraph</code><span class="sig-paren">(</span><em>json_path</em>, <em>env_class</em>, <em>*env_args</em>, <em>**env_kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <code class="xref py py-class docutils literal notranslate"><span class="pre">object</span></code></p> +<p>Represent the options graph as a graph like structure. The configuration +is specified in a json file and consists of the following specific values:</p> +<ul class="simple"> +<li>nodes: dictionary of policy node aliases -> maneuver classes</li> +<li><dl class="first docutils"> +<dt>edges: dictionary such that it has key value pairs which represent</dt> +<dd>edges between policy node aliases</dd> +</dl> +</li> +<li>starting_node: ego’s starting node</li> +</ul> +<dl class="attribute"> +<dt id="options.options_loader.OptionsGraph.adj"> +<code class="descname">adj</code><em class="property"> = None</em><a class="headerlink" href="#options.options_loader.OptionsGraph.adj" title="Permalink to this definition">¶</a></dt> +<dd><p>adjacency list from the graph</p> +</dd></dl> + +<dl class="attribute"> +<dt id="options.options_loader.OptionsGraph.current_node"> +<code class="descname">current_node</code><a class="headerlink" href="#options.options_loader.OptionsGraph.current_node" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.options_loader.OptionsGraph.edges"> +<code class="descname">edges</code><em class="property"> = None</em><a class="headerlink" href="#options.options_loader.OptionsGraph.edges" title="Permalink to this definition">¶</a></dt> +<dd><p>edges of the graph</p> +</dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.execute_controller_policy"> +<code class="descname">execute_controller_policy</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.execute_controller_policy" title="Permalink to this definition">¶</a></dt> +<dd><p>Performs low level steps and transitions to other nodes using controller transition policy.</p> +<p>Returns state after one step, step reward, episode_termination_flag, info</p> +</dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.get_number_of_nodes"> +<code class="descname">get_number_of_nodes</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.get_number_of_nodes" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.load_trained_low_level_policies"> +<code class="descname">load_trained_low_level_policies</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.load_trained_low_level_policies" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.options_loader.OptionsGraph.nodes"> +<code class="descname">nodes</code><em class="property"> = None</em><a class="headerlink" href="#options.options_loader.OptionsGraph.nodes" title="Permalink to this definition">¶</a></dt> +<dd><p>nodes of the graph</p> +</dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.render"> +<code class="descname">render</code><span class="sig-paren">(</span><em>mode='human'</em><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.render" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.reset"> +<code class="descname">reset</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.reset" title="Permalink to this definition">¶</a></dt> +<dd><p>Reset the environment. This function may be needed to reset the +environment for eg. after an MCTS rollout and update. Also reset the +controller to root node.</p> +<p>Returns whatever the environment’s reset returns.</p> +</dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.set_controller_args"> +<code class="descname">set_controller_args</code><span class="sig-paren">(</span><em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.set_controller_args" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets custom arguments depending on the chosen controller</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>**kwargs</strong> – dictionary of args and values</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.set_controller_policy"> +<code class="descname">set_controller_policy</code><span class="sig-paren">(</span><em>policy</em><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.set_controller_policy" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets the trained controller policy as a function which takes in feature vector and returns +an option index(int). By default, trained_policy is None</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>policy</strong> – a function which takes in feature vector and returns an option index(int)</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.set_current_node"> +<code class="descname">set_current_node</code><span class="sig-paren">(</span><em>node_alias</em><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.set_current_node" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets the current node for controller. Used for training/testing a particular node</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>node_alias</strong> – alias of the node as per config file</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="method"> +<dt id="options.options_loader.OptionsGraph.step"> +<code class="descname">step</code><span class="sig-paren">(</span><em>option</em><span class="sig-paren">)</span><a class="headerlink" href="#options.options_loader.OptionsGraph.step" title="Permalink to this definition">¶</a></dt> +<dd><p>Complete an episode using specified option. This assumes that +the manager’s env is at a place where the option’s initiation +condition is met.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>option</strong> – index of high level option to be executed</td> +</tr> +</tbody> +</table> +</dd></dl> + +<dl class="attribute"> +<dt id="options.options_loader.OptionsGraph.visualize_low_level_steps"> +<code class="descname">visualize_low_level_steps</code><em class="property"> = False</em><a class="headerlink" href="#options.options_loader.OptionsGraph.visualize_low_level_steps" title="Permalink to this definition">¶</a></dt> +<dd><p>visualization flag</p> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-options"> +<span id="module-contents"></span><h2>Module contents<a class="headerlink" href="#module-options" title="Permalink to this headline">¶</a></h2> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/options.simple_intersection.html b/documentation/sphinx/.build/.doc/options.simple_intersection.html new file mode 100644 index 0000000000000000000000000000000000000000..f2699ea3976dd979a8be09700421a5a665478560 --- /dev/null +++ b/documentation/sphinx/.build/.doc/options.simple_intersection.html @@ -0,0 +1,462 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>options.simple_intersection package — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>options.simple_intersection package</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="options-simple-intersection-package"> +<h1>options.simple_intersection package<a class="headerlink" href="#options-simple-intersection-package" title="Permalink to this headline">¶</a></h1> +<div class="section" id="submodules"> +<h2>Submodules<a class="headerlink" href="#submodules" title="Permalink to this headline">¶</a></h2> +</div> +<div class="section" id="module-options.simple_intersection.maneuver_base"> +<span id="options-simple-intersection-maneuver-base-module"></span><h2>options.simple_intersection.maneuver_base module<a class="headerlink" href="#module-options.simple_intersection.maneuver_base" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.maneuver_base.</code><code class="descname">ManeuverBase</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="env.html#env.env_base.EpisodicEnvBase" title="env.env_base.EpisodicEnvBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">env.env_base.EpisodicEnvBase</span></code></a></p> +<p>The abstract class from which each maneuver is defined and inherited.</p> +<p>In all of the maneuvers, we assume that the ego-vehicle is supposed +to drive on the ‘h’orizontal route.</p> +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.action_space"> +<code class="descname">action_space</code><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.action_space" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.extra_initiation_condition"> +<code class="descname">extra_initiation_condition</code><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.extra_initiation_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.extra_termination_condition"> +<code class="descname">extra_termination_condition</code><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.extra_termination_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.generate_scenario"> +<code class="descname">generate_scenario</code><span class="sig-paren">(</span><em>enable_LTL_preconditions=True</em>, <em>timeout=inf</em>, <em>**kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.generate_scenario" title="Permalink to this definition">¶</a></dt> +<dd><dl class="docutils"> +<dt>generates the scenario for low-level policy learning and validation. This method</dt> +<dd>will be used in generate_learning_scenario and generate_validation_scenario in +the subclasses.</dd> +<dt>Param:</dt> +<dd>enable_LTL_preconditions: whether to enable LTL preconditions in the maneuver or not +timeout: the timeout for the scenario (which is infinity by default) +<a href="#id1"><span class="problematic" id="id2">**</span></a>kwargs: the arguments of generate_scenario of the environment.</dd> +</dl> +</dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.generate_validation_scenario"> +<code class="descname">generate_validation_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.generate_validation_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.get_reduced_feature_length"> +<code class="descname">get_reduced_feature_length</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.get_reduced_feature_length" title="Permalink to this definition">¶</a></dt> +<dd><p>get the length of the feature tuple after applying _features_dim_reduction. +:return:</p> +</dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.get_reduced_features_tuple"> +<code class="descname">get_reduced_features_tuple</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.get_reduced_features_tuple" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.goal_achieved"> +<code class="descname">goal_achieved</code><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.goal_achieved" title="Permalink to this definition">¶</a></dt> +<dd><p>Check whether the ego vehicle achieves the goal of the maneuver or +not.</p> +<p>By default, there is no goal, so the ego vehicle never achieves +it (i.e., goal_achieved is always False).</p> +</dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.high_level_extra_reward"> +<code class="descname">high_level_extra_reward</code><em class="property"> = 0</em><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.high_level_extra_reward" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.initiation_condition"> +<code class="descname">initiation_condition</code><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.initiation_condition" title="Permalink to this definition">¶</a></dt> +<dd><p>this method specifies the initiation condition (or in a technical +term, initiation set) of the maneuver.</p> +<p>Returns True if the condition is satisfied, and False otherwise.</p> +</dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.learning_mode"> +<code class="descname">learning_mode</code><em class="property"> = 'training'</em><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.learning_mode" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.low_level_policy"> +<code class="descname">low_level_policy</code><span class="sig-paren">(</span><em>reduced_features_tuple</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.low_level_policy" title="Permalink to this definition">¶</a></dt> +<dd><p>the low level policy as a map from a feature vector to an action +(a, dot_psi). By default, it’ll call low_level_manual_policy below +if it’s implemented in the subclass.</p> +</dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.observation_space"> +<code class="descname">observation_space</code><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.observation_space" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.render"> +<code class="descname">render</code><span class="sig-paren">(</span><em>mode='human'</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.render" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant step function which +will be implemented in the subclass.</p> +</dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.reset"> +<code class="descname">reset</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.reset" title="Permalink to this definition">¶</a></dt> +<dd><p>Gym compliant reset function.</p> +<p>Reset the environment as specified by the +generate_learning_scenario() in this class and the maneuver, +and then return the initial features tuple.</p> +<table class="docutils field-list" frame="void" rules="none"> +<col class="field-name" /> +<col class="field-body" /> +<tbody valign="top"> +<tr class="field-odd field"><th class="field-name">Returns:</th><td class="field-body">features tuple after _features_dim_reduction</td> +</tr> +</tbody> +</table> +<p>Reinitialize the maneuver and the environment with whatever parameters +it was initially called with. This will be implemented in each subclass maneuver. +(to reset the maneuver part within the implementation of this method +in the subclass, use reset_maneuver below after resetting the environment). +Use this function only for the low-level policy learning of each maneuver.</p> +</dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.reset_maneuver"> +<code class="descname">reset_maneuver</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.reset_maneuver" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.set_low_level_trained_policy"> +<code class="descname">set_low_level_trained_policy</code><span class="sig-paren">(</span><em>trained_policy</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.set_low_level_trained_policy" title="Permalink to this definition">¶</a></dt> +<dd><p>Sets the trained policy as a function which takes in feature vector and returns +an action (a, dot_psi). By default, trained_policy is None</p> +</dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.step"> +<code class="descname">step</code><span class="sig-paren">(</span><em>u_ego</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.step" title="Permalink to this definition">¶</a></dt> +<dd><p>The main function, increases timeout count and calculates the reward +based on model- and collision-checking.</p> +<dl class="docutils"> +<dt>Returns: a tuple (reduced_features_tuple, R, terminal, info), where</dt> +<dd>reduced_features_tuple: the features tuple after _features_dim_reduction; +R: the reward for the transition; +terminal: True if the next state is the terminal state, False if not; +info: log info.</dd> +</dl> +</dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.termination_condition"> +<code class="descname">termination_condition</code><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.termination_condition" title="Permalink to this definition">¶</a></dt> +<dd><p>In the subclass, specify the condition for termination of the episode +(or the maneuver).</p> +</dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.timeout"> +<code class="descname">timeout</code><em class="property"> = 1</em><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.timeout" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.timeout_happened"> +<code class="descname">timeout_happened</code><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.timeout_happened" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuver_base.ManeuverBase.trained_policy"> +<code class="descname">trained_policy</code><em class="property"> = None</em><a class="headerlink" href="#options.simple_intersection.maneuver_base.ManeuverBase.trained_policy" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-options.simple_intersection.maneuvers"> +<span id="options-simple-intersection-maneuvers-module"></span><h2>options.simple_intersection.maneuvers module<a class="headerlink" href="#module-options.simple_intersection.maneuvers" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="options.simple_intersection.maneuvers.ChangeLane"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.maneuvers.</code><code class="descname">ChangeLane</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.ChangeLane" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="method"> +<dt id="options.simple_intersection.maneuvers.ChangeLane.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.ChangeLane.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuvers.ChangeLane.goal_achieved"> +<code class="descname">goal_achieved</code><a class="headerlink" href="#options.simple_intersection.maneuvers.ChangeLane.goal_achieved" title="Permalink to this definition">¶</a></dt> +<dd><p>Check whether the ego vehicle achieves the goal of the maneuver or +not.</p> +<p>By default, there is no goal, so the ego vehicle never achieves +it (i.e., goal_achieved is always False).</p> +</dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuvers.ChangeLane.high_level_extra_reward"> +<code class="descname">high_level_extra_reward</code><em class="property"> = -20</em><a class="headerlink" href="#options.simple_intersection.maneuvers.ChangeLane.high_level_extra_reward" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.maneuvers.ChangeLane.min_y_distance"> +<code class="descname">min_y_distance</code><em class="property"> = 1.0</em><a class="headerlink" href="#options.simple_intersection.maneuvers.ChangeLane.min_y_distance" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="options.simple_intersection.maneuvers.Follow"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.maneuvers.</code><code class="descname">Follow</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.Follow" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="method"> +<dt id="options.simple_intersection.maneuvers.Follow.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.Follow.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="options.simple_intersection.maneuvers.KeepLane"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.maneuvers.</code><code class="descname">KeepLane</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.KeepLane" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="method"> +<dt id="options.simple_intersection.maneuvers.KeepLane.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.KeepLane.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="options.simple_intersection.maneuvers.Stop"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.maneuvers.</code><code class="descname">Stop</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.Stop" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="method"> +<dt id="options.simple_intersection.maneuvers.Stop.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.Stop.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="options.simple_intersection.maneuvers.Wait"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.maneuvers.</code><code class="descname">Wait</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.Wait" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="method"> +<dt id="options.simple_intersection.maneuvers.Wait.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.maneuvers.Wait.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-options.simple_intersection.mcts_maneuvers"> +<span id="options-simple-intersection-mcts-maneuvers-module"></span><h2>options.simple_intersection.mcts_maneuvers module<a class="headerlink" href="#module-options.simple_intersection.mcts_maneuvers" title="Permalink to this headline">¶</a></h2> +<dl class="class"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSChangeLane"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.mcts_maneuvers.</code><code class="descname">MCTSChangeLane</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSChangeLane" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSChangeLane.extra_initiation_condition"> +<code class="descname">extra_initiation_condition</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.extra_initiation_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSChangeLane.extra_termination_condition"> +<code class="descname">extra_termination_condition</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.extra_termination_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSChangeLane.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSChangeLane.goal_achieved"> +<code class="descname">goal_achieved</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.goal_achieved" title="Permalink to this definition">¶</a></dt> +<dd><p>Check whether the ego vehicle achieves the goal of the maneuver or +not.</p> +<p>By default, there is no goal, so the ego vehicle never achieves +it (i.e., goal_achieved is always False).</p> +</dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSChangeLane.max_goal_distance"> +<code class="descname">max_goal_distance</code><em class="property"> = 21</em><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.max_goal_distance" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSChangeLane.min_y_distance"> +<code class="descname">min_y_distance</code><em class="property"> = 3.2</em><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.min_y_distance" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSFollow"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.mcts_maneuvers.</code><code class="descname">MCTSFollow</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSFollow" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSFollow.extra_initiation_condition"> +<code class="descname">extra_initiation_condition</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSFollow.extra_initiation_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSFollow.extra_termination_condition"> +<code class="descname">extra_termination_condition</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSFollow.extra_termination_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSFollow.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSFollow.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSFollow.generate_validation_scenario"> +<code class="descname">generate_validation_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSFollow.generate_validation_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSKeepLane"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.mcts_maneuvers.</code><code class="descname">MCTSKeepLane</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSKeepLane" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSKeepLane.extra_initiation_condition"> +<code class="descname">extra_initiation_condition</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSKeepLane.extra_initiation_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSKeepLane.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSKeepLane.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSKeepLane.generate_validation_scenario"> +<code class="descname">generate_validation_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSKeepLane.generate_validation_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSStop"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.mcts_maneuvers.</code><code class="descname">MCTSStop</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSStop" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSStop.extra_initiation_condition"> +<code class="descname">extra_initiation_condition</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSStop.extra_initiation_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSStop.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSStop.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSStop.goal_achieved"> +<code class="descname">goal_achieved</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSStop.goal_achieved" title="Permalink to this definition">¶</a></dt> +<dd><p>Check whether the ego vehicle achieves the goal of the maneuver or +not.</p> +<p>By default, there is no goal, so the ego vehicle never achieves +it (i.e., goal_achieved is always False).</p> +</dd></dl> + +</dd></dl> + +<dl class="class"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSWait"> +<em class="property">class </em><code class="descclassname">options.simple_intersection.mcts_maneuvers.</code><code class="descname">MCTSWait</code><span class="sig-paren">(</span><em>env</em><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSWait" title="Permalink to this definition">¶</a></dt> +<dd><p>Bases: <a class="reference internal" href="#options.simple_intersection.maneuver_base.ManeuverBase" title="options.simple_intersection.maneuver_base.ManeuverBase"><code class="xref py py-class docutils literal notranslate"><span class="pre">options.simple_intersection.maneuver_base.ManeuverBase</span></code></a></p> +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSWait.extra_initiation_condition"> +<code class="descname">extra_initiation_condition</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSWait.extra_initiation_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSWait.extra_termination_condition"> +<code class="descname">extra_termination_condition</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSWait.extra_termination_condition" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="method"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSWait.generate_learning_scenario"> +<code class="descname">generate_learning_scenario</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSWait.generate_learning_scenario" title="Permalink to this definition">¶</a></dt> +<dd></dd></dl> + +<dl class="attribute"> +<dt id="options.simple_intersection.mcts_maneuvers.MCTSWait.goal_achieved"> +<code class="descname">goal_achieved</code><a class="headerlink" href="#options.simple_intersection.mcts_maneuvers.MCTSWait.goal_achieved" title="Permalink to this definition">¶</a></dt> +<dd><p>Check whether the ego vehicle achieves the goal of the maneuver or +not.</p> +<p>By default, there is no goal, so the ego vehicle never achieves +it (i.e., goal_achieved is always False).</p> +</dd></dl> + +</dd></dl> + +</div> +<div class="section" id="module-options.simple_intersection"> +<span id="module-contents"></span><h2>Module contents<a class="headerlink" href="#module-options.simple_intersection" title="Permalink to this headline">¶</a></h2> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doc/ppo2_training.html b/documentation/sphinx/.build/.doc/ppo2_training.html new file mode 100644 index 0000000000000000000000000000000000000000..e107f8344ceedf50de9f86677ce8dcd87856811e --- /dev/null +++ b/documentation/sphinx/.build/.doc/ppo2_training.html @@ -0,0 +1,54 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>ppo2_training module — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>ppo2_training module</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="module-ppo2_training"> +<span id="ppo2-training-module"></span><h1>ppo2_training module<a class="headerlink" href="#module-ppo2_training" title="Permalink to this headline">¶</a></h1> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/.doctrees/.doc/backends.doctree b/documentation/sphinx/.build/.doctrees/.doc/backends.doctree new file mode 100644 index 0000000000000000000000000000000000000000..54ed373191d590a651e90ca9e5cefc70103a7c6f Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/backends.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/env.doctree b/documentation/sphinx/.build/.doctrees/.doc/env.doctree new file mode 100644 index 0000000000000000000000000000000000000000..1c932b51458ba40de60f64a1af78953cb6af8ab9 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/env.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/env.simple_intersection.doctree b/documentation/sphinx/.build/.doctrees/.doc/env.simple_intersection.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2d6b56f2f075019de9fc9606a07abbb87b7c1b1c Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/env.simple_intersection.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/high_level_policy_main.doctree b/documentation/sphinx/.build/.doctrees/.doc/high_level_policy_main.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e0156dc307cfd77996e42c975f5d492dcd1a6a29 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/high_level_policy_main.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/low_level_policy_main.doctree b/documentation/sphinx/.build/.doctrees/.doc/low_level_policy_main.doctree new file mode 100644 index 0000000000000000000000000000000000000000..27c03da8f6d7e8cafc2013d482f5959a95aa467c Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/low_level_policy_main.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/mcts.doctree b/documentation/sphinx/.build/.doctrees/.doc/mcts.doctree new file mode 100644 index 0000000000000000000000000000000000000000..24b9665115187d8227050d5da781e1825fc98075 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/mcts.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/model_checker.doctree b/documentation/sphinx/.build/.doctrees/.doc/model_checker.doctree new file mode 100644 index 0000000000000000000000000000000000000000..45f07f2ff35ae85c068394697e5ec736790e15f2 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/model_checker.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/model_checker.simple_intersection.doctree b/documentation/sphinx/.build/.doctrees/.doc/model_checker.simple_intersection.doctree new file mode 100644 index 0000000000000000000000000000000000000000..74fd9cd758553805c2dad3b24459f55ad71b1721 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/model_checker.simple_intersection.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/modules.doctree b/documentation/sphinx/.build/.doctrees/.doc/modules.doctree new file mode 100644 index 0000000000000000000000000000000000000000..6f6ea44362e6dff3a75f4d91dbc07609bca81830 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/modules.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/options.doctree b/documentation/sphinx/.build/.doctrees/.doc/options.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2af45197bb558f31afa26ec4dce5208d05d4482c Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/options.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/options.simple_intersection.doctree b/documentation/sphinx/.build/.doctrees/.doc/options.simple_intersection.doctree new file mode 100644 index 0000000000000000000000000000000000000000..47fb3231e29b9df8dbd224a0eccf1e6e186cd6db Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/options.simple_intersection.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/.doc/ppo2_training.doctree b/documentation/sphinx/.build/.doctrees/.doc/ppo2_training.doctree new file mode 100644 index 0000000000000000000000000000000000000000..fc91215a7f084853fd8947d963268c9c39933992 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/.doc/ppo2_training.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/environment.pickle b/documentation/sphinx/.build/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..82aca56c04f4313da34b1ce053b9ec0b3552a4ec Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/environment.pickle differ diff --git a/documentation/sphinx/.build/.doctrees/index.doctree b/documentation/sphinx/.build/.doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..0c65cbcd9da0ab7884ebdd41f87586e726eaea56 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/index.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/usage/config.doctree b/documentation/sphinx/.build/.doctrees/usage/config.doctree new file mode 100644 index 0000000000000000000000000000000000000000..1137b5480589561033102cae42e512c24a409836 Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/usage/config.doctree differ diff --git a/documentation/sphinx/.build/.doctrees/usage/quickstart.doctree b/documentation/sphinx/.build/.doctrees/usage/quickstart.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b11cf681cae88029ff5f34ffe2ccb204439c07da Binary files /dev/null and b/documentation/sphinx/.build/.doctrees/usage/quickstart.doctree differ diff --git a/documentation/sphinx/.build/_sources/.doc/backends.rst.txt b/documentation/sphinx/.build/_sources/.doc/backends.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..367db99c0322ede126d227162e4437fdcc56330e --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/backends.rst.txt @@ -0,0 +1,86 @@ +backends package +================ + +Submodules +---------- + +backends.baselines\_learner module +---------------------------------- + +.. automodule:: backends.baselines_learner + :members: + :undoc-members: + :show-inheritance: + +backends.controller\_base module +-------------------------------- + +.. automodule:: backends.controller_base + :members: + :undoc-members: + :show-inheritance: + +backends.kerasrl\_learner module +-------------------------------- + +.. automodule:: backends.kerasrl_learner + :members: + :undoc-members: + :show-inheritance: + +backends.learner\_base module +----------------------------- + +.. automodule:: backends.learner_base + :members: + :undoc-members: + :show-inheritance: + +backends.manual\_policy module +------------------------------ + +.. automodule:: backends.manual_policy + :members: + :undoc-members: + :show-inheritance: + +backends.mcts\_learner module +----------------------------- + +.. automodule:: backends.mcts_learner + :members: + :undoc-members: + :show-inheritance: + +backends.online\_mcts\_controller module +---------------------------------------- + +.. automodule:: backends.online_mcts_controller + :members: + :undoc-members: + :show-inheritance: + +backends.policy\_base module +---------------------------- + +.. automodule:: backends.policy_base + :members: + :undoc-members: + :show-inheritance: + +backends.rl\_controller module +------------------------------ + +.. automodule:: backends.rl_controller + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: backends + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/env.rst.txt b/documentation/sphinx/.build/_sources/.doc/env.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..5ab6c48e78bb9468f4f522a1b4cec5837bb9ef5b --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/env.rst.txt @@ -0,0 +1,37 @@ +env package +=========== + +Subpackages +----------- + +.. toctree:: + + env.simple_intersection + +Submodules +---------- + +env.env\_base module +-------------------- + +.. automodule:: env.env_base + :members: + :undoc-members: + :show-inheritance: + +env.road\_env module +-------------------- + +.. automodule:: env.road_env + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: env + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/env.simple_intersection.rst.txt b/documentation/sphinx/.build/_sources/.doc/env.simple_intersection.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..d66d3b456ba15212333de2b11737bb2bd0e901ce --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/env.simple_intersection.rst.txt @@ -0,0 +1,86 @@ +env.simple\_intersection package +================================ + +Submodules +---------- + +env.simple\_intersection.constants module +----------------------------------------- + +.. automodule:: env.simple_intersection.constants + :members: + :undoc-members: + :show-inheritance: + +env.simple\_intersection.features module +---------------------------------------- + +.. automodule:: env.simple_intersection.features + :members: + :undoc-members: + :show-inheritance: + +env.simple\_intersection.road\_geokinemetry module +-------------------------------------------------- + +.. automodule:: env.simple_intersection.road_geokinemetry + :members: + :undoc-members: + :show-inheritance: + +env.simple\_intersection.road\_networks module +---------------------------------------------- + +.. automodule:: env.simple_intersection.road_networks + :members: + :undoc-members: + :show-inheritance: + +env.simple\_intersection.shapes module +-------------------------------------- + +.. automodule:: env.simple_intersection.shapes + :members: + :undoc-members: + :show-inheritance: + +env.simple\_intersection.simple\_intersection\_env module +--------------------------------------------------------- + +.. automodule:: env.simple_intersection.simple_intersection_env + :members: + :undoc-members: + :show-inheritance: + +env.simple\_intersection.utilities module +----------------------------------------- + +.. automodule:: env.simple_intersection.utilities + :members: + :undoc-members: + :show-inheritance: + +env.simple\_intersection.vehicle\_networks module +------------------------------------------------- + +.. automodule:: env.simple_intersection.vehicle_networks + :members: + :undoc-members: + :show-inheritance: + +env.simple\_intersection.vehicles module +---------------------------------------- + +.. automodule:: env.simple_intersection.vehicles + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: env.simple_intersection + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/high_level_policy_main.rst.txt b/documentation/sphinx/.build/_sources/.doc/high_level_policy_main.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..ca75adab3676d03ec342fd3294e903d7ce1eaa6e --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/high_level_policy_main.rst.txt @@ -0,0 +1,7 @@ +high\_level\_policy\_main module +================================ + +.. automodule:: high_level_policy_main + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/low_level_policy_main.rst.txt b/documentation/sphinx/.build/_sources/.doc/low_level_policy_main.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..edaabe8007c98666299e0969e704c722cbc97b8f --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/low_level_policy_main.rst.txt @@ -0,0 +1,7 @@ +low\_level\_policy\_main module +=============================== + +.. automodule:: low_level_policy_main + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/mcts.rst.txt b/documentation/sphinx/.build/_sources/.doc/mcts.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..373395e4eefe01ac995c1cf9e9ff26382488cae6 --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/mcts.rst.txt @@ -0,0 +1,7 @@ +mcts module +=========== + +.. automodule:: mcts + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/model_checker.rst.txt b/documentation/sphinx/.build/_sources/.doc/model_checker.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..01b5acedfaa48cb1e906e5b5379a8bbaac65f699 --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/model_checker.rst.txt @@ -0,0 +1,53 @@ +model\_checker package +====================== + +Subpackages +----------- + +.. toctree:: + + model_checker.simple_intersection + +Submodules +---------- + +model\_checker.LTL\_property\_base module +----------------------------------------- + +.. automodule:: model_checker.LTL_property_base + :members: + :undoc-members: + :show-inheritance: + +model\_checker.atomic\_propositions\_base module +------------------------------------------------ + +.. automodule:: model_checker.atomic_propositions_base + :members: + :undoc-members: + :show-inheritance: + +model\_checker.parser module +---------------------------- + +.. automodule:: model_checker.parser + :members: + :undoc-members: + :show-inheritance: + +model\_checker.scanner module +----------------------------- + +.. automodule:: model_checker.scanner + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: model_checker + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/model_checker.simple_intersection.rst.txt b/documentation/sphinx/.build/_sources/.doc/model_checker.simple_intersection.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..0859f202f9266745e1455af901512cd85f66d136 --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/model_checker.simple_intersection.rst.txt @@ -0,0 +1,38 @@ +model\_checker.simple\_intersection package +=========================================== + +Submodules +---------- + +model\_checker.simple\_intersection.AP\_dict module +--------------------------------------------------- + +.. automodule:: model_checker.simple_intersection.AP_dict + :members: + :undoc-members: + :show-inheritance: + +model\_checker.simple\_intersection.LTL\_test module +---------------------------------------------------- + +.. automodule:: model_checker.simple_intersection.LTL_test + :members: + :undoc-members: + :show-inheritance: + +model\_checker.simple\_intersection.classes module +-------------------------------------------------- + +.. automodule:: model_checker.simple_intersection.classes + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: model_checker.simple_intersection + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/modules.rst.txt b/documentation/sphinx/.build/_sources/.doc/modules.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..6f654d3e26c07ee7cd061a2fc00cec3b54426490 --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/modules.rst.txt @@ -0,0 +1,14 @@ +wisemove +======== + +.. toctree:: + :maxdepth: 4 + + backends + env + high_level_policy_main + low_level_policy_main + mcts + model_checker + options + ppo2_training diff --git a/documentation/sphinx/.build/_sources/.doc/options.rst.txt b/documentation/sphinx/.build/_sources/.doc/options.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..afa47920fc6ad97ddc397ee233b0645eeff9dcec --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/options.rst.txt @@ -0,0 +1,29 @@ +options package +=============== + +Subpackages +----------- + +.. toctree:: + + options.simple_intersection + +Submodules +---------- + +options.options\_loader module +------------------------------ + +.. automodule:: options.options_loader + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: options + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/options.simple_intersection.rst.txt b/documentation/sphinx/.build/_sources/.doc/options.simple_intersection.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..888c74c9861b4dbf579eb7966ab8348165cccde1 --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/options.simple_intersection.rst.txt @@ -0,0 +1,38 @@ +options.simple\_intersection package +==================================== + +Submodules +---------- + +options.simple\_intersection.maneuver\_base module +-------------------------------------------------- + +.. automodule:: options.simple_intersection.maneuver_base + :members: + :undoc-members: + :show-inheritance: + +options.simple\_intersection.maneuvers module +--------------------------------------------- + +.. automodule:: options.simple_intersection.maneuvers + :members: + :undoc-members: + :show-inheritance: + +options.simple\_intersection.mcts\_maneuvers module +--------------------------------------------------- + +.. automodule:: options.simple_intersection.mcts_maneuvers + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: options.simple_intersection + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/.doc/ppo2_training.rst.txt b/documentation/sphinx/.build/_sources/.doc/ppo2_training.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..916a7f8f909b15c0080856b8a33ce98410fd9c35 --- /dev/null +++ b/documentation/sphinx/.build/_sources/.doc/ppo2_training.rst.txt @@ -0,0 +1,7 @@ +ppo2\_training module +===================== + +.. automodule:: ppo2_training + :members: + :undoc-members: + :show-inheritance: diff --git a/documentation/sphinx/.build/_sources/index.rst.txt b/documentation/sphinx/.build/_sources/index.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..b6cbd66157cf20bd657ebf949ba0bf8bf0707ff2 --- /dev/null +++ b/documentation/sphinx/.build/_sources/index.rst.txt @@ -0,0 +1,25 @@ +.. saferl documentation master file, created by + sphinx-quickstart on Tue Sep 4 16:50:18 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +######## +Contents +######## + +User Guide +=========== +.. toctree:: + :maxdepth: 2 + + usage/quickstart + +Code documentation +================== + +* :ref:`genindex` +* :ref:`modindex` + +Search +================== +* :ref:`search` diff --git a/documentation/sphinx/.build/_sources/usage/config.rst.txt b/documentation/sphinx/.build/_sources/usage/config.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..913e769e177b28edf98b4cb3c61bb3b2466b57c6 --- /dev/null +++ b/documentation/sphinx/.build/_sources/usage/config.rst.txt @@ -0,0 +1,5 @@ +================== +Configuration File +================== + +:code:`config.json` can be used to select the maneuvers and high_level policy for fast experimentation. \ No newline at end of file diff --git a/documentation/sphinx/.build/_sources/usage/quickstart.rst.txt b/documentation/sphinx/.build/_sources/usage/quickstart.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..d1f825abca85a1afb51112e0f6c81bc670ab1d96 --- /dev/null +++ b/documentation/sphinx/.build/_sources/usage/quickstart.rst.txt @@ -0,0 +1,174 @@ +########### +Quick Start +########### + +=========== +Environment +=========== + +An environment that supports the use of options is already provided with the framework, called *simple-intersection*, which is an autonomous driving environment consisting of a single intersection with two-lane roads. The objective of the agent (the controllable vehicle) is to reach the other side of the intersection while obeying some defined traffic rules and without crashing. The agent takes rate of change of steering angle and acceleration as an input. + +The environment supports the use of options/maneuvers, which model certain favourable behaviours. The number and type of maneuver are up to the user to define, but this framework comes with a few pre-defined maneuvers: + +* keeplane (drive on the current lane) +* changelane (change to the other lane) +* stop (come to a stop at a stop sign) +* wait (wait at the stop sign until safe) +* follow (follow the vehicle in front). + +================== +Low-level Policies +================== +The policy for executing each maneuver is referred to as the low-level policy, which provides the agent with an input depending on the current state. They can be both manually-defined or learned. For the simple-intersection environment, low-level policies learned using reinforcement learning are provided in the framework. Learning is done using `low_level_policy_main.py`. Use :code:`low_level_policy_main.py --help` to view supported arguments and defaults. + +:: + + usage: low_level_policy_main.py [-h] [--train] [--option] [--test] + [--saved_policy_in_root] [--load_weights] + [--tensorboard] [--visualize] + [--nb_steps NB_STEPS] + [--nb_episodes_for_test NB_EPISODES_FOR_TEST] + + optional arguments: + -h, --help show this help message and exit + --train Train a high-level policy with default settings. + Always saved in the root folder. Always tests after + training + --option the option to train. Eg. stop, keeplane, wait, + changelane, follow. If not defined, trains all options + --test Test a saved high-level policy. Uses backends/trained_ + policies/highlevel/highlevel_weights.h5f by default + --saved_policy_in_root + Use saved policies in the root of the project rather than + backends/trained_policies/highlevel/ + --load_weights Load a saved policy first before training + --tensorboard Use tensorboard while training + --visualize Visualize the training. Testing is always visualized. + --nb_steps NB_STEPS Number of steps to train for. Default is 100000 + --nb_episodes_for_test NB_EPISODES_FOR_TEST + The number of episodes to test. Default is 20 + +Training +======== +Run :code:`low_level_policy_main.py --train --option=OPTION_NAME`, where OPTION_NAME can be the key of any node defined in `config.json <../../../../config.json>`_ to learn the option using reinforcement learning default settings and save the result to root folder. If no option is specified, all options are trained. The training can be customized further using other supported arguments. For example, to train keeplane maneuver and visualize the training, run: + +:: + + python low_level_policy_main.py --train --option=keeplane --visualize + +Testing +======= +Run :code:`low_level_policy_main.py --test --option=OPTION_NAME` along with other supported arguments to test the trained policy. By default, uses the trained policies in `/backends/trained_policies`. For example: + +:: + + python low_level_policy_main.py --test --option=wait --nb_episodes_for_test=20 + +================= +High-level Policy +================= +By composing smaller maneuvers together, the objective can be achieved. It is also possible to have just one maneuver, called 'drive' and train it to achieve the goal but it is much harder than defining smaller easy-to-achieve maneuvers and composing them together. This composing of the maneuvers is done by the high-level policy. It decides which maneuver to execute according to the state of the environment. + +The high-level policy can also be manually-defined or learned. This framework comes with one learned with reinforcement learning for the simple-intersection environment. Learning is done using `high_level_policy_main.py`. Use :code:`high_level_policy_main.py --help` to view supported arguments and defaults. + +:: + + usage: high_level_policy_main.py [-h] [--train] [--test] [--evaluate] + [--saved_policy_in_root] [--load_weights] + [--tensorboard] [--visualize] + [--nb_steps NB_STEPS] + [--nb_episodes_for_test NB_EPISODES_FOR_TEST] + [--nb_trials NB_TRIALS] + [--save_file SAVE_FILE] + + optional arguments: + -h, --help show this help message and exit + --train Train a high-level policy with default settings. + Always saved in the root folder. Always tests after + training + --test Test a saved high-level policy. Uses backends/trained_ + policies/highlevel/highlevel_weights.h5f by default + --evaluate Evaluate a saved high level policy over n trials. Uses + backends/trained_policies/highlevel/highlevel_weights. + h5f by default + --saved_policy_in_root + Use saved policies in the root of the project rather than + backends/trained_policies/highlevel/ (which is default) + --load_weights Load a saved policy from root folder first before training + --tensorboard Use tensorboard while training + --visualize Visualize the training. Testing is always visualized. + Evaluation is not visualized by default + --nb_steps NB_STEPS Number of steps to train for. Default is 25000 + --nb_episodes_for_test NB_EPISODES_FOR_TEST + The number of episodes to test/evaluate. Default is 20 + --nb_trials NB_TRIALS + The number of trials to evaluate. Default is 10 + --save_file SAVE_FILE + filename to save/load the trained policy. Location is + as specified by --saved_policy_in_root + +Training +======== +Run :code:`high_level_policy_main.py --train` along with other supported arguments to train a policy using reinforcement learning default settings. By default, it is saved to the root folder so as not to overwrite already trained policies. For example: + +:: + + high_level_policy_training.py --train --nb_steps=25000 --nb_episodes_for_test=20 + +Testing +======= +Run :code:`high_level_policy_main.py --test` or :code:`high_level_policy_main.py --evaluate` along with other supported arguments to test the trained policy. By default, uses the trained policies in `/backends/trained_policies/highlevel`. For example: + +:: + + high_level_policy_training.py --evaluate --nb_trials=5 --nb_episodes_for_test=20 + +============== +Model Checking +============== + +Both low-level and high-level policies, while being trained, use model checking to ensure that user-defined temporal logic constraints are not violated. The user can define global LTL properties that apply to all maneuvers as well as maneuver-specific LTL constraints. + +Atomic Propositions +=================== +Atomic propositions for the simple_intersection environment are defined as human-readable strings in `model_checker/simple_intersection/AP_dict.py`. These should evaluate to True or False depending on the state of the environment and they need to be updated in every step of the environment. The temporal logic properties are constructed using a combination of atomic propositions and logic operators. + +Linear Temporal Logic +===================== +Global temporal logic properties are defined in `env/simple_intersection/simple_intersection_env.py` in _init_LTL_preconditions() function. For example, to add a global constraint that speed must not go beyond speed-limit, you may add :code:`self._LTL_preconditions.append(LTLProperty("G( not over_speed_limit)", 200))` to give a penalty of -200 if the agent crosses the speed limit while using any maneuver. + +Maneuver-specific LTL properties can be defined in the corresponding maneuver class in `options/simple_intersection/manuevers.py` in _init_LTL_preconditions() function. + +Temporal logic properties are specified using the following syntactic forms, where literal strings are given within quotation marks. + +============== ========================= + Form Meaning +============== ========================= +"F" phi Finally, eventually +"G" phi Globally, always +"X" phi neXt state +phi "U" phi Until +phi "=>" phi logical implication +phi "or" phi logical or +phi "and" phi logical and +"not" phi logical negation +"(" phi ")" parenthetic grouping +atomic atomic_proposition_string +============== ========================= + +Operator precedence (evaluation order), highest first, is: {atomic, "("...")"} > "not" > "and" > "or" > "=>" > {"F", "G", "X", "U"} + +Nested temporal operators must be enclosed in parentheses, e.g. G in_stop_region => (in_stop_region U has_stopped_in_stop_region). + +Note that the arguments of "U" should be predicates over atomic propositions. + +======================= +Monte-Carlo Tree Search +======================= +Even after using such a hierarchical structure and model-checking during learning, collisions and constraint violations can be inevitable because the policies are never perfect. This framework supports the safe execution of the high-level policy by using an MCTS to look ahead in time and choose paths that do not lead to a collision or a temporal logic violation. `mcts.py` is used to execute the learned policies using MCTS. As online execution can be computationally expensive the framework also provides an offline version of MCTS that learns probabilities of safe paths and uses it to enhance trained policies. + +================ +Learning Backend +================ + +The framework also supports multiple learning backends and it is easy to add and use other ones as necessary. The KerasRL reinforcement learning framework was used to learn and test policies for the simple-intersection environment using `backends/kerasrl_learner.py`. The stable-baselines library has also been incorporated in `backends/baselines_learner.py`. \ No newline at end of file diff --git a/documentation/sphinx/.build/_static/ajax-loader.gif b/documentation/sphinx/.build/_static/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..61faf8cab23993bd3e1560bff0668bd628642330 Binary files /dev/null and b/documentation/sphinx/.build/_static/ajax-loader.gif differ diff --git a/documentation/sphinx/.build/_static/alert_info_32.png b/documentation/sphinx/.build/_static/alert_info_32.png new file mode 100644 index 0000000000000000000000000000000000000000..ea4d1baf7001be1d988ca82c2ac4d65803589915 Binary files /dev/null and b/documentation/sphinx/.build/_static/alert_info_32.png differ diff --git a/documentation/sphinx/.build/_static/alert_warning_32.png b/documentation/sphinx/.build/_static/alert_warning_32.png new file mode 100644 index 0000000000000000000000000000000000000000..a687c3dca8d5241b584f69e28b230d9ec78a5a03 Binary files /dev/null and b/documentation/sphinx/.build/_static/alert_warning_32.png differ diff --git a/documentation/sphinx/.build/_static/basic.css b/documentation/sphinx/.build/_static/basic.css new file mode 100644 index 0000000000000000000000000000000000000000..c7adab456bded4d28e309d9a83fe053d2a6de07b --- /dev/null +++ b/documentation/sphinx/.build/_static/basic.css @@ -0,0 +1,665 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 59em; + max-width: 70em; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +div.code-block-caption { + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +div.code-block-caption + div > div.highlight > pre { + margin-top: 0; +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + padding: 1em 1em 0; +} + +div.literal-block-wrapper div.highlight { + margin: 0; +} + +code.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +code.descclassname { + background-color: transparent; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: relative; + left: 0px; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/documentation/sphinx/.build/_static/bg-page.png b/documentation/sphinx/.build/_static/bg-page.png new file mode 100644 index 0000000000000000000000000000000000000000..fe0a6dc896e0e3a5b7a5cdf37d07bcbc5c9a00cf Binary files /dev/null and b/documentation/sphinx/.build/_static/bg-page.png differ diff --git a/documentation/sphinx/.build/_static/bullet_orange.png b/documentation/sphinx/.build/_static/bullet_orange.png new file mode 100644 index 0000000000000000000000000000000000000000..1cb8097ce9b7592811e6ca10397ffe913e62503a Binary files /dev/null and b/documentation/sphinx/.build/_static/bullet_orange.png differ diff --git a/documentation/sphinx/.build/_static/comment-bright.png b/documentation/sphinx/.build/_static/comment-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..15e27edb12ac25701ac0ac21b97b52bb4e45415e Binary files /dev/null and b/documentation/sphinx/.build/_static/comment-bright.png differ diff --git a/documentation/sphinx/.build/_static/comment-close.png b/documentation/sphinx/.build/_static/comment-close.png new file mode 100644 index 0000000000000000000000000000000000000000..4d91bcf57de866a901a89a2a68c0f36af1114841 Binary files /dev/null and b/documentation/sphinx/.build/_static/comment-close.png differ diff --git a/documentation/sphinx/.build/_static/comment.png b/documentation/sphinx/.build/_static/comment.png new file mode 100644 index 0000000000000000000000000000000000000000..dfbc0cbd512bdeefcb1984c99d8e577efb77f006 Binary files /dev/null and b/documentation/sphinx/.build/_static/comment.png differ diff --git a/documentation/sphinx/.build/_static/css/LibreBaskerville-Regular.ttf b/documentation/sphinx/.build/_static/css/LibreBaskerville-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..57e3c23b5250fa5b1e61277e6f47f2d56c3194b8 Binary files /dev/null and b/documentation/sphinx/.build/_static/css/LibreBaskerville-Regular.ttf differ diff --git a/documentation/sphinx/.build/_static/css/OverpassMono-Regular.ttf b/documentation/sphinx/.build/_static/css/OverpassMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..67bdb9a8dbe28b60dd71e0cd9ec035b9d959cc3c Binary files /dev/null and b/documentation/sphinx/.build/_static/css/OverpassMono-Regular.ttf differ diff --git a/documentation/sphinx/.build/_static/css/OverpassMono-SemiBold.ttf b/documentation/sphinx/.build/_static/css/OverpassMono-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5109b5b88a5c7378b4e0cb630eb706fd4362e0c2 Binary files /dev/null and b/documentation/sphinx/.build/_static/css/OverpassMono-SemiBold.ttf differ diff --git a/documentation/sphinx/.build/_static/css/fonts.css b/documentation/sphinx/.build/_static/css/fonts.css new file mode 100644 index 0000000000000000000000000000000000000000..6e16fc8d4d3a3b3047021cb6a39f8244ca0cafae --- /dev/null +++ b/documentation/sphinx/.build/_static/css/fonts.css @@ -0,0 +1,14 @@ +@font-face { + font-family: "LibreBaskerville"; + src: url("LibreBaskerville-Regular.ttf"); +} +@font-face { + font-family: "OverpassMono"; + src: url("OverpassMono-Regular.ttf"); +} +body, p, ul, ol, li, table { + font-family: LibreBaskerville, Optima, Candara, Calibri, Arial, sans-serif; +} +code, code#descclassname, code#descname, span#pre { + font-family: OverpassMono, "Lucida Console", Monaco, monospace; +} diff --git a/documentation/sphinx/.build/_static/doctools.js b/documentation/sphinx/.build/_static/doctools.js new file mode 100644 index 0000000000000000000000000000000000000000..d8928926bf24bb081d91a12f7b92e1b2d8b142b6 --- /dev/null +++ b/documentation/sphinx/.build/_static/doctools.js @@ -0,0 +1,313 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var bbox = span.getBBox(); + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + var parentOfText = node.parentNode.parentNode; + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('<a class="headerlink">\u00B6</a>'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('<a class="headerlink">\u00B6</a>'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('<p class="highlight-link"><a href="javascript:Documentation.' + + 'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keyup(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box or textarea + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); \ No newline at end of file diff --git a/documentation/sphinx/.build/_static/documentation_options.js b/documentation/sphinx/.build/_static/documentation_options.js new file mode 100644 index 0000000000000000000000000000000000000000..893cd39b3bd6e1a4eb1f3fe2f4caecd1a664f98f --- /dev/null +++ b/documentation/sphinx/.build/_static/documentation_options.js @@ -0,0 +1,9 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + FILE_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt' +}; \ No newline at end of file diff --git a/documentation/sphinx/.build/_static/down-pressed.png b/documentation/sphinx/.build/_static/down-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..5756c8cad8854722893dc70b9eb4bb0400343a39 Binary files /dev/null and b/documentation/sphinx/.build/_static/down-pressed.png differ diff --git a/documentation/sphinx/.build/_static/down.png b/documentation/sphinx/.build/_static/down.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3bdad2ceffae91cee61b32f3295f9bbe646e48 Binary files /dev/null and b/documentation/sphinx/.build/_static/down.png differ diff --git a/documentation/sphinx/.build/_static/file.png b/documentation/sphinx/.build/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 Binary files /dev/null and b/documentation/sphinx/.build/_static/file.png differ diff --git a/documentation/sphinx/.build/_static/haiku.css b/documentation/sphinx/.build/_static/haiku.css new file mode 100644 index 0000000000000000000000000000000000000000..75af2a5c4955c609c458e25a908f15e1d88209a9 --- /dev/null +++ b/documentation/sphinx/.build/_static/haiku.css @@ -0,0 +1,376 @@ +/* + * haiku.css_t + * ~~~~~~~~~~~ + * + * Sphinx stylesheet -- haiku theme. + * + * Adapted from http://haiku-os.org/docs/Haiku-doc.css. + * Original copyright message: + * + * Copyright 2008-2009, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Francois Revol <revol@free.fr> + * Stephan Assmus <superstippi@gmx.de> + * Braden Ewing <brewin@gmail.com> + * Humdinger <humdingerb@gmail.com> + * + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +html { + margin: 0px; + padding: 0px; + background: #FFF url(bg-page.png) top left repeat-x; +} + +body { + line-height: 1.5; + margin: auto; + padding: 0px; + font-family: "DejaVu Sans", Arial, Helvetica, sans-serif; + min-width: 59em; + max-width: 70em; + color: #333333; +} + +div.footer { + padding: 8px; + font-size: 11px; + text-align: center; + letter-spacing: 0.5px; +} + +/* link colors and text decoration */ + +a:link { + font-weight: bold; + text-decoration: none; + color: #dc3c01; +} + +a:visited { + font-weight: bold; + text-decoration: none; + color: #892601; +} + +a:hover, a:active { + text-decoration: underline; + color: #ff4500; +} + +/* Some headers act as anchors, don't give them a hover effect */ + +h1 a:hover, a:active { + text-decoration: none; + color: #0c3762; +} + +h2 a:hover, a:active { + text-decoration: none; + color: #0c3762; +} + +h3 a:hover, a:active { + text-decoration: none; + color: #0c3762; +} + +h4 a:hover, a:active { + text-decoration: none; + color: #0c3762; +} + +a.headerlink { + color: #a7ce38; + padding-left: 5px; +} + +a.headerlink:hover { + color: #a7ce38; +} + +/* basic text elements */ + +div.content { + margin-top: 20px; + margin-left: 40px; + margin-right: 40px; + margin-bottom: 50px; + font-size: 0.9em; +} + +/* heading and navigation */ + +div.header { + position: relative; + left: 0px; + top: 0px; + height: 85px; + /* background: #eeeeee; */ + padding: 0 40px; +} +div.header h1 { + font-size: 1.6em; + font-weight: normal; + letter-spacing: 1px; + color: #0c3762; + border: 0; + margin: 0; + padding-top: 15px; +} +div.header h1 a { + font-weight: normal; + color: #0c3762; +} +div.header h2 { + font-size: 1.3em; + font-weight: normal; + letter-spacing: 1px; + text-transform: uppercase; + color: #aaa; + border: 0; + margin-top: -3px; + padding: 0; +} + +div.header img.rightlogo { + float: right; +} + + +div.title { + font-size: 1.3em; + font-weight: bold; + color: #0c3762; + border-bottom: dotted thin #e0e0e0; + margin-bottom: 25px; +} +div.topnav { + /* background: #e0e0e0; */ +} +div.topnav p { + margin-top: 0; + margin-left: 40px; + margin-right: 40px; + margin-bottom: 0px; + text-align: right; + font-size: 0.8em; +} +div.bottomnav { + background: #eeeeee; +} +div.bottomnav p { + margin-right: 40px; + text-align: right; + font-size: 0.8em; +} + +a.uplink { + font-weight: normal; +} + + +/* contents box */ + +table.index { + margin: 0px 0px 30px 30px; + padding: 1px; + border-width: 1px; + border-style: dotted; + border-color: #e0e0e0; +} +table.index tr.heading { + background-color: #e0e0e0; + text-align: center; + font-weight: bold; + font-size: 1.1em; +} +table.index tr.index { + background-color: #eeeeee; +} +table.index td { + padding: 5px 20px; +} + +table.index a:link, table.index a:visited { + font-weight: normal; + text-decoration: none; + color: #dc3c01; +} +table.index a:hover, table.index a:active { + text-decoration: underline; + color: #ff4500; +} + + +/* Haiku User Guide styles and layout */ + +/* Rounded corner boxes */ +/* Common declarations */ +div.admonition { + -webkit-border-radius: 10px; + -khtml-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; + border-style: dotted; + border-width: thin; + border-color: #dcdcdc; + padding: 10px 15px 10px 15px; + margin-bottom: 15px; + margin-top: 15px; +} +div.note { + padding: 10px 15px 10px 80px; + background: #e4ffde url(alert_info_32.png) 15px 15px no-repeat; + min-height: 42px; +} +div.warning { + padding: 10px 15px 10px 80px; + background: #fffbc6 url(alert_warning_32.png) 15px 15px no-repeat; + min-height: 42px; +} +div.seealso { + background: #e4ffde; +} + +/* More layout and styles */ +h1 { + font-size: 1.3em; + font-weight: bold; + color: #0c3762; + border-bottom: dotted thin #e0e0e0; + margin-top: 30px; +} + +h2 { + font-size: 1.2em; + font-weight: normal; + color: #0c3762; + border-bottom: dotted thin #e0e0e0; + margin-top: 30px; +} + +h3 { + font-size: 1.1em; + font-weight: normal; + color: #0c3762; + margin-top: 30px; +} + +h4 { + font-size: 1.0em; + font-weight: normal; + color: #0c3762; + margin-top: 30px; +} + +p { + text-align: justify; +} + +p.last { + margin-bottom: 0; +} + +ol { + padding-left: 20px; +} + +ul { + padding-left: 5px; + margin-top: 3px; +} + +li { + line-height: 1.3; +} + +div.content ul > li { + -moz-background-clip:border; + -moz-background-inline-policy:continuous; + -moz-background-origin:padding; + background: transparent url(bullet_orange.png) no-repeat scroll left 0.45em; + list-style-image: none; + list-style-type: none; + padding: 0 0 0 1.666em; + margin-bottom: 3px; +} + +td { + vertical-align: top; +} + +code { + background-color: #e2e2e2; + font-size: 1.0em; + font-family: monospace; +} + +pre { + border-color: #0c3762; + border-style: dotted; + border-width: thin; + margin: 0 0 12px 0; + padding: 0.8em; + background-color: #f0f0f0; +} + +hr { + border-top: 1px solid #ccc; + border-bottom: 0; + border-right: 0; + border-left: 0; + margin-bottom: 10px; + margin-top: 20px; +} + +/* printer only pretty stuff */ +@media print { + .noprint { + display: none; + } + /* for acronyms we want their definitions inlined at print time */ + acronym[title]:after { + font-size: small; + content: " (" attr(title) ")"; + font-style: italic; + } + /* and not have mozilla dotted underline */ + acronym { + border: none; + } + div.topnav, div.bottomnav, div.header, table.index { + display: none; + } + div.content { + margin: 0px; + padding: 0px; + } + html { + background: #FFF; + } +} + +.viewcode-back { + font-family: "DejaVu Sans", Arial, Helvetica, sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; + margin: -1px -10px; + padding: 0 12px; +} + +/* math display */ +div.math p { + text-align: center; +} \ No newline at end of file diff --git a/documentation/sphinx/.build/_static/jquery-3.2.1.js b/documentation/sphinx/.build/_static/jquery-3.2.1.js new file mode 100644 index 0000000000000000000000000000000000000000..d2d8ca4790e52b0537f3cbb7dcd766099b789583 --- /dev/null +++ b/documentation/sphinx/.build/_static/jquery-3.2.1.js @@ -0,0 +1,10253 @@ +/*! + * jQuery JavaScript Library v3.2.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2017-03-20T18:59Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + + + + function DOMEval( code, doc ) { + doc = doc || document; + + var script = doc.createElement( "script" ); + + script.text = code; + doc.head.appendChild( script ).parentNode.removeChild( script ); + } +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.2.1", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + + // As of jQuery 3.0, isNumeric is limited to + // strings and numbers (primitives or objects) + // that can be coerced to finite numbers (gh-2662) + var type = jQuery.type( obj ); + return ( type === "number" || type === "string" ) && + + // parseFloat NaNs numeric-cast false positives ("") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + !isNaN( obj - parseFloat( obj ) ); + }, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE <=9 - 11, Edge 12 - 13 + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" + + "<select id='" + expando + "-\r\\' msallowcapture=''>" + + "<option selected=''></option></select>"; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "<a href='' disabled='disabled'></a>" + + "<select disabled='disabled'><option/></select>"; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = "<a href='#'></a>"; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = "<input/>"; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Simple selector that can be filtered directly, removing non-Elements + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + // Complex selector, compare the two sets, removing non-Elements + qualifier = jQuery.filter( qualifier, elements ); + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1; + } ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( jQuery.isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && jQuery.isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( jQuery.isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ jQuery.camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ jQuery.camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( jQuery.camelCase ); + } else { + key = jQuery.camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, + scale = 1, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + do { + + // If previous iteration zeroed out, double until we get *something*. + // Use string for doubling so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + initialInUnit = initialInUnit / scale; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // Break the loop if scale is unchanged or perfect, or if we've just had enough. + } while ( + scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations + ); + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "<select multiple='multiple'>", "</select>" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting <tbody> or other required elements. + thead: [ 1, "<table>", "</table>" ], + col: [ 2, "<table><colgroup>", "</colgroup></table>" ], + tr: [ 2, "<table><tbody>", "</tbody></table>" ], + td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = "<textarea>x</textarea>"; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG <use> instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: jQuery.isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /<script|<style|<link/i, + + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptTypeMasked = /^true\/(.*)/, + rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( ">tbody", elem )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1></$2>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rmargin = ( /^margin/ ); + +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + div.style.cssText = + "box-sizing:border-box;" + + "position:relative;display:block;" + + "margin:auto;border:1px;padding:1px;" + + "top:1%;width:50%"; + div.innerHTML = ""; + documentElement.appendChild( container ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = divStyle.marginLeft === "2px"; + boxSizingReliableVal = divStyle.width === "4px"; + + // Support: Android 4.0 - 4.3 only + // Some styles come back with percentage values, even though they shouldn't + div.style.marginRight = "50%"; + pixelMarginRightVal = divStyle.marginRight === "4px"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" + + "padding:0;margin-top:1px;position:absolute"; + container.appendChild( div ); + + jQuery.extend( support, { + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelMarginRight: function() { + computeStyleTests(); + return pixelMarginRightVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i, + val = 0; + + // If we already have the right measurement, avoid augmentation + if ( extra === ( isBorderBox ? "border" : "content" ) ) { + i = 4; + + // Otherwise initialize for horizontal or vertical properties + } else { + i = name === "width" ? 1 : 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // At this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + + // At this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // At this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with computed style + var valueIsBorderBox, + styles = getStyles( elem ), + val = curCSS( elem, name, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test( val ) ) { + return val; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && + ( support.boxSizingReliable() || val === elem.style[ name ] ); + + // Fall back to offsetWidth/Height when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + if ( val === "auto" ) { + val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ]; + } + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + + // Use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + "float": "cssFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = jQuery.camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, name, extra ); + } ) : + getWidthOrHeight( elem, name, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = extra && getStyles( elem ), + subtract = extra && augmentWidthOrHeight( + elem, + name, + extra, + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + styles + ); + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ name ] = value; + value = jQuery.css( elem, name ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( !rmargin.test( prefix ) ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = jQuery.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 13 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = jQuery.camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( jQuery.isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + jQuery.proxy( result.stop, result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( jQuery.isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( jQuery.isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = jQuery.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnothtmlwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnothtmlwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( type === "string" ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = value.match( rnothtmlwhite ) || []; + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, isFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup contextmenu" ).split( " " ), + function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +} ); + +jQuery.fn.extend( { + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +} ); + + + + +support.focusin = "onfocusin" in window; + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = jQuery.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && jQuery.type( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = jQuery.isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( jQuery.isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 13 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available, append data to url + if ( s.data ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( jQuery.isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( "<script>" ).prop( { + charset: s.scriptCharset, + src: s.url + } ).on( + "load error", + callback = function( evt ) { + script.remove(); + callback = null; + if ( evt ) { + complete( evt.type === "error" ? 404 : 200, evt.type ); + } + } + ); + + // Use native DOM manipulation to avoid our domManip AJAX trickery + document.head.appendChild( script[ 0 ] ); + }, + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +var oldCallbacks = [], + rjsonp = /(=)\?(?=&|$)|\?\?/; + +// Default jsonp settings +jQuery.ajaxSetup( { + jsonp: "callback", + jsonpCallback: function() { + var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); + this[ callback ] = true; + return callback; + } +} ); + +// Detect, normalize options and install callbacks for jsonp requests +jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { + + var callbackName, overwritten, responseContainer, + jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? + "url" : + typeof s.data === "string" && + ( s.contentType || "" ) + .indexOf( "application/x-www-form-urlencoded" ) === 0 && + rjsonp.test( s.data ) && "data" + ); + + // Handle iff the expected data type is "jsonp" or we have a parameter to set + if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { + + // Get callback name, remembering preexisting value associated with it + callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? + s.jsonpCallback() : + s.jsonpCallback; + + // Insert callback into url or form data + if ( jsonProp ) { + s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); + } else if ( s.jsonp !== false ) { + s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; + } + + // Use data converter to retrieve json after script execution + s.converters[ "script json" ] = function() { + if ( !responseContainer ) { + jQuery.error( callbackName + " was not called" ); + } + return responseContainer[ 0 ]; + }; + + // Force json dataType + s.dataTypes[ 0 ] = "json"; + + // Install callback + overwritten = window[ callbackName ]; + window[ callbackName ] = function() { + responseContainer = arguments; + }; + + // Clean-up function (fires after converters) + jqXHR.always( function() { + + // If previous value didn't exist - remove it + if ( overwritten === undefined ) { + jQuery( window ).removeProp( callbackName ); + + // Otherwise restore preexisting value + } else { + window[ callbackName ] = overwritten; + } + + // Save back as free + if ( s[ callbackName ] ) { + + // Make sure that re-using the options doesn't screw things around + s.jsonpCallback = originalSettings.jsonpCallback; + + // Save the callback name for future use + oldCallbacks.push( callbackName ); + } + + // Call if it was a function and we have a response + if ( responseContainer && jQuery.isFunction( overwritten ) ) { + overwritten( responseContainer[ 0 ] ); + } + + responseContainer = overwritten = undefined; + } ); + + // Delegate to script + return "script"; + } +} ); + + + + +// Support: Safari 8 only +// In Safari 8 documents created via document.implementation.createHTMLDocument +// collapse sibling forms: the second one becomes a child of the first one. +// Because of that, this security measure has to be disabled in Safari 8. +// https://bugs.webkit.org/show_bug.cgi?id=137337 +support.createHTMLDocument = ( function() { + var body = document.implementation.createHTMLDocument( "" ).body; + body.innerHTML = "<form></form><form></form>"; + return body.childNodes.length === 2; +} )(); + + +// Argument "data" should be string of html +// context (optional): If specified, the fragment will be created in this context, +// defaults to document +// keepScripts (optional): If true, will include scripts passed in the html string +jQuery.parseHTML = function( data, context, keepScripts ) { + if ( typeof data !== "string" ) { + return []; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + + var base, parsed, scripts; + + if ( !context ) { + + // Stop scripts or inline event handlers from being executed immediately + // by using document.implementation + if ( support.createHTMLDocument ) { + context = document.implementation.createHTMLDocument( "" ); + + // Set the base href for the created document + // so any parsed elements with URLs + // are based on the document's URL (gh-2965) + base = context.createElement( "base" ); + base.href = document.location.href; + context.head.appendChild( base ); + } else { + context = document; + } + } + + parsed = rsingleTag.exec( data ); + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[ 1 ] ) ]; + } + + parsed = buildFragment( [ data ], context, scripts ); + + if ( scripts && scripts.length ) { + jQuery( scripts ).remove(); + } + + return jQuery.merge( [], parsed.childNodes ); +}; + + +/** + * Load a url into a page + */ +jQuery.fn.load = function( url, params, callback ) { + var selector, type, response, + self = this, + off = url.indexOf( " " ); + + if ( off > -1 ) { + selector = stripAndCollapse( url.slice( off ) ); + url = url.slice( 0, off ); + } + + // If it's a function + if ( jQuery.isFunction( params ) ) { + + // We assume that it's the callback + callback = params; + params = undefined; + + // Otherwise, build a param string + } else if ( params && typeof params === "object" ) { + type = "POST"; + } + + // If we have elements to modify, make the request + if ( self.length > 0 ) { + jQuery.ajax( { + url: url, + + // If "type" variable is undefined, then "GET" method will be used. + // Make value of this field explicit since + // user can override it through ajaxSetup method + type: type || "GET", + dataType: "html", + data: params + } ).done( function( responseText ) { + + // Save response for use in complete callback + response = arguments; + + self.html( selector ? + + // If a selector was specified, locate the right elements in a dummy div + // Exclude scripts to avoid IE 'Permission Denied' errors + jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) : + + // Otherwise use the full result + responseText ); + + // If the request succeeds, this function gets "data", "status", "jqXHR" + // but they are ignored because response was set above. + // If it fails, this function gets "jqXHR", "status", "error" + } ).always( callback && function( jqXHR, status ) { + self.each( function() { + callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] ); + } ); + } ); + } + + return this; +}; + + + + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( [ + "ajaxStart", + "ajaxStop", + "ajaxComplete", + "ajaxError", + "ajaxSuccess", + "ajaxSend" +], function( i, type ) { + jQuery.fn[ type ] = function( fn ) { + return this.on( type, fn ); + }; +} ); + + + + +jQuery.expr.pseudos.animated = function( elem ) { + return jQuery.grep( jQuery.timers, function( fn ) { + return elem === fn.elem; + } ).length; +}; + + + + +jQuery.offset = { + setOffset: function( elem, options, i ) { + var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, + position = jQuery.css( elem, "position" ), + curElem = jQuery( elem ), + props = {}; + + // Set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + curOffset = curElem.offset(); + curCSSTop = jQuery.css( elem, "top" ); + curCSSLeft = jQuery.css( elem, "left" ); + calculatePosition = ( position === "absolute" || position === "fixed" ) && + ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1; + + // Need to be able to calculate position if either + // top or left is auto and position is either absolute or fixed + if ( calculatePosition ) { + curPosition = curElem.position(); + curTop = curPosition.top; + curLeft = curPosition.left; + + } else { + curTop = parseFloat( curCSSTop ) || 0; + curLeft = parseFloat( curCSSLeft ) || 0; + } + + if ( jQuery.isFunction( options ) ) { + + // Use jQuery.extend here to allow modification of coordinates argument (gh-1848) + options = options.call( elem, i, jQuery.extend( {}, curOffset ) ); + } + + if ( options.top != null ) { + props.top = ( options.top - curOffset.top ) + curTop; + } + if ( options.left != null ) { + props.left = ( options.left - curOffset.left ) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + + } else { + curElem.css( props ); + } + } +}; + +jQuery.fn.extend( { + offset: function( options ) { + + // Preserve chaining for setter + if ( arguments.length ) { + return options === undefined ? + this : + this.each( function( i ) { + jQuery.offset.setOffset( this, options, i ); + } ); + } + + var doc, docElem, rect, win, + elem = this[ 0 ]; + + if ( !elem ) { + return; + } + + // Return zeros for disconnected and hidden (display: none) elements (gh-2310) + // Support: IE <=11 only + // Running getBoundingClientRect on a + // disconnected node in IE throws an error + if ( !elem.getClientRects().length ) { + return { top: 0, left: 0 }; + } + + rect = elem.getBoundingClientRect(); + + doc = elem.ownerDocument; + docElem = doc.documentElement; + win = doc.defaultView; + + return { + top: rect.top + win.pageYOffset - docElem.clientTop, + left: rect.left + win.pageXOffset - docElem.clientLeft + }; + }, + + position: function() { + if ( !this[ 0 ] ) { + return; + } + + var offsetParent, offset, + elem = this[ 0 ], + parentOffset = { top: 0, left: 0 }; + + // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, + // because it is its only offset parent + if ( jQuery.css( elem, "position" ) === "fixed" ) { + + // Assume getBoundingClientRect is there when computed position is fixed + offset = elem.getBoundingClientRect(); + + } else { + + // Get *real* offsetParent + offsetParent = this.offsetParent(); + + // Get correct offsets + offset = this.offset(); + if ( !nodeName( offsetParent[ 0 ], "html" ) ) { + parentOffset = offsetParent.offset(); + } + + // Add offsetParent borders + parentOffset = { + top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ), + left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ) + }; + } + + // Subtract parent offsets and element margins + return { + top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), + left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) + }; + }, + + // This method will return documentElement in the following cases: + // 1) For the element inside the iframe without offsetParent, this method will return + // documentElement of the parent window + // 2) For the hidden or detached element + // 3) For body or html element, i.e. in case of the html node - it will return itself + // + // but those exceptions were never presented as a real life use-cases + // and might be considered as more preferable results. + // + // This logic, however, is not guaranteed and can change at any point in the future + offsetParent: function() { + return this.map( function() { + var offsetParent = this.offsetParent; + + while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) { + offsetParent = offsetParent.offsetParent; + } + + return offsetParent || documentElement; + } ); + } +} ); + +// Create scrollLeft and scrollTop methods +jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) { + var top = "pageYOffset" === prop; + + jQuery.fn[ method ] = function( val ) { + return access( this, function( elem, method, val ) { + + // Coalesce documents and windows + var win; + if ( jQuery.isWindow( elem ) ) { + win = elem; + } else if ( elem.nodeType === 9 ) { + win = elem.defaultView; + } + + if ( val === undefined ) { + return win ? win[ prop ] : elem[ method ]; + } + + if ( win ) { + win.scrollTo( + !top ? val : win.pageXOffset, + top ? val : win.pageYOffset + ); + + } else { + elem[ method ] = val; + } + }, method, val, arguments.length ); + }; +} ); + +// Support: Safari <=7 - 9.1, Chrome <=37 - 49 +// Add the top/left cssHooks using jQuery.fn.position +// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 +// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347 +// getComputedStyle returns percent when specified for top/left/bottom/right; +// rather than make the css module depend on the offset module, just check for it here +jQuery.each( [ "top", "left" ], function( i, prop ) { + jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, + function( elem, computed ) { + if ( computed ) { + computed = curCSS( elem, prop ); + + // If curCSS returns percentage, fallback to offset + return rnumnonpx.test( computed ) ? + jQuery( elem ).position()[ prop ] + "px" : + computed; + } + } + ); +} ); + + +// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods +jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { + jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, + function( defaultExtra, funcName ) { + + // Margin is only for outerHeight, outerWidth + jQuery.fn[ funcName ] = function( margin, value ) { + var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), + extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); + + return access( this, function( elem, type, value ) { + var doc; + + if ( jQuery.isWindow( elem ) ) { + + // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729) + return funcName.indexOf( "outer" ) === 0 ? + elem[ "inner" + name ] : + elem.document.documentElement[ "client" + name ]; + } + + // Get document width or height + if ( elem.nodeType === 9 ) { + doc = elem.documentElement; + + // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], + // whichever is greatest + return Math.max( + elem.body[ "scroll" + name ], doc[ "scroll" + name ], + elem.body[ "offset" + name ], doc[ "offset" + name ], + doc[ "client" + name ] + ); + } + + return value === undefined ? + + // Get width or height on the element, requesting but not forcing parseFloat + jQuery.css( elem, type, extra ) : + + // Set width or height on the element + jQuery.style( elem, type, value, extra ); + }, type, chainable ? margin : undefined, chainable ); + }; + } ); +} ); + + +jQuery.fn.extend( { + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length === 1 ? + this.off( selector, "**" ) : + this.off( types, selector || "**", fn ); + } +} ); + +jQuery.holdReady = function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } +}; +jQuery.isArray = Array.isArray; +jQuery.parseJSON = JSON.parse; +jQuery.nodeName = nodeName; + + + + +// Register as a named AMD module, since jQuery can be concatenated with other +// files that may use define, but not via a proper concatenation script that +// understands anonymous AMD modules. A named AMD is safest and most robust +// way to register. Lowercase jquery is used because AMD module names are +// derived from file names, and jQuery is normally delivered in a lowercase +// file name. Do this after creating the global so that if an AMD module wants +// to call noConflict to hide this version of jQuery, it will work. + +// Note that for maximum portability, libraries that are not jQuery should +// declare themselves as anonymous modules, and avoid setting a global if an +// AMD loader is present. jQuery is a special case. For more information, see +// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon + +if ( typeof define === "function" && define.amd ) { + define( "jquery", [], function() { + return jQuery; + } ); +} + + + + +var + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$; + +jQuery.noConflict = function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; +}; + +// Expose jQuery and $ identifiers, even in AMD +// (#7102#comment:10, https://github.com/jquery/jquery/pull/557) +// and CommonJS for browser emulators (#13566) +if ( !noGlobal ) { + window.jQuery = window.$ = jQuery; +} + + + + +return jQuery; +} ); diff --git a/documentation/sphinx/.build/_static/jquery.js b/documentation/sphinx/.build/_static/jquery.js new file mode 100644 index 0000000000000000000000000000000000000000..644d35e274fd64ddaf6d12af813e820c424176a9 --- /dev/null +++ b/documentation/sphinx/.build/_static/jquery.js @@ -0,0 +1,4 @@ +/*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */ +!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.2.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c<b?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);h<i;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=Array.isArray(d)))?(e?(e=!1,f=c&&Array.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return!(!a||"[object Object]"!==k.call(a))&&(!(b=e(a))||(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;d<c;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;d<c;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;f<g;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;f<d;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;if("string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a))return d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"!==c&&!r.isWindow(a)&&("array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;c<b;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e);return!1}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}return!1}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d<e;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i<f;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;e<f;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i<e&&ya(a.slice(i,e)),e<f&&ya(a=a.slice(e)),e<f&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b<d;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;b<d;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a<c;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;d<e;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}function O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b<f)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,N,e),g(f,c,O,e)):(f++,j.call(a,g(f,c,N,e),g(f,c,O,e),g(f,c,N,c.notifyWith))):(d!==N&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S), +a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h<i;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},U=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function V(){this.expando=r.expando+V.uid++}V.uid=1,V.prototype={cache:function(a){var b=a[this.expando];return b||(b={},U(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){Array.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(L)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var W=new V,X=new V,Y=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function $(a){return"true"===a||"false"!==a&&("null"===a?null:a===+a+""?+a:Y.test(a)?JSON.parse(a):a)}function _(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Z,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c=$(c)}catch(e){}X.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return X.hasData(a)||W.hasData(a)},data:function(a,b,c){return X.access(a,b,c)},removeData:function(a,b){X.remove(a,b)},_data:function(a,b,c){return W.access(a,b,c)},_removeData:function(a,b){W.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=X.get(f),1===f.nodeType&&!W.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),_(f,d,e[d])));W.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){X.set(this,a)}):T(this,function(b){var c;if(f&&void 0===b){if(c=X.get(f,a),void 0!==c)return c;if(c=_(f,a),void 0!==c)return c}else this.each(function(){X.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=W.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var aa=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ba=new RegExp("^(?:([+-])=|)("+aa+")([a-z%]*)$","i"),ca=["Top","Right","Bottom","Left"],da=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},ea=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function fa(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&ba.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var ga={};function ha(a){var b,c=a.ownerDocument,d=a.nodeName,e=ga[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),ga[d]=e,e)}function ia(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=W.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&da(d)&&(e[f]=ha(d))):"none"!==c&&(e[f]="none",W.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ia(this,!0)},hide:function(){return ia(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){da(this)?r(this).show():r(this).hide()})}});var ja=/^(?:checkbox|radio)$/i,ka=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c<d;c++)W.set(a[c],"globalEval",!b||W.get(b[c],"globalEval"))}var pa=/<|&#?\w+;/;function qa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;n<o;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(pa.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ka.exec(f)||["",""])[1].toLowerCase(),i=ma[h]||ma._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g,h=[],i=b.delegateCount,j=a.target;if(i&&j.nodeType&&!("click"===a.type&&a.button>=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c<i;c++)d=b[c],e=d.selector+" ",void 0===g[e]&&(g[e]=d.needsContext?r(e,this).index(j)>-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i<b.length&&h.push({elem:j,handlers:b.slice(i)}),h},addProp:function(a,b){Object.defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){if(this.originalEvent)return b(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[a]},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==xa()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===xa()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&B(this,"input"))return this.click(),!1},_default:function(a){return B(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?va:wa,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:wa,isPropagationStopped:wa,isImmediatePropagationStopped:wa,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=va,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=va,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=va,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&sa.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&ta.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return ya(this,a,b,c,d)},one:function(a,b,c,d){return ya(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=wa),this.each(function(){r.event.remove(this,a,c,b)})}});var za=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/<script|<style|<link/i,Ba=/checked\s*(?:[^=]|=\s*.checked.)/i,Ca=/^true\/(.*)/,Da=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c<d;c++)r.event.add(b,e,j[e][c])}X.hasData(a)&&(h=X.access(a),i=r.extend({},h),X.set(b,i))}}function Ia(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ja.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ja(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l<m;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,na(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Ga),l=0;l<i;l++)j=h[l],la.test(j.type||"")&&!W.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Da,""),k))}return a}function Ka(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(na(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&oa(na(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(za,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d<e;d++)Ia(f[d],g[d]);if(b)if(c)for(f=f||na(a),g=g||na(h),d=0,e=f.length;d<e;d++)Ha(f[d],g[d]);else Ha(a,h);return g=na(h,"script"),g.length>0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c<d;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(na(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ja(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(na(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;g<=f;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var La=/^margin/,Ma=new RegExp("^("+aa+")(?!px)[a-z%]+$","i"),Na=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",ra.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,ra.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Oa(a,b,c){var d,e,f,g,h=a.style;return c=c||Na(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&Ma.test(g)&&La.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Pa(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Qa=/^(none|table(?!-c[ea]).+)/,Ra=/^--/,Sa={position:"absolute",visibility:"hidden",display:"block"},Ta={letterSpacing:"0",fontWeight:"400"},Ua=["Webkit","Moz","ms"],Va=d.createElement("div").style;function Wa(a){if(a in Va)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ua.length;while(c--)if(a=Ua[c]+b,a in Va)return a}function Xa(a){var b=r.cssProps[a];return b||(b=r.cssProps[a]=Wa(a)||a),b}function Ya(a,b,c){var d=ba.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Za(a,b,c,d,e){var f,g=0;for(f=c===(d?"border":"content")?4:"width"===b?1:0;f<4;f+=2)"margin"===c&&(g+=r.css(a,c+ca[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+ca[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+ca[f]+"Width",!0,e))):(g+=r.css(a,"padding"+ca[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+ca[f]+"Width",!0,e)));return g}function $a(a,b,c){var d,e=Na(a),f=Oa(a,b,e),g="border-box"===r.css(a,"boxSizing",!1,e);return Ma.test(f)?f:(d=g&&(o.boxSizingReliable()||f===a.style[b]),"auto"===f&&(f=a["offset"+b[0].toUpperCase()+b.slice(1)]),f=parseFloat(f)||0,f+Za(a,b,c||(g?"border":"content"),d,e)+"px")}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Oa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=Ra.test(b),j=a.style;return i||(b=Xa(h)),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:j[b]:(f=typeof c,"string"===f&&(e=ba.exec(c))&&e[1]&&(c=fa(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(j[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i?j.setProperty(b,c):j[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b),i=Ra.test(b);return i||(b=Xa(h)),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Oa(a,b,d)),"normal"===e&&b in Ta&&(e=Ta[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){if(c)return!Qa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?$a(a,b,d):ea(a,Sa,function(){return $a(a,b,d)})},set:function(a,c,d){var e,f=d&&Na(a),g=d&&Za(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=ba.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Ya(a,c,g)}}}),r.cssHooks.marginLeft=Pa(o.reliableMarginLeft,function(a,b){if(b)return(parseFloat(Oa(a,"marginLeft"))||a.getBoundingClientRect().left-ea(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px"}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];d<4;d++)e[a+ca[d]+b]=f[d]||f[d-2]||f[0];return e}},La.test(a)||(r.cssHooks[a+b].set=Ya)}),r.fn.extend({css:function(a,b){return T(this,function(a,b,c){var d,e,f={},g=0;if(Array.isArray(b)){for(d=Na(a),e=b.length;g<e;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function _a(a,b,c,d,e){return new _a.prototype.init(a,b,c,d,e)}r.Tween=_a,_a.prototype={constructor:_a,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=_a.propHooks[this.prop];return a&&a.get?a.get(this):_a.propHooks._default.get(this)},run:function(a){var b,c=_a.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):_a.propHooks._default.set(this),this}},_a.prototype.init.prototype=_a.prototype,_a.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},_a.propHooks.scrollTop=_a.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=_a.prototype.init,r.fx.step={};var ab,bb,cb=/^(?:toggle|show|hide)$/,db=/queueHooks$/;function eb(){bb&&(d.hidden===!1&&a.requestAnimationFrame?a.requestAnimationFrame(eb):a.setTimeout(eb,r.fx.interval),r.fx.tick())}function fb(){return a.setTimeout(function(){ab=void 0}),ab=r.now()}function gb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ca[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function hb(a,b,c){for(var d,e=(kb.tweeners[b]||[]).concat(kb.tweeners["*"]),f=0,g=e.length;f<g;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&da(a),q=W.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],cb.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=W.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ia([a],!0),j=a.style.display||j,k=r.css(a,"display"),ia([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=W.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ia([a],!0),m.done(function(){p||ia([a]),W.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=hb(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],Array.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kb(a,b,c){var d,e,f=0,g=kb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=ab||fb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;g<i;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),f<1&&i?c:(i||h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:ab||fb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;c<d;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jb(k,j.opts.specialEasing);f<g;f++)if(d=kb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,hb,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j}r.Animation=r.extend(kb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return fa(c.elem,a,ba.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(L);for(var c,d=0,e=a.length;d<e;d++)c=a[d],kb.tweeners[c]=kb.tweeners[c]||[],kb.tweeners[c].unshift(b)},prefilters:[ib],prefilter:function(a,b){b?kb.prefilters.unshift(a):kb.prefilters.push(a)}}),r.speed=function(a,b,c){var d=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off?d.duration=0:"number"!=typeof d.duration&&(d.duration in r.fx.speeds?d.duration=r.fx.speeds[d.duration]:d.duration=r.fx.speeds._default),null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){r.isFunction(d.old)&&d.old.call(this),d.queue&&r.dequeue(this,d.queue)},d},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(da).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=kb(this,r.extend({},a),f);(e||W.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=W.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&db.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=W.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;b<g;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gb(b,!0),a,d,e)}}),r.each({slideDown:gb("show"),slideUp:gb("hide"),slideToggle:gb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(ab=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),ab=void 0},r.fx.timer=function(a){r.timers.push(a),r.fx.start()},r.fx.interval=13,r.fx.start=function(){bb||(bb=!0,eb())},r.fx.stop=function(){bb=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var lb,mb=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return T(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?lb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b), +null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),lb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=mb[b]||r.find.attr;mb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=mb[g],mb[g]=e,e=null!=c(a,b,d)?g:null,mb[g]=f),e}});var nb=/^(?:input|select|textarea|button)$/i,ob=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):nb.test(a.nodeName)||ob.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function pb(a){var b=a.match(L)||[];return b.join(" ")}function qb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,qb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,qb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,qb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=qb(this),b&&W.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+pb(qb(c))+" ").indexOf(b)>-1)return!0;return!1}});var rb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:pb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d<i;d++)if(c=e[d],(c.selected||d===f)&&!c.disabled&&(!c.parentNode.disabled||!B(c.parentNode,"optgroup"))){if(b=r(c).val(),g)return b;h.push(b)}return h},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var sb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!sb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,sb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var tb=a.location,ub=r.now(),vb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}});var Bb=/%20/g,Cb=/#.*$/,Db=/([?&])_=[^&]*/,Eb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Fb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Gb=/^(?:GET|HEAD)$/,Hb=/^\/\//,Ib={},Jb={},Kb="*/".concat("*"),Lb=d.createElement("a");Lb.href=tb.href;function Mb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(L)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nb(a,b,c,d){var e={},f=a===Jb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Ob(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Pb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Qb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:tb.href,type:"GET",isLocal:Fb.test(tb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Ob(Ob(a,r.ajaxSettings),b):Ob(r.ajaxSettings,a)},ajaxPrefilter:Mb(Ib),ajaxTransport:Mb(Jb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Eb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||tb.href)+"").replace(Hb,tb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(L)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Lb.protocol+"//"+Lb.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Nb(Ib,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Gb.test(o.type),f=o.url.replace(Cb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(Bb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(vb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Db,"$1"),n=(vb.test(f)?"&":"?")+"_="+ub++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Kb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Nb(Jb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Pb(o,y,d)),v=Qb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Rb={0:200,1223:204},Sb=r.ajaxSettings.xhr();o.cors=!!Sb&&"withCredentials"in Sb,o.ajax=Sb=!!Sb,r.ajaxTransport(function(b){var c,d;if(o.cors||Sb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Rb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Tb=[],Ub=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Tb.pop()||r.expando+"_"+ub++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Ub.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ub.test(b.data)&&"data");if(h||"jsonp"===b.dataTypes[0])return e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Ub,"$1"+e):b.jsonp!==!1&&(b.url+=(vb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Tb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=C.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=qa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=pb(a.slice(h)),a=a.slice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length},r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),b=f.ownerDocument,c=b.documentElement,e=b.defaultView,{top:d.top+e.pageYOffset-c.clientTop,left:d.left+e.pageXOffset-c.clientLeft}):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),B(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||ra})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return T(this,function(a,d,e){var f;return r.isWindow(a)?f=a:9===a.nodeType&&(f=a.defaultView),void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Pa(o.pixelPosition,function(a,c){if(c)return c=Oa(a,b),Ma.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return T(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.holdReady=function(a){a?r.readyWait++:r.ready(!0)},r.isArray=Array.isArray,r.parseJSON=JSON.parse,r.nodeName=B,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Vb=a.jQuery,Wb=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Wb),b&&a.jQuery===r&&(a.jQuery=Vb),r},b||(a.jQuery=a.$=r),r}); diff --git a/documentation/sphinx/.build/_static/minus.png b/documentation/sphinx/.build/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d Binary files /dev/null and b/documentation/sphinx/.build/_static/minus.png differ diff --git a/documentation/sphinx/.build/_static/plus.png b/documentation/sphinx/.build/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d Binary files /dev/null and b/documentation/sphinx/.build/_static/plus.png differ diff --git a/documentation/sphinx/.build/_static/pygments.css b/documentation/sphinx/.build/_static/pygments.css new file mode 100644 index 0000000000000000000000000000000000000000..20c4814dcf0d3f437ee9a46f5957e3165aa5fb17 --- /dev/null +++ b/documentation/sphinx/.build/_static/pygments.css @@ -0,0 +1,69 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #333333 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #208050 } /* Literal.Number.Bin */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070a0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287e } /* Name.Function.Magic */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/documentation/sphinx/.build/_static/searchtools.js b/documentation/sphinx/.build/_static/searchtools.js new file mode 100644 index 0000000000000000000000000000000000000000..41b8336776442fbc64332ffbd3d2c1ddd8b3b9c2 --- /dev/null +++ b/documentation/sphinx/.build/_static/searchtools.js @@ -0,0 +1,761 @@ +/* + * searchtools.js_t + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + + +/* Non-minified version JS is _stemmer.js if file is provided */ +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + + + +/** + * Simple result scoring code. + */ +var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [filename, title, anchor, descr, score] + // and returns the new score. + /* + score: function(result) { + return result[4]; + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: {0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5}, // used to be unimportantResults + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + // query found in terms + term: 5 +}; + + + + + +var splitChars = (function() { + var result = {}; + var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, + 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, + 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, + 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, + 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, + 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, + 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, + 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, + 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, + 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; + var i, j, start, end; + for (i = 0; i < singles.length; i++) { + result[singles[i]] = true; + } + var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], + [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], + [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], + [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], + [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], + [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], + [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], + [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], + [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], + [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], + [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], + [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], + [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], + [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], + [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], + [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], + [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], + [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], + [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], + [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], + [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], + [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], + [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], + [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], + [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], + [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], + [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], + [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], + [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], + [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], + [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], + [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], + [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], + [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], + [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], + [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], + [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], + [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], + [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], + [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], + [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], + [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], + [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], + [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], + [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], + [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], + [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], + [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], + [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; + for (i = 0; i < ranges.length; i++) { + start = ranges[i][0]; + end = ranges[i][1]; + for (j = start; j <= end; j++) { + result[j] = true; + } + } + return result; +})(); + +function splitQuery(query) { + var result = []; + var start = -1; + for (var i = 0; i < query.length; i++) { + if (splitChars[query.charCodeAt(i)]) { + if (start !== -1) { + result.push(query.slice(start, i)); + start = -1; + } + } else if (start === -1) { + start = i; + } + } + if (start !== -1) { + result.push(query.slice(start)); + } + return result; +} + + + + +/** + * Search Module + */ +var Search = { + + _index : null, + _queued_query : null, + _pulse_status : -1, + + init : function() { + var params = $.getQueryParameters(); + if (params.q) { + var query = params.q[0]; + $('input[name="q"]')[0].value = query; + this.performSearch(query); + } + }, + + loadIndex : function(url) { + $.ajax({type: "GET", url: url, data: null, + dataType: "script", cache: true, + complete: function(jqxhr, textstatus) { + if (textstatus != "success") { + document.getElementById("searchindexloader").src = url; + } + }}); + }, + + setIndex : function(index) { + var q; + this._index = index; + if ((q = this._queued_query) !== null) { + this._queued_query = null; + Search.query(q); + } + }, + + hasIndex : function() { + return this._index !== null; + }, + + deferQuery : function(query) { + this._queued_query = query; + }, + + stopPulse : function() { + this._pulse_status = 0; + }, + + startPulse : function() { + if (this._pulse_status >= 0) + return; + function pulse() { + var i; + Search._pulse_status = (Search._pulse_status + 1) % 4; + var dotString = ''; + for (i = 0; i < Search._pulse_status; i++) + dotString += '.'; + Search.dots.text(dotString); + if (Search._pulse_status > -1) + window.setTimeout(pulse, 500); + } + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch : function(query) { + // create the required interface elements + this.out = $('#search-results'); + this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out); + this.dots = $('<span></span>').appendTo(this.title); + this.status = $('<p style="display: none"></p>').appendTo(this.out); + this.output = $('<ul class="search"/>').appendTo(this.out); + + $('#search-progress').text(_('Preparing search...')); + this.startPulse(); + + // index already loaded, the browser was quick! + if (this.hasIndex()) + this.query(query); + else + this.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query : function(query) { + var i; + var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; + + // stem the searchterms and add them to the correct list + var stemmer = new Stemmer(); + var searchterms = []; + var excluded = []; + var hlterms = []; + var tmp = splitQuery(query); + var objectterms = []; + for (i = 0; i < tmp.length; i++) { + if (tmp[i] !== "") { + objectterms.push(tmp[i].toLowerCase()); + } + + if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) || + tmp[i] === "") { + // skip this "word" + continue; + } + // stem the word + var word = stemmer.stemWord(tmp[i].toLowerCase()); + // prevent stemmer from cutting word smaller than two chars + if(word.length < 3 && tmp[i].length >= 3) { + word = tmp[i]; + } + var toAppend; + // select the correct list + if (word[0] == '-') { + toAppend = excluded; + word = word.substr(1); + } + else { + toAppend = searchterms; + hlterms.push(tmp[i].toLowerCase()); + } + // only add if not already in the list + if (!$u.contains(toAppend, word)) + toAppend.push(word); + } + var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" ")); + + // console.debug('SEARCH: searching for:'); + // console.info('required: ', searchterms); + // console.info('excluded: ', excluded); + + // prepare search + var terms = this._index.terms; + var titleterms = this._index.titleterms; + + // array of [filename, title, anchor, descr, score] + var results = []; + $('#search-progress').empty(); + + // lookup as object + for (i = 0; i < objectterms.length; i++) { + var others = [].concat(objectterms.slice(0, i), + objectterms.slice(i+1, objectterms.length)); + results = results.concat(this.performObjectSearch(objectterms[i], others)); + } + + // lookup as search terms in fulltext + results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + for (i = 0; i < results.length; i++) + results[i][4] = Scorer.score(results[i]); + } + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort(function(a, b) { + var left = a[4]; + var right = b[4]; + if (left > right) { + return 1; + } else if (left < right) { + return -1; + } else { + // same score: sort alphabetically + left = a[1].toLowerCase(); + right = b[1].toLowerCase(); + return (left > right) ? -1 : ((left < right) ? 1 : 0); + } + }); + + // for debugging + //Search.lastresults = results.slice(); // a copy + //console.info('search results:', Search.lastresults); + + // print the results + var resultCount = results.length; + function displayNextItem() { + // results left, load the summary and display it + if (results.length) { + var item = results.pop(); + var listItem = $('<li style="display:none"></li>'); + if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') { + // dirhtml builder + var dirname = item[0] + '/'; + if (dirname.match(/\/index\/$/)) { + dirname = dirname.substring(0, dirname.length-6); + } else if (dirname == 'index/') { + dirname = ''; + } + listItem.append($('<a/>').attr('href', + DOCUMENTATION_OPTIONS.URL_ROOT + dirname + + highlightstring + item[2]).html(item[1])); + } else { + // normal html builders + listItem.append($('<a/>').attr('href', + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX + + highlightstring + item[2]).html(item[1])); + } + if (item[3]) { + listItem.append($('<span> (' + item[3] + ')</span>')); + Search.output.append(listItem); + listItem.slideDown(5, function() { + displayNextItem(); + }); + } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) { + var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX; + if (suffix === undefined) { + suffix = '.txt'; + } + $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].slice(-suffix.length) === suffix ? '' : suffix), + dataType: "text", + complete: function(jqxhr, textstatus) { + var data = jqxhr.responseText; + if (data !== '' && data !== undefined) { + listItem.append(Search.makeSearchSummary(data, searchterms, hlterms)); + } + Search.output.append(listItem); + listItem.slideDown(5, function() { + displayNextItem(); + }); + }}); + } else { + // no source available, just display title + Search.output.append(listItem); + listItem.slideDown(5, function() { + displayNextItem(); + }); + } + } + // search finished, update title and status message + else { + Search.stopPulse(); + Search.title.text(_('Search Results')); + if (!resultCount) + Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.')); + else + Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount)); + Search.status.fadeIn(500); + } + } + displayNextItem(); + }, + + /** + * search for object names + */ + performObjectSearch : function(object, otherterms) { + var filenames = this._index.filenames; + var docnames = this._index.docnames; + var objects = this._index.objects; + var objnames = this._index.objnames; + var titles = this._index.titles; + + var i; + var results = []; + + for (var prefix in objects) { + for (var name in objects[prefix]) { + var fullname = (prefix ? prefix + '.' : '') + name; + if (fullname.toLowerCase().indexOf(object) > -1) { + var score = 0; + var parts = fullname.split('.'); + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullname == object || parts[parts.length - 1] == object) { + score += Scorer.objNameMatch; + // matches in last name + } else if (parts[parts.length - 1].indexOf(object) > -1) { + score += Scorer.objPartialMatch; + } + var match = objects[prefix][name]; + var objname = objnames[match[1]][2]; + var title = titles[match[0]]; + // If more than one term searched for, we require other words to be + // found in the name/title/description + if (otherterms.length > 0) { + var haystack = (prefix + ' ' + name + ' ' + + objname + ' ' + title).toLowerCase(); + var allfound = true; + for (i = 0; i < otherterms.length; i++) { + if (haystack.indexOf(otherterms[i]) == -1) { + allfound = false; + break; + } + } + if (!allfound) { + continue; + } + } + var descr = objname + _(', in ') + title; + + var anchor = match[3]; + if (anchor === '') + anchor = fullname; + else if (anchor == '-') + anchor = objnames[match[1]][1] + '-' + fullname; + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) { + score += Scorer.objPrio[match[2]]; + } else { + score += Scorer.objPrioDefault; + } + results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]); + } + } + } + + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch : function(searchterms, excluded, terms, titleterms) { + var docnames = this._index.docnames; + var filenames = this._index.filenames; + var titles = this._index.titles; + + var i, j, file; + var fileMap = {}; + var scoreMap = {}; + var results = []; + + // perform the search on the required terms + for (i = 0; i < searchterms.length; i++) { + var word = searchterms[i]; + var files = []; + var _o = [ + {files: terms[word], score: Scorer.term}, + {files: titleterms[word], score: Scorer.title} + ]; + + // no match but word was a required one + if ($u.every(_o, function(o){return o.files === undefined;})) { + break; + } + // found search word in contents + $u.each(_o, function(o) { + var _files = o.files; + if (_files === undefined) + return + + if (_files.length === undefined) + _files = [_files]; + files = files.concat(_files); + + // set score for the word in each file to Scorer.term + for (j = 0; j < _files.length; j++) { + file = _files[j]; + if (!(file in scoreMap)) + scoreMap[file] = {} + scoreMap[file][word] = o.score; + } + }); + + // create the mapping + for (j = 0; j < files.length; j++) { + file = files[j]; + if (file in fileMap) + fileMap[file].push(word); + else + fileMap[file] = [word]; + } + } + + // now check if the files don't contain excluded terms + for (file in fileMap) { + var valid = true; + + // check if all requirements are matched + if (fileMap[file].length != searchterms.length) + continue; + + // ensure that none of the excluded terms is in the search result + for (i = 0; i < excluded.length; i++) { + if (terms[excluded[i]] == file || + titleterms[excluded[i]] == file || + $u.contains(terms[excluded[i]] || [], file) || + $u.contains(titleterms[excluded[i]] || [], file)) { + valid = false; + break; + } + } + + // if we have still a valid result we can add it to the result list + if (valid) { + // select one (max) score for the file. + // for better ranking, we should calculate ranking by using words statistics like basic tf-idf... + var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]})); + results.push([docnames[file], titles[file], '', null, score, filenames[file]]); + } + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words, hlwords is the list of normal, unstemmed + * words. the first one is used to find the occurrence, the + * latter for highlighting it. + */ + makeSearchSummary : function(text, keywords, hlwords) { + var textLower = text.toLowerCase(); + var start = 0; + $.each(keywords, function() { + var i = textLower.indexOf(this.toLowerCase()); + if (i > -1) + start = i; + }); + start = Math.max(start - 120, 0); + var excerpt = ((start > 0) ? '...' : '') + + $.trim(text.substr(start, 240)) + + ((start + 240 - text.length) ? '...' : ''); + var rv = $('<div class="context"></div>').text(excerpt); + $.each(hlwords, function() { + rv = rv.highlightText(this, 'highlighted'); + }); + return rv; + } +}; + +$(document).ready(function() { + Search.init(); +}); \ No newline at end of file diff --git a/documentation/sphinx/.build/_static/underscore-1.3.1.js b/documentation/sphinx/.build/_static/underscore-1.3.1.js new file mode 100644 index 0000000000000000000000000000000000000000..208d4cd890c3183d946092ebe982738ade565061 --- /dev/null +++ b/documentation/sphinx/.build/_static/underscore-1.3.1.js @@ -0,0 +1,999 @@ +// Underscore.js 1.3.1 +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var slice = ArrayProto.slice, + unshift = ArrayProto.unshift, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { return new wrapper(obj); }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root['_'] = _; + } + + // Current version. + _.VERSION = '1.3.1'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + if (obj.length === +obj.length) results.length = obj.length; + return results; + }; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError('Reduce of empty array with no initial value'); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var reversed = _.toArray(obj).reverse(); + if (context && !initial) iterator = _.bind(iterator, context); + return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator); + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + each(obj, function(value, index, list) { + if (!iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if a given value is included in the array or object using `===`. + // Aliased as `contains`. + _.include = _.contains = function(obj, target) { + var found = false; + if (obj == null) return found; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + found = any(obj, function(value) { + return value === target; + }); + return found; + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + return _.map(obj, function(value) { + return (_.isFunction(method) ? method || value : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Return the maximum element or (element-based computation). + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj); + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var shuffled = [], rand; + each(obj, function(value, index, list) { + if (index == 0) { + shuffled[0] = value; + } else { + rand = Math.floor(Math.random() * (index + 1)); + shuffled[index] = shuffled[rand]; + shuffled[rand] = value; + } + }); + return shuffled; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }), 'value'); + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, val) { + var result = {}; + var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; }; + each(obj, function(value, index) { + var key = iterator(value, index); + (result[key] || (result[key] = [])).push(value); + }); + return result; + }; + + // Use a comparator function to figure out at what index an object should + // be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator) { + iterator || (iterator = _.identity); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >> 1; + iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + if (_.isArray(iterable)) return slice.call(iterable); + if (_.isArguments(iterable)) return slice.call(iterable); + return _.values(iterable); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + return _.toArray(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head`. The **guard** check allows it to work + // with `_.map`. + _.first = _.head = function(array, n, guard) { + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especcialy useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail`. + // Especially useful on the arguments object. Passing an **index** will return + // the rest of the values in the array from that index onward. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = function(array, index, guard) { + return slice.call(array, (index == null) || guard ? 1 : index); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, function(value){ return !!value; }); + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return _.reduce(array, function(memo, value) { + if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value)); + memo[memo.length] = value; + return memo; + }, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator) { + var initial = iterator ? _.map(array, iterator) : array; + var result = []; + _.reduce(initial, function(memo, el, i) { + if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) { + memo[memo.length] = el; + result[result.length] = array[i]; + } + return memo; + }, []); + return result; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. (Aliased as "intersect" for back-compat.) + _.intersection = _.intersect = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = _.flatten(slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.include(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i); + return results; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i, l; + if (isSorted) { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item); + for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item) { + if (array == null) return -1; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item); + var i = array.length; + while (i--) if (i in array && array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Binding with arguments is also known as `curry`. + // Delegates to **ECMAScript 5**'s native `Function.bind` if available. + // We check for `func.bind` first, to fail fast when `func` is undefined. + _.bind = function bind(func, context) { + var bound, args; + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length == 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(func, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, throttling, more; + var whenDone = _.debounce(function(){ more = throttling = false; }, wait); + return function() { + context = this; args = arguments; + var later = function() { + timeout = null; + if (more) func.apply(context, args); + whenDone(); + }; + if (!timeout) timeout = setTimeout(later, wait); + if (throttling) { + more = true; + } else { + func.apply(context, args); + } + whenDone(); + throttling = true; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. + _.debounce = function(func, wait) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + func.apply(context, args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + return memo = func.apply(this, arguments); + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func].concat(slice.call(arguments, 0)); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { return func.apply(this, arguments); } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + return _.map(obj, _.identity); + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function. + function eq(a, b, stack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a._chain) a = a._wrapped; + if (b._chain) b = b._wrapped; + // Invoke a custom `isEqual` method if one is provided. + if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b); + if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = stack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (stack[length] == a) return true; + } + // Add the first object to the stack of traversed objects. + stack.push(a); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + // Ensure commutative equality for sparse arrays. + if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break; + } + } + } else { + // Objects with different constructors are not equivalent. + if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + stack.pop(); + return result; + } + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType == 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Is a given variable an arguments object? + _.isArguments = function(obj) { + return toString.call(obj) == '[object Arguments]'; + }; + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Is a given value a function? + _.isFunction = function(obj) { + return toString.call(obj) == '[object Function]'; + }; + + // Is a given value a string? + _.isString = function(obj) { + return toString.call(obj) == '[object String]'; + }; + + // Is a given value a number? + _.isNumber = function(obj) { + return toString.call(obj) == '[object Number]'; + }; + + // Is the given value `NaN`? + _.isNaN = function(obj) { + // `NaN` is the only value for which `===` is not reflexive. + return obj !== obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value a date? + _.isDate = function(obj) { + return toString.call(obj) == '[object Date]'; + }; + + // Is the given value a regular expression? + _.isRegExp = function(obj) { + return toString.call(obj) == '[object RegExp]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Has own property? + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function (n, iterator, context) { + for (var i = 0; i < n; i++) iterator.call(context, i); + }; + + // Escape a string for HTML interpolation. + _.escape = function(string) { + return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/'); + }; + + // Add your own custom functions to the Underscore object, ensuring that + // they're correctly added to the OOP wrapper as well. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + addToWrapper(name, _[name] = obj[name]); + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = idCounter++; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /.^/; + + // Within an interpolation, evaluation, or escaping, remove HTML escaping + // that had been previously added. + var unescape = function(code) { + return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'"); + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(str, data) { + var c = _.templateSettings; + var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' + + 'with(obj||{}){__p.push(\'' + + str.replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(c.escape || noMatch, function(match, code) { + return "',_.escape(" + unescape(code) + "),'"; + }) + .replace(c.interpolate || noMatch, function(match, code) { + return "'," + unescape(code) + ",'"; + }) + .replace(c.evaluate || noMatch, function(match, code) { + return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('"; + }) + .replace(/\r/g, '\\r') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t') + + "');}return __p.join('');"; + var func = new Function('obj', '_', tmpl); + if (data) return func(data, _); + return function(data) { + return func.call(this, data, _); + }; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // The OOP Wrapper + // --------------- + + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + var wrapper = function(obj) { this._wrapped = obj; }; + + // Expose `wrapper.prototype` as `_.prototype` + _.prototype = wrapper.prototype; + + // Helper function to continue chaining intermediate results. + var result = function(obj, chain) { + return chain ? _(obj).chain() : obj; + }; + + // A method to easily add functions to the OOP wrapper. + var addToWrapper = function(name, func) { + wrapper.prototype[name] = function() { + var args = slice.call(arguments); + unshift.call(args, this._wrapped); + return result(func.apply(_, args), this._chain); + }; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + var wrapped = this._wrapped; + method.apply(wrapped, arguments); + var length = wrapped.length; + if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0]; + return result(wrapped, this._chain); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + wrapper.prototype[name] = function() { + return result(method.apply(this._wrapped, arguments), this._chain); + }; + }); + + // Start chaining a wrapped Underscore object. + wrapper.prototype.chain = function() { + this._chain = true; + return this; + }; + + // Extracts the result from a wrapped and chained object. + wrapper.prototype.value = function() { + return this._wrapped; + }; + +}).call(this); diff --git a/documentation/sphinx/.build/_static/underscore.js b/documentation/sphinx/.build/_static/underscore.js new file mode 100644 index 0000000000000000000000000000000000000000..5b55f32beaca186f84cca115514f02cddbd1bbd5 --- /dev/null +++ b/documentation/sphinx/.build/_static/underscore.js @@ -0,0 +1,31 @@ +// Underscore.js 1.3.1 +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore is freely distributable under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore +(function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== +c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, +h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= +b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===n)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===n)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(x&&a.map===x)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a== +null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= +function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= +e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= +function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&(e={value:a,computed:b})}); +return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){f==0?b[0]=a:(d=Math.floor(Math.random()*(f+1)),b[f]=b[d],b[d]=a)});return b};b.sortBy=function(a,c,d){return b.pluck(b.map(a,function(a,b,g){return{value:a,criteria:c.call(d,a,b,g)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, +c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:a.toArray?a.toArray():b.isArray(a)?i.call(a):b.isArguments(a)?i.call(a):b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=b.head=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest= +b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,h){if(0==h||(c===true?b.last(d)!=g:!b.include(d,g)))d[d.length]=g,e[e.length]=a[h];return d},[]); +return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c, +d){if(a==null)return-1;var e;if(d)return d=b.sortedIndex(a,c),a[d]===c?d:-1;if(p&&a.indexOf===p)return a.indexOf(c);for(d=0,e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(D&&a.lastIndexOf===D)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){arguments.length<=1&&(b=a||0,a=0);for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;)g[f++]=a,a+=d;return g}; +var F=function(){};b.bind=function(a,c){var d,e;if(a.bind===s&&s)return s.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));F.prototype=a.prototype;var b=new F,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a, +c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i=b.debounce(function(){h=g=false},c);return function(){d=this;e=arguments;var b;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);i()},c));g?h=true: +a.apply(d,e);i();g=true}};b.debounce=function(a,b){var d;return function(){var e=this,f=arguments;clearTimeout(d);d=setTimeout(function(){d=null;a.apply(e,f)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}}; +b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, +1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; +b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; +b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), +function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ +u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= +function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= +true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); diff --git a/documentation/sphinx/.build/_static/up-pressed.png b/documentation/sphinx/.build/_static/up-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..acee3b68efbbfb9de3bfa73fce2531380f4bd820 Binary files /dev/null and b/documentation/sphinx/.build/_static/up-pressed.png differ diff --git a/documentation/sphinx/.build/_static/up.png b/documentation/sphinx/.build/_static/up.png new file mode 100644 index 0000000000000000000000000000000000000000..2a940a7da7c14e6a36901e83306849ba7efad4d4 Binary files /dev/null and b/documentation/sphinx/.build/_static/up.png differ diff --git a/documentation/sphinx/.build/_static/websupport.js b/documentation/sphinx/.build/_static/websupport.js new file mode 100644 index 0000000000000000000000000000000000000000..78e14bb4a1ee080ca01b92b20ed583941db04373 --- /dev/null +++ b/documentation/sphinx/.build/_static/websupport.js @@ -0,0 +1,808 @@ +/* + * websupport.js + * ~~~~~~~~~~~~~ + * + * sphinx.websupport utilities for all documentation. + * + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +(function($) { + $.fn.autogrow = function() { + return this.each(function() { + var textarea = this; + + $.fn.autogrow.resize(textarea); + + $(textarea) + .focus(function() { + textarea.interval = setInterval(function() { + $.fn.autogrow.resize(textarea); + }, 500); + }) + .blur(function() { + clearInterval(textarea.interval); + }); + }); + }; + + $.fn.autogrow.resize = function(textarea) { + var lineHeight = parseInt($(textarea).css('line-height'), 10); + var lines = textarea.value.split('\n'); + var columns = textarea.cols; + var lineCount = 0; + $.each(lines, function() { + lineCount += Math.ceil(this.length / columns) || 1; + }); + var height = lineHeight * (lineCount + 1); + $(textarea).css('height', height); + }; +})(jQuery); + +(function($) { + var comp, by; + + function init() { + initEvents(); + initComparator(); + } + + function initEvents() { + $(document).on("click", 'a.comment-close', function(event) { + event.preventDefault(); + hide($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.vote', function(event) { + event.preventDefault(); + handleVote($(this)); + }); + $(document).on("click", 'a.reply', function(event) { + event.preventDefault(); + openReply($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.close-reply', function(event) { + event.preventDefault(); + closeReply($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.sort-option', function(event) { + event.preventDefault(); + handleReSort($(this)); + }); + $(document).on("click", 'a.show-proposal', function(event) { + event.preventDefault(); + showProposal($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.hide-proposal', function(event) { + event.preventDefault(); + hideProposal($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.show-propose-change', function(event) { + event.preventDefault(); + showProposeChange($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.hide-propose-change', function(event) { + event.preventDefault(); + hideProposeChange($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.accept-comment', function(event) { + event.preventDefault(); + acceptComment($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.delete-comment', function(event) { + event.preventDefault(); + deleteComment($(this).attr('id').substring(2)); + }); + $(document).on("click", 'a.comment-markup', function(event) { + event.preventDefault(); + toggleCommentMarkupBox($(this).attr('id').substring(2)); + }); + } + + /** + * Set comp, which is a comparator function used for sorting and + * inserting comments into the list. + */ + function setComparator() { + // If the first three letters are "asc", sort in ascending order + // and remove the prefix. + if (by.substring(0,3) == 'asc') { + var i = by.substring(3); + comp = function(a, b) { return a[i] - b[i]; }; + } else { + // Otherwise sort in descending order. + comp = function(a, b) { return b[by] - a[by]; }; + } + + // Reset link styles and format the selected sort option. + $('a.sel').attr('href', '#').removeClass('sel'); + $('a.by' + by).removeAttr('href').addClass('sel'); + } + + /** + * Create a comp function. If the user has preferences stored in + * the sortBy cookie, use those, otherwise use the default. + */ + function initComparator() { + by = 'rating'; // Default to sort by rating. + // If the sortBy cookie is set, use that instead. + if (document.cookie.length > 0) { + var start = document.cookie.indexOf('sortBy='); + if (start != -1) { + start = start + 7; + var end = document.cookie.indexOf(";", start); + if (end == -1) { + end = document.cookie.length; + by = unescape(document.cookie.substring(start, end)); + } + } + } + setComparator(); + } + + /** + * Show a comment div. + */ + function show(id) { + $('#ao' + id).hide(); + $('#ah' + id).show(); + var context = $.extend({id: id}, opts); + var popup = $(renderTemplate(popupTemplate, context)).hide(); + popup.find('textarea[name="proposal"]').hide(); + popup.find('a.by' + by).addClass('sel'); + var form = popup.find('#cf' + id); + form.submit(function(event) { + event.preventDefault(); + addComment(form); + }); + $('#s' + id).after(popup); + popup.slideDown('fast', function() { + getComments(id); + }); + } + + /** + * Hide a comment div. + */ + function hide(id) { + $('#ah' + id).hide(); + $('#ao' + id).show(); + var div = $('#sc' + id); + div.slideUp('fast', function() { + div.remove(); + }); + } + + /** + * Perform an ajax request to get comments for a node + * and insert the comments into the comments tree. + */ + function getComments(id) { + $.ajax({ + type: 'GET', + url: opts.getCommentsURL, + data: {node: id}, + success: function(data, textStatus, request) { + var ul = $('#cl' + id); + var speed = 100; + $('#cf' + id) + .find('textarea[name="proposal"]') + .data('source', data.source); + + if (data.comments.length === 0) { + ul.html('<li>No comments yet.</li>'); + ul.data('empty', true); + } else { + // If there are comments, sort them and put them in the list. + var comments = sortComments(data.comments); + speed = data.comments.length * 100; + appendComments(comments, ul); + ul.data('empty', false); + } + $('#cn' + id).slideUp(speed + 200); + ul.slideDown(speed); + }, + error: function(request, textStatus, error) { + showError('Oops, there was a problem retrieving the comments.'); + }, + dataType: 'json' + }); + } + + /** + * Add a comment via ajax and insert the comment into the comment tree. + */ + function addComment(form) { + var node_id = form.find('input[name="node"]').val(); + var parent_id = form.find('input[name="parent"]').val(); + var text = form.find('textarea[name="comment"]').val(); + var proposal = form.find('textarea[name="proposal"]').val(); + + if (text == '') { + showError('Please enter a comment.'); + return; + } + + // Disable the form that is being submitted. + form.find('textarea,input').attr('disabled', 'disabled'); + + // Send the comment to the server. + $.ajax({ + type: "POST", + url: opts.addCommentURL, + dataType: 'json', + data: { + node: node_id, + parent: parent_id, + text: text, + proposal: proposal + }, + success: function(data, textStatus, error) { + // Reset the form. + if (node_id) { + hideProposeChange(node_id); + } + form.find('textarea') + .val('') + .add(form.find('input')) + .removeAttr('disabled'); + var ul = $('#cl' + (node_id || parent_id)); + if (ul.data('empty')) { + $(ul).empty(); + ul.data('empty', false); + } + insertComment(data.comment); + var ao = $('#ao' + node_id); + ao.find('img').attr({'src': opts.commentBrightImage}); + if (node_id) { + // if this was a "root" comment, remove the commenting box + // (the user can get it back by reopening the comment popup) + $('#ca' + node_id).slideUp(); + } + }, + error: function(request, textStatus, error) { + form.find('textarea,input').removeAttr('disabled'); + showError('Oops, there was a problem adding the comment.'); + } + }); + } + + /** + * Recursively append comments to the main comment list and children + * lists, creating the comment tree. + */ + function appendComments(comments, ul) { + $.each(comments, function() { + var div = createCommentDiv(this); + ul.append($(document.createElement('li')).html(div)); + appendComments(this.children, div.find('ul.comment-children')); + // To avoid stagnating data, don't store the comments children in data. + this.children = null; + div.data('comment', this); + }); + } + + /** + * After adding a new comment, it must be inserted in the correct + * location in the comment tree. + */ + function insertComment(comment) { + var div = createCommentDiv(comment); + + // To avoid stagnating data, don't store the comments children in data. + comment.children = null; + div.data('comment', comment); + + var ul = $('#cl' + (comment.node || comment.parent)); + var siblings = getChildren(ul); + + var li = $(document.createElement('li')); + li.hide(); + + // Determine where in the parents children list to insert this comment. + for(var i=0; i < siblings.length; i++) { + if (comp(comment, siblings[i]) <= 0) { + $('#cd' + siblings[i].id) + .parent() + .before(li.html(div)); + li.slideDown('fast'); + return; + } + } + + // If we get here, this comment rates lower than all the others, + // or it is the only comment in the list. + ul.append(li.html(div)); + li.slideDown('fast'); + } + + function acceptComment(id) { + $.ajax({ + type: 'POST', + url: opts.acceptCommentURL, + data: {id: id}, + success: function(data, textStatus, request) { + $('#cm' + id).fadeOut('fast'); + $('#cd' + id).removeClass('moderate'); + }, + error: function(request, textStatus, error) { + showError('Oops, there was a problem accepting the comment.'); + } + }); + } + + function deleteComment(id) { + $.ajax({ + type: 'POST', + url: opts.deleteCommentURL, + data: {id: id}, + success: function(data, textStatus, request) { + var div = $('#cd' + id); + if (data == 'delete') { + // Moderator mode: remove the comment and all children immediately + div.slideUp('fast', function() { + div.remove(); + }); + return; + } + // User mode: only mark the comment as deleted + div + .find('span.user-id:first') + .text('[deleted]').end() + .find('div.comment-text:first') + .text('[deleted]').end() + .find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id + + ', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id) + .remove(); + var comment = div.data('comment'); + comment.username = '[deleted]'; + comment.text = '[deleted]'; + div.data('comment', comment); + }, + error: function(request, textStatus, error) { + showError('Oops, there was a problem deleting the comment.'); + } + }); + } + + function showProposal(id) { + $('#sp' + id).hide(); + $('#hp' + id).show(); + $('#pr' + id).slideDown('fast'); + } + + function hideProposal(id) { + $('#hp' + id).hide(); + $('#sp' + id).show(); + $('#pr' + id).slideUp('fast'); + } + + function showProposeChange(id) { + $('#pc' + id).hide(); + $('#hc' + id).show(); + var textarea = $('#pt' + id); + textarea.val(textarea.data('source')); + $.fn.autogrow.resize(textarea[0]); + textarea.slideDown('fast'); + } + + function hideProposeChange(id) { + $('#hc' + id).hide(); + $('#pc' + id).show(); + var textarea = $('#pt' + id); + textarea.val('').removeAttr('disabled'); + textarea.slideUp('fast'); + } + + function toggleCommentMarkupBox(id) { + $('#mb' + id).toggle(); + } + + /** Handle when the user clicks on a sort by link. */ + function handleReSort(link) { + var classes = link.attr('class').split(/\s+/); + for (var i=0; i<classes.length; i++) { + if (classes[i] != 'sort-option') { + by = classes[i].substring(2); + } + } + setComparator(); + // Save/update the sortBy cookie. + var expiration = new Date(); + expiration.setDate(expiration.getDate() + 365); + document.cookie= 'sortBy=' + escape(by) + + ';expires=' + expiration.toUTCString(); + $('ul.comment-ul').each(function(index, ul) { + var comments = getChildren($(ul), true); + comments = sortComments(comments); + appendComments(comments, $(ul).empty()); + }); + } + + /** + * Function to process a vote when a user clicks an arrow. + */ + function handleVote(link) { + if (!opts.voting) { + showError("You'll need to login to vote."); + return; + } + + var id = link.attr('id'); + if (!id) { + // Didn't click on one of the voting arrows. + return; + } + // If it is an unvote, the new vote value is 0, + // Otherwise it's 1 for an upvote, or -1 for a downvote. + var value = 0; + if (id.charAt(1) != 'u') { + value = id.charAt(0) == 'u' ? 1 : -1; + } + // The data to be sent to the server. + var d = { + comment_id: id.substring(2), + value: value + }; + + // Swap the vote and unvote links. + link.hide(); + $('#' + id.charAt(0) + (id.charAt(1) == 'u' ? 'v' : 'u') + d.comment_id) + .show(); + + // The div the comment is displayed in. + var div = $('div#cd' + d.comment_id); + var data = div.data('comment'); + + // If this is not an unvote, and the other vote arrow has + // already been pressed, unpress it. + if ((d.value !== 0) && (data.vote === d.value * -1)) { + $('#' + (d.value == 1 ? 'd' : 'u') + 'u' + d.comment_id).hide(); + $('#' + (d.value == 1 ? 'd' : 'u') + 'v' + d.comment_id).show(); + } + + // Update the comments rating in the local data. + data.rating += (data.vote === 0) ? d.value : (d.value - data.vote); + data.vote = d.value; + div.data('comment', data); + + // Change the rating text. + div.find('.rating:first') + .text(data.rating + ' point' + (data.rating == 1 ? '' : 's')); + + // Send the vote information to the server. + $.ajax({ + type: "POST", + url: opts.processVoteURL, + data: d, + error: function(request, textStatus, error) { + showError('Oops, there was a problem casting that vote.'); + } + }); + } + + /** + * Open a reply form used to reply to an existing comment. + */ + function openReply(id) { + // Swap out the reply link for the hide link + $('#rl' + id).hide(); + $('#cr' + id).show(); + + // Add the reply li to the children ul. + var div = $(renderTemplate(replyTemplate, {id: id})).hide(); + $('#cl' + id) + .prepend(div) + // Setup the submit handler for the reply form. + .find('#rf' + id) + .submit(function(event) { + event.preventDefault(); + addComment($('#rf' + id)); + closeReply(id); + }) + .find('input[type=button]') + .click(function() { + closeReply(id); + }); + div.slideDown('fast', function() { + $('#rf' + id).find('textarea').focus(); + }); + } + + /** + * Close the reply form opened with openReply. + */ + function closeReply(id) { + // Remove the reply div from the DOM. + $('#rd' + id).slideUp('fast', function() { + $(this).remove(); + }); + + // Swap out the hide link for the reply link + $('#cr' + id).hide(); + $('#rl' + id).show(); + } + + /** + * Recursively sort a tree of comments using the comp comparator. + */ + function sortComments(comments) { + comments.sort(comp); + $.each(comments, function() { + this.children = sortComments(this.children); + }); + return comments; + } + + /** + * Get the children comments from a ul. If recursive is true, + * recursively include childrens' children. + */ + function getChildren(ul, recursive) { + var children = []; + ul.children().children("[id^='cd']") + .each(function() { + var comment = $(this).data('comment'); + if (recursive) + comment.children = getChildren($(this).find('#cl' + comment.id), true); + children.push(comment); + }); + return children; + } + + /** Create a div to display a comment in. */ + function createCommentDiv(comment) { + if (!comment.displayed && !opts.moderator) { + return $('<div class="moderate">Thank you! Your comment will show up ' + + 'once it is has been approved by a moderator.</div>'); + } + // Prettify the comment rating. + comment.pretty_rating = comment.rating + ' point' + + (comment.rating == 1 ? '' : 's'); + // Make a class (for displaying not yet moderated comments differently) + comment.css_class = comment.displayed ? '' : ' moderate'; + // Create a div for this comment. + var context = $.extend({}, opts, comment); + var div = $(renderTemplate(commentTemplate, context)); + + // If the user has voted on this comment, highlight the correct arrow. + if (comment.vote) { + var direction = (comment.vote == 1) ? 'u' : 'd'; + div.find('#' + direction + 'v' + comment.id).hide(); + div.find('#' + direction + 'u' + comment.id).show(); + } + + if (opts.moderator || comment.text != '[deleted]') { + div.find('a.reply').show(); + if (comment.proposal_diff) + div.find('#sp' + comment.id).show(); + if (opts.moderator && !comment.displayed) + div.find('#cm' + comment.id).show(); + if (opts.moderator || (opts.username == comment.username)) + div.find('#dc' + comment.id).show(); + } + return div; + } + + /** + * A simple template renderer. Placeholders such as <%id%> are replaced + * by context['id'] with items being escaped. Placeholders such as <#id#> + * are not escaped. + */ + function renderTemplate(template, context) { + var esc = $(document.createElement('div')); + + function handle(ph, escape) { + var cur = context; + $.each(ph.split('.'), function() { + cur = cur[this]; + }); + return escape ? esc.text(cur || "").html() : cur; + } + + return template.replace(/<([%#])([\w\.]*)\1>/g, function() { + return handle(arguments[2], arguments[1] == '%' ? true : false); + }); + } + + /** Flash an error message briefly. */ + function showError(message) { + $(document.createElement('div')).attr({'class': 'popup-error'}) + .append($(document.createElement('div')) + .attr({'class': 'error-message'}).text(message)) + .appendTo('body') + .fadeIn("slow") + .delay(2000) + .fadeOut("slow"); + } + + /** Add a link the user uses to open the comments popup. */ + $.fn.comment = function() { + return this.each(function() { + var id = $(this).attr('id').substring(1); + var count = COMMENT_METADATA[id]; + var title = count + ' comment' + (count == 1 ? '' : 's'); + var image = count > 0 ? opts.commentBrightImage : opts.commentImage; + var addcls = count == 0 ? ' nocomment' : ''; + $(this) + .append( + $(document.createElement('a')).attr({ + href: '#', + 'class': 'sphinx-comment-open' + addcls, + id: 'ao' + id + }) + .append($(document.createElement('img')).attr({ + src: image, + alt: 'comment', + title: title + })) + .click(function(event) { + event.preventDefault(); + show($(this).attr('id').substring(2)); + }) + ) + .append( + $(document.createElement('a')).attr({ + href: '#', + 'class': 'sphinx-comment-close hidden', + id: 'ah' + id + }) + .append($(document.createElement('img')).attr({ + src: opts.closeCommentImage, + alt: 'close', + title: 'close' + })) + .click(function(event) { + event.preventDefault(); + hide($(this).attr('id').substring(2)); + }) + ); + }); + }; + + var opts = { + processVoteURL: '/_process_vote', + addCommentURL: '/_add_comment', + getCommentsURL: '/_get_comments', + acceptCommentURL: '/_accept_comment', + deleteCommentURL: '/_delete_comment', + commentImage: '/static/_static/comment.png', + closeCommentImage: '/static/_static/comment-close.png', + loadingImage: '/static/_static/ajax-loader.gif', + commentBrightImage: '/static/_static/comment-bright.png', + upArrow: '/static/_static/up.png', + downArrow: '/static/_static/down.png', + upArrowPressed: '/static/_static/up-pressed.png', + downArrowPressed: '/static/_static/down-pressed.png', + voting: false, + moderator: false + }; + + if (typeof COMMENT_OPTIONS != "undefined") { + opts = jQuery.extend(opts, COMMENT_OPTIONS); + } + + var popupTemplate = '\ + <div class="sphinx-comments" id="sc<%id%>">\ + <p class="sort-options">\ + Sort by:\ + <a href="#" class="sort-option byrating">best rated</a>\ + <a href="#" class="sort-option byascage">newest</a>\ + <a href="#" class="sort-option byage">oldest</a>\ + </p>\ + <div class="comment-header">Comments</div>\ + <div class="comment-loading" id="cn<%id%>">\ + loading comments... <img src="<%loadingImage%>" alt="" /></div>\ + <ul id="cl<%id%>" class="comment-ul"></ul>\ + <div id="ca<%id%>">\ + <p class="add-a-comment">Add a comment\ + (<a href="#" class="comment-markup" id="ab<%id%>">markup</a>):</p>\ + <div class="comment-markup-box" id="mb<%id%>">\ + reStructured text markup: <i>*emph*</i>, <b>**strong**</b>, \ + <code>``code``</code>, \ + code blocks: <code>::</code> and an indented block after blank line</div>\ + <form method="post" id="cf<%id%>" class="comment-form" action="">\ + <textarea name="comment" cols="80"></textarea>\ + <p class="propose-button">\ + <a href="#" id="pc<%id%>" class="show-propose-change">\ + Propose a change ▹\ + </a>\ + <a href="#" id="hc<%id%>" class="hide-propose-change">\ + Propose a change ▿\ + </a>\ + </p>\ + <textarea name="proposal" id="pt<%id%>" cols="80"\ + spellcheck="false"></textarea>\ + <input type="submit" value="Add comment" />\ + <input type="hidden" name="node" value="<%id%>" />\ + <input type="hidden" name="parent" value="" />\ + </form>\ + </div>\ + </div>'; + + var commentTemplate = '\ + <div id="cd<%id%>" class="sphinx-comment<%css_class%>">\ + <div class="vote">\ + <div class="arrow">\ + <a href="#" id="uv<%id%>" class="vote" title="vote up">\ + <img src="<%upArrow%>" />\ + </a>\ + <a href="#" id="uu<%id%>" class="un vote" title="vote up">\ + <img src="<%upArrowPressed%>" />\ + </a>\ + </div>\ + <div class="arrow">\ + <a href="#" id="dv<%id%>" class="vote" title="vote down">\ + <img src="<%downArrow%>" id="da<%id%>" />\ + </a>\ + <a href="#" id="du<%id%>" class="un vote" title="vote down">\ + <img src="<%downArrowPressed%>" />\ + </a>\ + </div>\ + </div>\ + <div class="comment-content">\ + <p class="tagline comment">\ + <span class="user-id"><%username%></span>\ + <span class="rating"><%pretty_rating%></span>\ + <span class="delta"><%time.delta%></span>\ + </p>\ + <div class="comment-text comment"><#text#></div>\ + <p class="comment-opts comment">\ + <a href="#" class="reply hidden" id="rl<%id%>">reply ▹</a>\ + <a href="#" class="close-reply" id="cr<%id%>">reply ▿</a>\ + <a href="#" id="sp<%id%>" class="show-proposal">proposal ▹</a>\ + <a href="#" id="hp<%id%>" class="hide-proposal">proposal ▿</a>\ + <a href="#" id="dc<%id%>" class="delete-comment hidden">delete</a>\ + <span id="cm<%id%>" class="moderation hidden">\ + <a href="#" id="ac<%id%>" class="accept-comment">accept</a>\ + </span>\ + </p>\ + <pre class="proposal" id="pr<%id%>">\ +<#proposal_diff#>\ + </pre>\ + <ul class="comment-children" id="cl<%id%>"></ul>\ + </div>\ + <div class="clearleft"></div>\ + </div>\ + </div>'; + + var replyTemplate = '\ + <li>\ + <div class="reply-div" id="rd<%id%>">\ + <form id="rf<%id%>">\ + <textarea name="comment" cols="80"></textarea>\ + <input type="submit" value="Add reply" />\ + <input type="button" value="Cancel" />\ + <input type="hidden" name="parent" value="<%id%>" />\ + <input type="hidden" name="node" value="" />\ + </form>\ + </div>\ + </li>'; + + $(document).ready(function() { + init(); + }); +})(jQuery); + +$(document).ready(function() { + // add comment anchors for all paragraphs that are commentable + $('.sphinx-has-comment').comment(); + + // highlight search words in search results + $("div.context").each(function() { + var params = $.getQueryParameters(); + var terms = (params.q) ? params.q[0].split(/\s+/) : []; + var result = $(this); + $.each(terms, function() { + result.highlightText(this.toLowerCase(), 'highlighted'); + }); + }); + + // directly open comment window if requested + var anchor = document.location.hash; + if (anchor.substring(0, 9) == '#comment-') { + $('#ao' + anchor.substring(9)).click(); + document.location.hash = '#s' + anchor.substring(9); + } +}); diff --git a/documentation/sphinx/.build/genindex.html b/documentation/sphinx/.build/genindex.html new file mode 100644 index 0000000000000000000000000000000000000000..4e9343e85407bee72ecaa20e57ae7d23fe43e81a --- /dev/null +++ b/documentation/sphinx/.build/genindex.html @@ -0,0 +1,1166 @@ + + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Index — WiseMove documentation</title> + <link rel="stylesheet" href="_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="#" /> + <link rel="search" title="Search" href="search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>Index</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + +<h1 id="index">Index</h1> + +<div class="genindex-jumpbox"> + <a href="#A"><strong>A</strong></a> + | <a href="#B"><strong>B</strong></a> + | <a href="#C"><strong>C</strong></a> + | <a href="#D"><strong>D</strong></a> + | <a href="#E"><strong>E</strong></a> + | <a href="#F"><strong>F</strong></a> + | <a href="#G"><strong>G</strong></a> + | <a href="#H"><strong>H</strong></a> + | <a href="#I"><strong>I</strong></a> + | <a href="#K"><strong>K</strong></a> + | <a href="#L"><strong>L</strong></a> + | <a href="#M"><strong>M</strong></a> + | <a href="#N"><strong>N</strong></a> + | <a href="#O"><strong>O</strong></a> + | <a href="#P"><strong>P</strong></a> + | <a href="#R"><strong>R</strong></a> + | <a href="#S"><strong>S</strong></a> + | <a href="#T"><strong>T</strong></a> + | <a href="#U"><strong>U</strong></a> + | <a href="#V"><strong>V</strong></a> + | <a href="#W"><strong>W</strong></a> + | <a href="#X"><strong>X</strong></a> + +</div> +<h2 id="A">A</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.action_space">action_space (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.action_space">(options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.adj">adj (backends.mcts_learner.MCTSLearner attribute)</a> + + <ul> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.adj">(options.options_loader.OptionsGraph attribute)</a> +</li> + </ul></li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.aggressive_driving_policy">aggressive_driving_policy() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.BoundingBox.all_same_sign_in_list">all_same_sign_in_list() (env.simple_intersection.utilities.BoundingBox static method)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/model_checker.html#model_checker.atomic_propositions_base.AtomicPropositionsBase.APdict">APdict (model_checker.atomic_propositions_base.AtomicPropositionsBase attribute)</a> + + <ul> + <li><a href=".doc/model_checker.html#model_checker.LTL_property_base.LTLPropertyBase.APdict">(model_checker.LTL_property_base.LTLPropertyBase attribute)</a> +</li> + <li><a href=".doc/model_checker.simple_intersection.html#model_checker.simple_intersection.classes.AtomicPropositions.APdict">(model_checker.simple_intersection.classes.AtomicPropositions attribute)</a> +</li> + <li><a href=".doc/model_checker.simple_intersection.html#model_checker.simple_intersection.classes.LTLProperty.APdict">(model_checker.simple_intersection.classes.LTLProperty attribute)</a> +</li> + </ul></li> + <li><a href=".doc/model_checker.simple_intersection.html#model_checker.simple_intersection.classes.AtomicPropositions">AtomicPropositions (class in model_checker.simple_intersection.classes)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.atomic_propositions_base.AtomicPropositionsBase">AtomicPropositionsBase (class in model_checker.atomic_propositions_base)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="B">B</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#module-backends">backends (module)</a> +</li> + <li><a href=".doc/backends.html#module-backends.baselines_learner">backends.baselines_learner (module)</a> +</li> + <li><a href=".doc/backends.html#module-backends.controller_base">backends.controller_base (module)</a> +</li> + <li><a href=".doc/backends.html#module-backends.kerasrl_learner">backends.kerasrl_learner (module)</a> +</li> + <li><a href=".doc/backends.html#module-backends.learner_base">backends.learner_base (module)</a> +</li> + <li><a href=".doc/backends.html#module-backends.manual_policy">backends.manual_policy (module)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#module-backends.mcts_learner">backends.mcts_learner (module)</a> +</li> + <li><a href=".doc/backends.html#module-backends.online_mcts_controller">backends.online_mcts_controller (module)</a> +</li> + <li><a href=".doc/backends.html#module-backends.policy_base">backends.policy_base (module)</a> +</li> + <li><a href=".doc/backends.html#module-backends.rl_controller">backends.rl_controller (module)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.atomic_propositions_base.Bits">Bits (class in model_checker.atomic_propositions_base)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.BoundingBox">BoundingBox (class in env.simple_intersection.utilities)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer">Buffer (class in model_checker.scanner)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="C">C</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.calculate_s">calculate_s() (in module env.simple_intersection.utilities)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.calculate_v_max">calculate_v_max() (in module env.simple_intersection.utilities)</a> +</li> + <li><a href=".doc/backends.html#backends.controller_base.ControllerBase.can_transition">can_transition() (backends.controller_base.ControllerBase method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.manual_policy.ManualPolicy.can_transition">(backends.manual_policy.ManualPolicy method)</a> +</li> + <li><a href=".doc/backends.html#backends.online_mcts_controller.OnlineMCTSController.can_transition">(backends.online_mcts_controller.OnlineMCTSController method)</a> +</li> + <li><a href=".doc/backends.html#backends.rl_controller.RLController.can_transition">(backends.rl_controller.RLController method)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.online_mcts_controller.OnlineMCTSController.change_low_level_references">change_low_level_references() (backends.online_mcts_controller.OnlineMCTSController method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.ChangeLane">ChangeLane (class in options.simple_intersection.maneuvers)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.charSetSize">charSetSize (model_checker.scanner.Scanner attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.LTL_property_base.LTLPropertyBase.check">check() (model_checker.LTL_property_base.LTLPropertyBase method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Check">Check() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.check_ego_collision">check_ego_collision() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.LTL_property_base.LTLPropertyBase.check_incremental">check_incremental() (model_checker.LTL_property_base.LTLPropertyBase method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Check_old">Check_old() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.check_other_veh_collisions">check_other_veh_collisions() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.CheckIncremental">CheckIncremental() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.CheckLiteral">CheckLiteral() (model_checker.scanner.Scanner method)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.collision_happened">collision_happened (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.Comment0">Comment0() (model_checker.scanner.Scanner method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.config_Pyglet">config_Pyglet() (in module env.simple_intersection.utilities)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Conjunction">Conjunction() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/backends.html#backends.controller_base.ControllerBase">ControllerBase (class in backends.controller_base)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.copy">copy() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost">cost() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost_normalization_ranges">cost_normalization_ranges (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.cost_weights">cost_weights (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.count">count (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent.create_agent">create_agent() (backends.baselines_learner.PPO2Agent method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.create_agent">(backends.kerasrl_learner.DDPGLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.create_agent">(backends.kerasrl_learner.DQNLearner method)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.curr_node_alias">curr_node_alias (backends.mcts_learner.MCTSLearner attribute)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.curr_node_num">curr_node_num (backends.mcts_learner.MCTSLearner attribute)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.current_model_checking_result">current_model_checking_result() (env.env_base.EpisodicEnvBase method)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.current_node">current_node (options.options_loader.OptionsGraph attribute)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="D">D</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner">DDPGLearner (class in backends.kerasrl_learner)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.disable_LTL_preconditions">disable_LTL_preconditions() (env.env_base.EpisodicEnvBase method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Disjunction">Disjunction() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.display">display() (model_checker.parser.Errors static method)</a> +</li> + <li><a href=".doc/backends.html#backends.controller_base.ControllerBase.do_transition">do_transition() (backends.controller_base.ControllerBase method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.manual_policy.ManualPolicy.do_transition">(backends.manual_policy.ManualPolicy method)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.do_transition">(backends.mcts_learner.MCTSLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.online_mcts_controller.OnlineMCTSController.do_transition">(backends.online_mcts_controller.OnlineMCTSController method)</a> +</li> + <li><a href=".doc/backends.html#backends.rl_controller.RLController.do_transition">(backends.rl_controller.RLController method)</a> +</li> + </ul></li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.BoundingBox.does_bounding_box_cross_line">does_bounding_box_cross_line() (env.simple_intersection.utilities.BoundingBox static method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.BoundingBox.does_bounding_box_intersect">does_bounding_box_intersect() (env.simple_intersection.utilities.BoundingBox static method)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNAgentOverOptions">DQNAgentOverOptions (class in backends.kerasrl_learner)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner">DQNLearner (class in backends.kerasrl_learner)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.road_networks.RoadNetworkCross.draw">draw() (env.simple_intersection.road_networks.RoadNetworkCross method)</a> + + <ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.shapes.Image.draw">(env.simple_intersection.shapes.Image method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.shapes.Rectangle.draw">(env.simple_intersection.shapes.Rectangle method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.shapes.Text.draw">(env.simple_intersection.shapes.Text method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.draw">(env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicle_networks.VehicleNetworkCross.draw">(env.simple_intersection.vehicle_networks.VehicleNetworkCross method)</a> +</li> + </ul></li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.draw_all_shapes">draw_all_shapes() (in module env.simple_intersection.utilities)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.DT">DT (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.DT_over_2">DT_over_2 (in module env.simple_intersection.constants)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="E">E</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.edges">edges (options.options_loader.OptionsGraph attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.ego">ego (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.EGO_INDEX">EGO_INDEX (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.ego_info_text">ego_info_text (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.enable_LTL_preconditions">enable_LTL_preconditions() (env.env_base.EpisodicEnvBase method)</a> +</li> + <li><a href=".doc/env.html#module-env">env (module)</a> +</li> + <li><a href=".doc/env.html#module-env.env_base">env.env_base (module)</a> +</li> + <li><a href=".doc/env.html#module-env.road_env">env.road_env (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection">env.simple_intersection (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.constants">env.simple_intersection.constants (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.features">env.simple_intersection.features (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.road_geokinemetry">env.simple_intersection.road_geokinemetry (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.road_networks">env.simple_intersection.road_networks (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.shapes">env.simple_intersection.shapes (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.simple_intersection_env">env.simple_intersection.simple_intersection_env (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.utilities">env.simple_intersection.utilities (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.vehicle_networks">env.simple_intersection.vehicle_networks (module)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#module-env.simple_intersection.vehicles">env.simple_intersection.vehicles (module)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.eof">eof (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer.EOF">EOF (model_checker.scanner.Buffer attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.eofSym">eofSym (model_checker.scanner.Scanner attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.EOL">EOL (model_checker.scanner.Scanner attribute)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase">EpisodicEnvBase (class in env.env_base)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.errDist">errDist (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.errMsgFormat">errMsgFormat (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.errorMessages">errorMessages (model_checker.parser.Parser attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.ErrorRec">ErrorRec (class in model_checker.parser)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors">Errors (class in model_checker.parser)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.errors">errors (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/high_level_policy_main.html#high_level_policy_main.evaluate_high_level_policy">evaluate_high_level_policy() (in module high_level_policy_main)</a> +</li> + <li><a href=".doc/mcts.html#mcts.evaluate_online_mcts">evaluate_online_mcts() (in module mcts)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.Exception">Exception() (model_checker.parser.Errors static method)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.execute_controller_policy">execute_controller_policy() (options.options_loader.OptionsGraph method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Expect">Expect() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.ExpectWeak">ExpectWeak() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.extra_initiation_condition">extra_initiation_condition (options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.extra_initiation_condition">(options.simple_intersection.mcts_maneuvers.MCTSChangeLane attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSFollow.extra_initiation_condition">(options.simple_intersection.mcts_maneuvers.MCTSFollow attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSKeepLane.extra_initiation_condition">(options.simple_intersection.mcts_maneuvers.MCTSKeepLane attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSStop.extra_initiation_condition">(options.simple_intersection.mcts_maneuvers.MCTSStop attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSWait.extra_initiation_condition">(options.simple_intersection.mcts_maneuvers.MCTSWait attribute)</a> +</li> + </ul></li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.extra_termination_condition">extra_termination_condition (options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.extra_termination_condition">(options.simple_intersection.mcts_maneuvers.MCTSChangeLane attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSFollow.extra_termination_condition">(options.simple_intersection.mcts_maneuvers.MCTSFollow attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSWait.extra_termination_condition">(options.simple_intersection.mcts_maneuvers.MCTSWait attribute)</a> +</li> + </ul></li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.features.extract_ego_features">extract_ego_features() (in module env.simple_intersection.features)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.features.extract_other_veh_features">extract_other_veh_features() (in module env.simple_intersection.features)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="F">F</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Factor">Factor() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.FALSE">FALSE (model_checker.parser.Parser attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.features.Features">Features (class in env.simple_intersection.features)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.fileName">fileName (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/high_level_policy_main.html#high_level_policy_main.find_good_high_level_policy">find_good_high_level_policy() (in module high_level_policy_main)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent.fit">fit() (backends.baselines_learner.PPO2Agent method)</a> +</li> + <li><a href=".doc/mcts.html#mcts.Logger.flush">flush() (mcts.Logger method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.Follow">Follow (class in options.simple_intersection.maneuvers)</a> +</li> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent.forward">forward() (backends.baselines_learner.PPO2Agent method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNAgentOverOptions.forward">(backends.kerasrl_learner.DQNAgentOverOptions method)</a> +</li> + </ul></li> + </ul></td> +</tr></table> + +<h2 id="G">G</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.generate_learning_scenario">generate_learning_scenario() (options.simple_intersection.maneuver_base.ManeuverBase method)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.ChangeLane.generate_learning_scenario">(options.simple_intersection.maneuvers.ChangeLane method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.Follow.generate_learning_scenario">(options.simple_intersection.maneuvers.Follow method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.KeepLane.generate_learning_scenario">(options.simple_intersection.maneuvers.KeepLane method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.Stop.generate_learning_scenario">(options.simple_intersection.maneuvers.Stop method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.Wait.generate_learning_scenario">(options.simple_intersection.maneuvers.Wait method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.generate_learning_scenario">(options.simple_intersection.mcts_maneuvers.MCTSChangeLane method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSFollow.generate_learning_scenario">(options.simple_intersection.mcts_maneuvers.MCTSFollow method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSKeepLane.generate_learning_scenario">(options.simple_intersection.mcts_maneuvers.MCTSKeepLane method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSStop.generate_learning_scenario">(options.simple_intersection.mcts_maneuvers.MCTSStop method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSWait.generate_learning_scenario">(options.simple_intersection.mcts_maneuvers.MCTSWait method)</a> +</li> + </ul></li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.generate_scenario">generate_scenario() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.generate_scenario">(options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + </ul></li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.generate_validation_scenario">generate_validation_scenario() (options.simple_intersection.maneuver_base.ManeuverBase method)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSFollow.generate_validation_scenario">(options.simple_intersection.mcts_maneuvers.MCTSFollow method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSKeepLane.generate_validation_scenario">(options.simple_intersection.mcts_maneuvers.MCTSKeepLane method)</a> +</li> + </ul></li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Get">Get() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.get_APs">get_APs() (in module env.simple_intersection.utilities)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.get_best_node">get_best_node() (backends.mcts_learner.MCTSLearner method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.VehicleState.get_bounding_box">get_bounding_box() (env.simple_intersection.vehicles.VehicleState method)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.get_default_actor_model">get_default_actor_model() (backends.kerasrl_learner.DDPGLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.get_default_critic_model">get_default_critic_model() (backends.kerasrl_learner.DDPGLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.get_default_memory">get_default_memory() (backends.kerasrl_learner.DDPGLearner method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.get_default_memory">(backends.kerasrl_learner.DQNLearner method)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.get_default_model">get_default_model() (backends.kerasrl_learner.DQNLearner method)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent.get_default_policy">get_default_policy() (backends.baselines_learner.PPO2Agent method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.get_default_policy">(backends.kerasrl_learner.DQNLearner method)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.get_default_randomprocess">get_default_randomprocess() (backends.kerasrl_learner.DDPGLearner method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.features.Features.get_features_tuple">get_features_tuple() (env.simple_intersection.features.Features method)</a> + + <ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.get_features_tuple">(env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNAgentOverOptions.get_modified_q_values">get_modified_q_values() (backends.kerasrl_learner.DQNAgentOverOptions method)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.get_number_of_nodes">get_number_of_nodes() (options.options_loader.OptionsGraph method)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.get_q_value">get_q_value() (backends.kerasrl_learner.DQNLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.get_q_value_using_option_alias">get_q_value_using_option_alias() (backends.kerasrl_learner.DQNLearner method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.get_reduced_feature_length">get_reduced_feature_length() (options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.get_reduced_features_tuple">get_reduced_features_tuple() (options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.get_softq_value_using_option_alias">get_softq_value_using_option_alias() (backends.kerasrl_learner.DQNLearner method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.get_V2V_distance">get_V2V_distance() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.get_veh_attributes">get_veh_attributes() (in module env.simple_intersection.utilities)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.getParsingPos">getParsingPos() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer.getPos">getPos() (model_checker.scanner.Buffer method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer.getString">getString() (model_checker.scanner.Buffer method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Position.getSubstring">getSubstring() (model_checker.scanner.Position method)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.goal_achieved">goal_achieved (env.env_base.EpisodicEnvBase attribute)</a> + + <ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.goal_achieved">(env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.goal_achieved">(options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.ChangeLane.goal_achieved">(options.simple_intersection.maneuvers.ChangeLane attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.goal_achieved">(options.simple_intersection.mcts_maneuvers.MCTSChangeLane attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSStop.goal_achieved">(options.simple_intersection.mcts_maneuvers.MCTSStop attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSWait.goal_achieved">(options.simple_intersection.mcts_maneuvers.MCTSWait attribute)</a> +</li> + </ul></li> + <li><a href=".doc/env.html#env.env_base.GymCompliantEnvBase">GymCompliantEnvBase (class in env.env_base)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="H">H</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.H_CAR_SCALE">H_CAR_SCALE() (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.H_SPACE_SCALE">H_SPACE_SCALE (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.H_TILE_SCALE">H_TILE_SCALE() (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.high_level_extra_reward">high_level_extra_reward (options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.ChangeLane.high_level_extra_reward">(options.simple_intersection.maneuvers.ChangeLane attribute)</a> +</li> + </ul></li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/high_level_policy_main.html#module-high_level_policy_main">high_level_policy_main (module)</a> +</li> + <li><a href=".doc/high_level_policy_main.html#high_level_policy_main.high_level_policy_testing">high_level_policy_testing() (in module high_level_policy_main)</a> +</li> + <li><a href=".doc/high_level_policy_main.html#high_level_policy_main.high_level_policy_training">high_level_policy_training() (in module high_level_policy_main)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="I">I</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.shapes.Image">Image (class in env.simple_intersection.shapes)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Implication">Implication() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.Init">Init() (model_checker.parser.Errors static method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.init_APs">init_APs() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.Vehicle.init_local_discrete_var">init_local_discrete_var() (env.simple_intersection.vehicles.Vehicle method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.initiation_condition">initiation_condition (options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.is_ego_off_road">is_ego_off_road() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.is_terminal">is_terminal() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.Vehicle.is_within_road_boundaries">is_within_road_boundaries() (env.simple_intersection.vehicles.Vehicle method)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="K">K</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.KeepLane">KeepLane (class in options.simple_intersection.maneuvers)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="L">L</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.LANE_SEPARATOR_HALF_WIDTH">LANE_SEPARATOR_HALF_WIDTH (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.LANE_WIDTH">LANE_WIDTH (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/backends.html#backends.learner_base.LearnerBase">LearnerBase (class in backends.learner_base)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.learning_mode">learning_mode (options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.LexString">LexString() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.listName">listName (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.load_model">load_model() (backends.kerasrl_learner.DDPGLearner method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.load_model">(backends.kerasrl_learner.DQNLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.learner_base.LearnerBase.load_model">(backends.learner_base.LearnerBase method)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.load_model">(backends.mcts_learner.MCTSLearner method)</a> +</li> + </ul></li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.load_trained_low_level_policies">load_trained_low_level_policies() (options.options_loader.OptionsGraph method)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent.load_weights">load_weights() (backends.baselines_learner.PPO2Agent method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.BoundingBox.localize_bounding_box_wrt_line">localize_bounding_box_wrt_line() (env.simple_intersection.utilities.BoundingBox static method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.BoundingBox.localize_point_wrt_line">localize_point_wrt_line() (env.simple_intersection.utilities.BoundingBox static method)</a> +</li> + <li><a href=".doc/mcts.html#mcts.Logger">Logger (class in mcts)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.LookAheadString">LookAheadString() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.low_level_policy">low_level_policy() (options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + <li><a href=".doc/low_level_policy_main.html#module-low_level_policy_main">low_level_policy_main (module)</a> +</li> + <li><a href=".doc/low_level_policy_main.html#low_level_policy_main.low_level_policy_testing">low_level_policy_testing() (in module low_level_policy_main)</a> +</li> + <li><a href=".doc/low_level_policy_main.html#low_level_policy_main.low_level_policy_training">low_level_policy_training() (in module low_level_policy_main)</a> +</li> + <li><a href=".doc/backends.html#backends.controller_base.ControllerBase.low_level_step_current_node">low_level_step_current_node() (backends.controller_base.ControllerBase method)</a> +</li> + <li><a href=".doc/model_checker.simple_intersection.html#model_checker.simple_intersection.classes.LTLProperty">LTLProperty (class in model_checker.simple_intersection.classes)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.LTL_property_base.LTLPropertyBase">LTLPropertyBase (class in model_checker.LTL_property_base)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="M">M</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.M">M (backends.mcts_learner.MCTSLearner attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase">ManeuverBase (class in options.simple_intersection.maneuver_base)</a> +</li> + <li><a href=".doc/backends.html#backends.manual_policy.ManualPolicy">ManualPolicy (class in backends.manual_policy)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.MAX_ACCELERATION">MAX_ACCELERATION (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.max_ego_theta">max_ego_theta (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.max_goal_distance">max_goal_distance (options.simple_intersection.mcts_maneuvers.MCTSChangeLane attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.MAX_NUM_VEHICLES">MAX_NUM_VEHICLES (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.MAX_STEERING_ANGLE">MAX_STEERING_ANGLE (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.MAX_STEERING_ANGLE_RATE">MAX_STEERING_ANGLE_RATE (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.maxT">maxT (model_checker.parser.Parser attribute)</a> + + <ul> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.maxT">(model_checker.scanner.Scanner attribute)</a> +</li> + </ul></li> + <li><a href=".doc/mcts.html#module-mcts">mcts (module)</a> +</li> + <li><a href=".doc/mcts.html#mcts.mcts_evaluation">mcts_evaluation() (in module mcts)</a> +</li> + <li><a href=".doc/mcts.html#mcts.mcts_training">mcts_training() (in module mcts)</a> +</li> + <li><a href=".doc/mcts.html#mcts.mcts_visualize">mcts_visualize() (in module mcts)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSChangeLane">MCTSChangeLane (class in options.simple_intersection.mcts_maneuvers)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSFollow">MCTSFollow (class in options.simple_intersection.mcts_maneuvers)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSKeepLane">MCTSKeepLane (class in options.simple_intersection.mcts_maneuvers)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner">MCTSLearner (class in backends.mcts_learner)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSStop">MCTSStop (class in options.simple_intersection.mcts_maneuvers)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSWait">MCTSWait (class in options.simple_intersection.mcts_maneuvers)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.mergedList">mergedList (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.mergeErrors">mergeErrors (model_checker.parser.Errors attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.ChangeLane.min_y_distance">min_y_distance (options.simple_intersection.maneuvers.ChangeLane attribute)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.mcts_maneuvers.MCTSChangeLane.min_y_distance">(options.simple_intersection.mcts_maneuvers.MCTSChangeLane attribute)</a> +</li> + </ul></li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.minErrDist">minErrDist (model_checker.parser.Errors attribute)</a> + + <ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.minErrDist">(model_checker.parser.Parser attribute)</a> +</li> + </ul></li> + <li><a href=".doc/model_checker.html#module-model_checker">model_checker (module)</a> +</li> + <li><a href=".doc/model_checker.html#module-model_checker.atomic_propositions_base">model_checker.atomic_propositions_base (module)</a> +</li> + <li><a href=".doc/model_checker.html#module-model_checker.LTL_property_base">model_checker.LTL_property_base (module)</a> +</li> + <li><a href=".doc/model_checker.html#module-model_checker.parser">model_checker.parser (module)</a> +</li> + <li><a href=".doc/model_checker.html#module-model_checker.scanner">model_checker.scanner (module)</a> +</li> + <li><a href=".doc/model_checker.simple_intersection.html#module-model_checker.simple_intersection">model_checker.simple_intersection (module)</a> +</li> + <li><a href=".doc/model_checker.simple_intersection.html#module-model_checker.simple_intersection.AP_dict">model_checker.simple_intersection.AP_dict (module)</a> +</li> + <li><a href=".doc/model_checker.simple_intersection.html#module-model_checker.simple_intersection.classes">model_checker.simple_intersection.classes (module)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="N">N</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.N">N (backends.mcts_learner.MCTSLearner attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.n_other_vehs">n_other_vehs (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.NextCh">NextCh() (model_checker.scanner.Scanner method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.NextToken">NextToken() (model_checker.scanner.Scanner method)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.nodes">nodes (backends.mcts_learner.MCTSLearner attribute)</a> + + <ul> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.nodes">(options.options_loader.OptionsGraph attribute)</a> +</li> + </ul></li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.normalize_cost">normalize_cost (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.normalize_tuple">normalize_tuple() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.noSym">noSym (model_checker.scanner.Scanner attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.NUM_HPIXELS">NUM_HPIXELS (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.NUM_HTILES">NUM_HTILES (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.NUM_VPIXELS">NUM_VPIXELS (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.NUM_VTILES">NUM_VTILES (in module env.simple_intersection.constants)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="O">O</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.observation_space">observation_space (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> + + <ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.observation_space">(options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + </ul></li> + <li><a href=".doc/mcts.html#mcts.online_mcts">online_mcts() (in module mcts)</a> +</li> + <li><a href=".doc/backends.html#backends.online_mcts_controller.OnlineMCTSController">OnlineMCTSController (class in backends.online_mcts_controller)</a> +</li> + <li><a href=".doc/options.html#module-options">options (module)</a> +</li> + <li><a href=".doc/options.html#module-options.options_loader">options.options_loader (module)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/options.simple_intersection.html#module-options.simple_intersection">options.simple_intersection (module)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#module-options.simple_intersection.maneuver_base">options.simple_intersection.maneuver_base (module)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#module-options.simple_intersection.maneuvers">options.simple_intersection.maneuvers (module)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#module-options.simple_intersection.mcts_maneuvers">options.simple_intersection.mcts_maneuvers (module)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph">OptionsGraph (class in options.options_loader)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.features.OtherVehFeatures">OtherVehFeatures (class in env.simple_intersection.features)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="P">P</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Parse">Parse() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser">Parser (class in model_checker.parser)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.LTL_property_base.LTLPropertyBase.parser">parser (model_checker.LTL_property_base.LTLPropertyBase attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer.Peek">Peek() (model_checker.scanner.Buffer method)</a> + + <ul> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.Peek">(model_checker.scanner.Scanner method)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.policy_base.PolicyBase">PolicyBase (class in backends.policy_base)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.road_geokinemetry.Route.pos_range">pos_range (env.simple_intersection.road_geokinemetry.Route attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Position">Position (class in model_checker.scanner)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/ppo2_training.html#module-ppo2_training">ppo2_training (module)</a> +</li> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent">PPO2Agent (class in backends.baselines_learner)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.predict">predict() (backends.kerasrl_learner.DDPGLearner method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.predict">(backends.kerasrl_learner.DQNLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.learner_base.LearnerBase.predict">(backends.learner_base.LearnerBase method)</a> +</li> + </ul></li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.printMsg">printMsg() (model_checker.parser.Errors static method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Property">Property() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.PyCheck">PyCheck() (model_checker.parser.Parser method)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="R">R</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.r_terminal">r_terminal (env.env_base.EpisodicEnvBase attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.Vehicle.random_reset">random_reset() (env.simple_intersection.vehicles.Vehicle method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer.Read">Read() (model_checker.scanner.Buffer method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer.ReadChars">ReadChars() (model_checker.scanner.Buffer method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer.readPosition">readPosition() (model_checker.scanner.Buffer method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.shapes.Rectangle">Rectangle (class in env.simple_intersection.shapes)</a> +</li> + <li><a href=".doc/env.html#env.env_base.GymCompliantEnvBase.render">render() (env.env_base.GymCompliantEnvBase method)</a> + + <ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.render">(env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.render">(options.options_loader.OptionsGraph method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.render">(options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + </ul></li> + <li><a href=".doc/env.html#env.env_base.GymCompliantEnvBase.reset">reset() (env.env_base.GymCompliantEnvBase method)</a> + + <ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.features.Features.reset">(env.simple_intersection.features.Features method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.reset">(env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.Vehicle.reset">(env.simple_intersection.vehicles.Vehicle method)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.reset">(options.options_loader.OptionsGraph method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.reset">(options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + </ul></li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.reset_maneuver">reset_maneuver() (options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.LTL_property_base.LTLPropertyBase.reset_property">reset_property() (model_checker.LTL_property_base.LTLPropertyBase method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.ResetPeek">ResetPeek() (model_checker.scanner.Scanner method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.ResetProperty">ResetProperty() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/backends.html#backends.rl_controller.RLController">RLController (class in backends.rl_controller)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.utilities.road2image">road2image() (in module env.simple_intersection.utilities)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.ROAD_TILE_IMAGE_DIM">ROAD_TILE_IMAGE_DIM (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.html#env.road_env.RoadEnv">RoadEnv (class in env.road_env)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.road_networks.RoadNetworkCross">RoadNetworkCross (class in env.simple_intersection.road_networks)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.road_geokinemetry.Route">Route (class in env.simple_intersection.road_geokinemetry)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="S">S</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.save_model">save_model() (backends.kerasrl_learner.DDPGLearner method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.save_model">(backends.kerasrl_learner.DQNLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.learner_base.LearnerBase.save_model">(backends.learner_base.LearnerBase method)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.save_model">(backends.mcts_learner.MCTSLearner method)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent.save_weights">save_weights() (backends.baselines_learner.PPO2Agent method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.Scan">Scan() (model_checker.scanner.Scanner method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner">Scanner (class in model_checker.scanner)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.SemErr">SemErr() (model_checker.parser.Errors static method)</a> + + <ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.SemErr">(model_checker.parser.Parser method)</a> +</li> + </ul></li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.set">set (model_checker.parser.Parser attribute)</a> +</li> + <li><a href=".doc/backends.html#backends.controller_base.ControllerBase.set_controller_args">set_controller_args() (backends.controller_base.ControllerBase method)</a> + + <ul> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.set_controller_args">(options.options_loader.OptionsGraph method)</a> +</li> + </ul></li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.set_controller_policy">set_controller_policy() (options.options_loader.OptionsGraph method)</a> +</li> + <li><a href=".doc/backends.html#backends.controller_base.ControllerBase.set_current_node">set_current_node() (backends.controller_base.ControllerBase method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.set_current_node">(backends.mcts_learner.MCTSLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.online_mcts_controller.OnlineMCTSController.set_current_node">(backends.online_mcts_controller.OnlineMCTSController method)</a> +</li> + <li><a href=".doc/backends.html#backends.rl_controller.RLController.set_current_node">(backends.rl_controller.RLController method)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.set_current_node">(options.options_loader.OptionsGraph method)</a> +</li> + </ul></li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.set_ego_info_text">set_ego_info_text() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent.set_environment">set_environment() (backends.baselines_learner.PPO2Agent method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.set_low_level_trained_policy">set_low_level_trained_policy() (options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/backends.html#backends.rl_controller.RLController.set_trained_policy">set_trained_policy() (backends.rl_controller.RLController method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Buffer.setPos">setPos() (model_checker.scanner.Buffer method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.SetProperty">SetProperty() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.shapes.Shape">Shape (class in env.simple_intersection.shapes)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv">SimpleIntersectionEnv (class in env.simple_intersection.simple_intersection_env)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Scanner.start">start (model_checker.scanner.Scanner attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.StartOf">StartOf() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.step">step() (env.env_base.EpisodicEnvBase method)</a> + + <ul> + <li><a href=".doc/env.html#env.env_base.GymCompliantEnvBase.step">(env.env_base.GymCompliantEnvBase method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.step">(env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.Vehicle.step">(env.simple_intersection.vehicles.Vehicle method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.VehicleState.step">(env.simple_intersection.vehicles.VehicleState method)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.step">(options.options_loader.OptionsGraph method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.step">(options.simple_intersection.maneuver_base.ManeuverBase method)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.controller_base.ControllerBase.step_current_node">step_current_node() (backends.controller_base.ControllerBase method)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.Stop">Stop (class in options.simple_intersection.maneuvers)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.storeError">storeError() (model_checker.parser.Errors static method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Successful">Successful() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.Summarize">Summarize() (model_checker.parser.Errors static method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.SynErr">SynErr() (model_checker.parser.Errors static method)</a> + + <ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.SynErr">(model_checker.parser.Parser method)</a> +</li> + </ul></li> + </ul></td> +</tr></table> + +<h2 id="T">T</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.T">T (model_checker.parser.Parser attribute)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.terminal_reward_type">terminal_reward_type (env.env_base.EpisodicEnvBase attribute)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.termination_condition">termination_condition (env.env_base.EpisodicEnvBase attribute)</a> + + <ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.termination_condition">(env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.termination_condition">(options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + </ul></li> + <li><a href=".doc/backends.html#backends.baselines_learner.PPO2Agent.test_model">test_model() (backends.baselines_learner.PPO2Agent method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.test_model">(backends.kerasrl_learner.DDPGLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.test_model">(backends.kerasrl_learner.DQNLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.learner_base.LearnerBase.test_model">(backends.learner_base.LearnerBase method)</a> +</li> + </ul></li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.shapes.Text">Text (class in env.simple_intersection.shapes)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.timeout">timeout (options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.timeout_happened">timeout_happened (options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.scanner.Token">Token (class in model_checker.scanner)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.TR">TR (backends.mcts_learner.MCTSLearner attribute)</a> +</li> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DDPGLearner.train">train() (backends.kerasrl_learner.DDPGLearner method)</a> + + <ul> + <li><a href=".doc/backends.html#backends.kerasrl_learner.DQNLearner.train">(backends.kerasrl_learner.DQNLearner method)</a> +</li> + <li><a href=".doc/backends.html#backends.learner_base.LearnerBase.train">(backends.learner_base.LearnerBase method)</a> +</li> + </ul></li> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuver_base.ManeuverBase.trained_policy">trained_policy (options.simple_intersection.maneuver_base.ManeuverBase attribute)</a> +</li> + <li><a href=".doc/backends.html#backends.mcts_learner.MCTSLearner.traverse">traverse() (backends.mcts_learner.MCTSLearner method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.TRUE">TRUE (model_checker.parser.Parser attribute)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="U">U</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.UNDECIDED">UNDECIDED (model_checker.parser.Parser attribute)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.UNDEFINED">UNDEFINED (model_checker.parser.Parser attribute)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.update_APs">update_APs() (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.Vehicle.update_local_APs">update_local_APs() (env.simple_intersection.vehicles.Vehicle method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.Vehicle.update_waited_count">update_waited_count() (env.simple_intersection.vehicles.Vehicle method)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="V">V</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.V2V_ref">V2V_ref (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.V_CAR_SCALE">V_CAR_SCALE() (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.V_SPACE_SCALE">V_SPACE_SCALE (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.V_TILE_SCALE">V_TILE_SCALE() (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.veh_ahead_max">veh_ahead_max (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.veh_ahead_min">veh_ahead_min (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.Vehicle">Vehicle (class in env.simple_intersection.vehicles)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.vehicle_network">vehicle_network (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.constants.VEHICLE_WHEEL_BASE">VEHICLE_WHEEL_BASE (in module env.simple_intersection.constants)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicle_networks.VehicleNetworkCross">VehicleNetworkCross (class in env.simple_intersection.vehicle_networks)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.vehicles.VehicleState">VehicleState (class in env.simple_intersection.vehicles)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.vehs">vehs (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/env.html#env.env_base.EpisodicEnvBase.violation_happened">violation_happened (env.env_base.EpisodicEnvBase attribute)</a> +</li> + <li><a href=".doc/options.html#options.options_loader.OptionsGraph.visualize_low_level_steps">visualize_low_level_steps (options.options_loader.OptionsGraph attribute)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="W">W</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/options.simple_intersection.html#options.simple_intersection.maneuvers.Wait">Wait (class in options.simple_intersection.maneuvers)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Errors.Warn">Warn() (model_checker.parser.Errors static method)</a> +</li> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.Warning">Warning() (model_checker.parser.Parser method)</a> +</li> + </ul></td> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.WeakSeparator">WeakSeparator() (model_checker.parser.Parser method)</a> +</li> + <li><a href=".doc/env.simple_intersection.html#env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv.window">window (env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv attribute)</a> +</li> + <li><a href=".doc/mcts.html#mcts.Logger.write">write() (mcts.Logger method)</a> +</li> + </ul></td> +</tr></table> + +<h2 id="X">X</h2> +<table style="width: 100%" class="indextable genindextable"><tr> + <td style="width: 33%; vertical-align: top;"><ul> + <li><a href=".doc/model_checker.html#model_checker.parser.Parser.x">x (model_checker.parser.Parser attribute)</a> +</li> + </ul></td> +</tr></table> + + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/index.html b/documentation/sphinx/.build/index.html new file mode 100644 index 0000000000000000000000000000000000000000..44a98b61f7a9879ddae37ad0dd5407f230a1a7fb --- /dev/null +++ b/documentation/sphinx/.build/index.html @@ -0,0 +1,88 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Contents — WiseMove documentation</title> + <link rel="stylesheet" href="_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="genindex.html" /> + <link rel="search" title="Search" href="search.html" /> + <link rel="next" title="Quick Start" href="usage/quickstart.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="#"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>Contents</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="#">Contents</a> +   ::   + <a href="usage/quickstart.html">Quick Start</a>  Â» + </p> + + </div> + <div class="content"> + + + <div class="section" id="contents"> +<h1>Contents<a class="headerlink" href="#contents" title="Permalink to this headline">¶</a></h1> +<div class="section" id="user-guide"> +<h2>User Guide<a class="headerlink" href="#user-guide" title="Permalink to this headline">¶</a></h2> +<div class="toctree-wrapper compound"> +<ul> +<li class="toctree-l1"><a class="reference internal" href="usage/quickstart.html">Quick Start</a><ul> +<li class="toctree-l2"><a class="reference internal" href="usage/quickstart.html#environment">Environment</a></li> +<li class="toctree-l2"><a class="reference internal" href="usage/quickstart.html#low-level-policies">Low-level Policies</a></li> +<li class="toctree-l2"><a class="reference internal" href="usage/quickstart.html#high-level-policy">High-level Policy</a></li> +<li class="toctree-l2"><a class="reference internal" href="usage/quickstart.html#model-checking">Model Checking</a></li> +<li class="toctree-l2"><a class="reference internal" href="usage/quickstart.html#monte-carlo-tree-search">Monte-Carlo Tree Search</a></li> +<li class="toctree-l2"><a class="reference internal" href="usage/quickstart.html#learning-backend">Learning Backend</a></li> +</ul> +</li> +</ul> +</div> +</div> +<div class="section" id="code-documentation"> +<h2>Code documentation<a class="headerlink" href="#code-documentation" title="Permalink to this headline">¶</a></h2> +<ul class="simple"> +<li><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></li> +<li><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></li> +</ul> +</div> +<div class="section" id="search"> +<h2>Search<a class="headerlink" href="#search" title="Permalink to this headline">¶</a></h2> +<ul class="simple"> +<li><a class="reference internal" href="search.html"><span class="std std-ref">Search Page</span></a></li> +</ul> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="#">Contents</a> +   ::   + <a href="usage/quickstart.html">Quick Start</a>  Â» + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/objects.inv b/documentation/sphinx/.build/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..46806fc1af587d76e16ad36dcbd84db4da68c39a Binary files /dev/null and b/documentation/sphinx/.build/objects.inv differ diff --git a/documentation/sphinx/.build/py-modindex.html b/documentation/sphinx/.build/py-modindex.html new file mode 100644 index 0000000000000000000000000000000000000000..5ae8eb173b271898c63720820e98d9f888734a69 --- /dev/null +++ b/documentation/sphinx/.build/py-modindex.html @@ -0,0 +1,299 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Python Module Index — WiseMove documentation</title> + <link rel="stylesheet" href="_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="genindex.html" /> + <link rel="search" title="Search" href="search.html" /> + + + + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>Python Module Index</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + + <h1>Python Module Index</h1> + + <div class="modindex-jumpbox"> + <a href="#cap-b"><strong>b</strong></a> | + <a href="#cap-e"><strong>e</strong></a> | + <a href="#cap-h"><strong>h</strong></a> | + <a href="#cap-l"><strong>l</strong></a> | + <a href="#cap-m"><strong>m</strong></a> | + <a href="#cap-o"><strong>o</strong></a> | + <a href="#cap-p"><strong>p</strong></a> + </div> + + <table class="indextable modindextable"> + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap" id="cap-b"><td></td><td> + <strong>b</strong></td><td></td></tr> + <tr> + <td><img src="_static/minus.png" class="toggler" + id="toggle-1" style="display: none" alt="-" /></td> + <td> + <a href=".doc/backends.html#module-backends"><code class="xref">backends</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.baselines_learner"><code class="xref">backends.baselines_learner</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.controller_base"><code class="xref">backends.controller_base</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.kerasrl_learner"><code class="xref">backends.kerasrl_learner</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.learner_base"><code class="xref">backends.learner_base</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.manual_policy"><code class="xref">backends.manual_policy</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.mcts_learner"><code class="xref">backends.mcts_learner</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.online_mcts_controller"><code class="xref">backends.online_mcts_controller</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.policy_base"><code class="xref">backends.policy_base</code></a></td><td> + <em></em></td></tr> + <tr class="cg-1"> + <td></td> + <td>    + <a href=".doc/backends.html#module-backends.rl_controller"><code class="xref">backends.rl_controller</code></a></td><td> + <em></em></td></tr> + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap" id="cap-e"><td></td><td> + <strong>e</strong></td><td></td></tr> + <tr> + <td><img src="_static/minus.png" class="toggler" + id="toggle-2" style="display: none" alt="-" /></td> + <td> + <a href=".doc/env.html#module-env"><code class="xref">env</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.html#module-env.env_base"><code class="xref">env.env_base</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.html#module-env.road_env"><code class="xref">env.road_env</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection"><code class="xref">env.simple_intersection</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.constants"><code class="xref">env.simple_intersection.constants</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.features"><code class="xref">env.simple_intersection.features</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.road_geokinemetry"><code class="xref">env.simple_intersection.road_geokinemetry</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.road_networks"><code class="xref">env.simple_intersection.road_networks</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.shapes"><code class="xref">env.simple_intersection.shapes</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.simple_intersection_env"><code class="xref">env.simple_intersection.simple_intersection_env</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.utilities"><code class="xref">env.simple_intersection.utilities</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.vehicle_networks"><code class="xref">env.simple_intersection.vehicle_networks</code></a></td><td> + <em></em></td></tr> + <tr class="cg-2"> + <td></td> + <td>    + <a href=".doc/env.simple_intersection.html#module-env.simple_intersection.vehicles"><code class="xref">env.simple_intersection.vehicles</code></a></td><td> + <em></em></td></tr> + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap" id="cap-h"><td></td><td> + <strong>h</strong></td><td></td></tr> + <tr> + <td></td> + <td> + <a href=".doc/high_level_policy_main.html#module-high_level_policy_main"><code class="xref">high_level_policy_main</code></a></td><td> + <em></em></td></tr> + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap" id="cap-l"><td></td><td> + <strong>l</strong></td><td></td></tr> + <tr> + <td></td> + <td> + <a href=".doc/low_level_policy_main.html#module-low_level_policy_main"><code class="xref">low_level_policy_main</code></a></td><td> + <em></em></td></tr> + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap" id="cap-m"><td></td><td> + <strong>m</strong></td><td></td></tr> + <tr> + <td></td> + <td> + <a href=".doc/mcts.html#module-mcts"><code class="xref">mcts</code></a></td><td> + <em></em></td></tr> + <tr> + <td><img src="_static/minus.png" class="toggler" + id="toggle-3" style="display: none" alt="-" /></td> + <td> + <a href=".doc/model_checker.html#module-model_checker"><code class="xref">model_checker</code></a></td><td> + <em></em></td></tr> + <tr class="cg-3"> + <td></td> + <td>    + <a href=".doc/model_checker.html#module-model_checker.atomic_propositions_base"><code class="xref">model_checker.atomic_propositions_base</code></a></td><td> + <em></em></td></tr> + <tr class="cg-3"> + <td></td> + <td>    + <a href=".doc/model_checker.html#module-model_checker.LTL_property_base"><code class="xref">model_checker.LTL_property_base</code></a></td><td> + <em></em></td></tr> + <tr class="cg-3"> + <td></td> + <td>    + <a href=".doc/model_checker.html#module-model_checker.parser"><code class="xref">model_checker.parser</code></a></td><td> + <em></em></td></tr> + <tr class="cg-3"> + <td></td> + <td>    + <a href=".doc/model_checker.html#module-model_checker.scanner"><code class="xref">model_checker.scanner</code></a></td><td> + <em></em></td></tr> + <tr class="cg-3"> + <td></td> + <td>    + <a href=".doc/model_checker.simple_intersection.html#module-model_checker.simple_intersection"><code class="xref">model_checker.simple_intersection</code></a></td><td> + <em></em></td></tr> + <tr class="cg-3"> + <td></td> + <td>    + <a href=".doc/model_checker.simple_intersection.html#module-model_checker.simple_intersection.AP_dict"><code class="xref">model_checker.simple_intersection.AP_dict</code></a></td><td> + <em></em></td></tr> + <tr class="cg-3"> + <td></td> + <td>    + <a href=".doc/model_checker.simple_intersection.html#module-model_checker.simple_intersection.classes"><code class="xref">model_checker.simple_intersection.classes</code></a></td><td> + <em></em></td></tr> + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap" id="cap-o"><td></td><td> + <strong>o</strong></td><td></td></tr> + <tr> + <td><img src="_static/minus.png" class="toggler" + id="toggle-4" style="display: none" alt="-" /></td> + <td> + <a href=".doc/options.html#module-options"><code class="xref">options</code></a></td><td> + <em></em></td></tr> + <tr class="cg-4"> + <td></td> + <td>    + <a href=".doc/options.html#module-options.options_loader"><code class="xref">options.options_loader</code></a></td><td> + <em></em></td></tr> + <tr class="cg-4"> + <td></td> + <td>    + <a href=".doc/options.simple_intersection.html#module-options.simple_intersection"><code class="xref">options.simple_intersection</code></a></td><td> + <em></em></td></tr> + <tr class="cg-4"> + <td></td> + <td>    + <a href=".doc/options.simple_intersection.html#module-options.simple_intersection.maneuver_base"><code class="xref">options.simple_intersection.maneuver_base</code></a></td><td> + <em></em></td></tr> + <tr class="cg-4"> + <td></td> + <td>    + <a href=".doc/options.simple_intersection.html#module-options.simple_intersection.maneuvers"><code class="xref">options.simple_intersection.maneuvers</code></a></td><td> + <em></em></td></tr> + <tr class="cg-4"> + <td></td> + <td>    + <a href=".doc/options.simple_intersection.html#module-options.simple_intersection.mcts_maneuvers"><code class="xref">options.simple_intersection.mcts_maneuvers</code></a></td><td> + <em></em></td></tr> + <tr class="pcap"><td></td><td> </td><td></td></tr> + <tr class="cap" id="cap-p"><td></td><td> + <strong>p</strong></td><td></td></tr> + <tr> + <td></td> + <td> + <a href=".doc/ppo2_training.html#module-ppo2_training"><code class="xref">ppo2_training</code></a></td><td> + <em></em></td></tr> + </table> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/search.html b/documentation/sphinx/.build/search.html new file mode 100644 index 0000000000000000000000000000000000000000..e6ded20ea9eed69ef545c8bf3fd29a375946f655 --- /dev/null +++ b/documentation/sphinx/.build/search.html @@ -0,0 +1,81 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Search — WiseMove documentation</title> + <link rel="stylesheet" href="_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> + <script type="text/javascript" src="_static/jquery.js"></script> + <script type="text/javascript" src="_static/underscore.js"></script> + <script type="text/javascript" src="_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <script type="text/javascript" src="_static/searchtools.js"></script> + <link rel="index" title="Index" href="genindex.html" /> + <link rel="search" title="Search" href="#" /> + <script type="text/javascript"> + jQuery(function() { Search.loadIndex("searchindex.js"); }); + </script> + + <script type="text/javascript" id="searchindexloader"></script> + + + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>Search</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <h1 id="search-documentation">Search</h1> + <div id="fallback" class="admonition warning"> + <script type="text/javascript">$('#fallback').hide();</script> + <p> + Please activate JavaScript to enable the search + functionality. + </p> + </div> + <p> + From here you can search these documents. Enter your search + words into the box below and click "search". Note that the search + function will automatically search for all of the words. Pages + containing fewer words won't appear in the result list. + </p> + <form action="" method="get"> + <input type="text" name="q" value="" /> + <input type="submit" value="search" /> + <span id="search-progress" style="padding-left: 10px"></span> + </form> + + <div id="search-results"> + + </div> + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/searchindex.js b/documentation/sphinx/.build/searchindex.js new file mode 100644 index 0000000000000000000000000000000000000000..4a96626ab5e44c1ec0e4e5f834f053d87c453bb1 --- /dev/null +++ b/documentation/sphinx/.build/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:[".doc/backends",".doc/env",".doc/env.simple_intersection",".doc/high_level_policy_main",".doc/low_level_policy_main",".doc/mcts",".doc/model_checker",".doc/model_checker.simple_intersection",".doc/modules",".doc/options",".doc/options.simple_intersection",".doc/ppo2_training","index","usage/config","usage/quickstart"],envversion:53,filenames:[".doc/backends.rst",".doc/env.rst",".doc/env.simple_intersection.rst",".doc/high_level_policy_main.rst",".doc/low_level_policy_main.rst",".doc/mcts.rst",".doc/model_checker.rst",".doc/model_checker.simple_intersection.rst",".doc/modules.rst",".doc/options.rst",".doc/options.simple_intersection.rst",".doc/ppo2_training.rst","index.rst","usage/config.rst","usage/quickstart.rst"],objects:{"":{backends:[0,0,0,"-"],env:[1,0,0,"-"],high_level_policy_main:[3,0,0,"-"],low_level_policy_main:[4,0,0,"-"],mcts:[5,0,0,"-"],model_checker:[6,0,0,"-"],options:[9,0,0,"-"],ppo2_training:[11,0,0,"-"]},"backends.baselines_learner":{PPO2Agent:[0,1,1,""]},"backends.baselines_learner.PPO2Agent":{create_agent:[0,2,1,""],fit:[0,2,1,""],forward:[0,2,1,""],get_default_policy:[0,2,1,""],load_weights:[0,2,1,""],save_weights:[0,2,1,""],set_environment:[0,2,1,""],test_model:[0,2,1,""]},"backends.controller_base":{ControllerBase:[0,1,1,""]},"backends.controller_base.ControllerBase":{can_transition:[0,2,1,""],do_transition:[0,2,1,""],low_level_step_current_node:[0,2,1,""],set_controller_args:[0,2,1,""],set_current_node:[0,2,1,""],step_current_node:[0,2,1,""]},"backends.kerasrl_learner":{DDPGLearner:[0,1,1,""],DQNAgentOverOptions:[0,1,1,""],DQNLearner:[0,1,1,""]},"backends.kerasrl_learner.DDPGLearner":{create_agent:[0,2,1,""],get_default_actor_model:[0,2,1,""],get_default_critic_model:[0,2,1,""],get_default_memory:[0,2,1,""],get_default_randomprocess:[0,2,1,""],load_model:[0,2,1,""],predict:[0,2,1,""],save_model:[0,2,1,""],test_model:[0,2,1,""],train:[0,2,1,""]},"backends.kerasrl_learner.DQNAgentOverOptions":{forward:[0,2,1,""],get_modified_q_values:[0,2,1,""]},"backends.kerasrl_learner.DQNLearner":{create_agent:[0,2,1,""],get_default_memory:[0,2,1,""],get_default_model:[0,2,1,""],get_default_policy:[0,2,1,""],get_q_value:[0,2,1,""],get_q_value_using_option_alias:[0,2,1,""],get_softq_value_using_option_alias:[0,2,1,""],load_model:[0,2,1,""],predict:[0,2,1,""],save_model:[0,2,1,""],test_model:[0,2,1,""],train:[0,2,1,""]},"backends.learner_base":{LearnerBase:[0,1,1,""]},"backends.learner_base.LearnerBase":{load_model:[0,2,1,""],predict:[0,2,1,""],save_model:[0,2,1,""],test_model:[0,2,1,""],train:[0,2,1,""]},"backends.manual_policy":{ManualPolicy:[0,1,1,""]},"backends.manual_policy.ManualPolicy":{can_transition:[0,2,1,""],do_transition:[0,2,1,""]},"backends.mcts_learner":{MCTSLearner:[0,1,1,""]},"backends.mcts_learner.MCTSLearner":{M:[0,3,1,""],N:[0,3,1,""],TR:[0,3,1,""],adj:[0,3,1,""],curr_node_alias:[0,3,1,""],curr_node_num:[0,3,1,""],do_transition:[0,2,1,""],get_best_node:[0,2,1,""],load_model:[0,2,1,""],nodes:[0,3,1,""],save_model:[0,2,1,""],set_current_node:[0,2,1,""],traverse:[0,2,1,""]},"backends.online_mcts_controller":{OnlineMCTSController:[0,1,1,""]},"backends.online_mcts_controller.OnlineMCTSController":{can_transition:[0,2,1,""],change_low_level_references:[0,2,1,""],do_transition:[0,2,1,""],set_current_node:[0,2,1,""]},"backends.policy_base":{PolicyBase:[0,1,1,""]},"backends.rl_controller":{RLController:[0,1,1,""]},"backends.rl_controller.RLController":{can_transition:[0,2,1,""],do_transition:[0,2,1,""],set_current_node:[0,2,1,""],set_trained_policy:[0,2,1,""]},"env.env_base":{EpisodicEnvBase:[1,1,1,""],GymCompliantEnvBase:[1,1,1,""]},"env.env_base.EpisodicEnvBase":{current_model_checking_result:[1,2,1,""],disable_LTL_preconditions:[1,2,1,""],enable_LTL_preconditions:[1,2,1,""],goal_achieved:[1,3,1,""],r_terminal:[1,3,1,""],step:[1,2,1,""],terminal_reward_type:[1,3,1,""],termination_condition:[1,3,1,""],violation_happened:[1,3,1,""]},"env.env_base.GymCompliantEnvBase":{render:[1,2,1,""],reset:[1,2,1,""],step:[1,2,1,""]},"env.road_env":{RoadEnv:[1,1,1,""]},"env.simple_intersection":{constants:[2,0,0,"-"],features:[2,0,0,"-"],road_geokinemetry:[2,0,0,"-"],road_networks:[2,0,0,"-"],shapes:[2,0,0,"-"],simple_intersection_env:[2,0,0,"-"],utilities:[2,0,0,"-"],vehicle_networks:[2,0,0,"-"],vehicles:[2,0,0,"-"]},"env.simple_intersection.constants":{DT:[2,4,1,""],DT_over_2:[2,4,1,""],EGO_INDEX:[2,4,1,""],H_CAR_SCALE:[2,5,1,""],H_SPACE_SCALE:[2,4,1,""],H_TILE_SCALE:[2,5,1,""],LANE_SEPARATOR_HALF_WIDTH:[2,4,1,""],LANE_WIDTH:[2,4,1,""],MAX_ACCELERATION:[2,4,1,""],MAX_NUM_VEHICLES:[2,4,1,""],MAX_STEERING_ANGLE:[2,4,1,""],MAX_STEERING_ANGLE_RATE:[2,4,1,""],NUM_HPIXELS:[2,4,1,""],NUM_HTILES:[2,4,1,""],NUM_VPIXELS:[2,4,1,""],NUM_VTILES:[2,4,1,""],ROAD_TILE_IMAGE_DIM:[2,4,1,""],VEHICLE_WHEEL_BASE:[2,4,1,""],V_CAR_SCALE:[2,5,1,""],V_SPACE_SCALE:[2,4,1,""],V_TILE_SCALE:[2,5,1,""]},"env.simple_intersection.features":{Features:[2,1,1,""],OtherVehFeatures:[2,1,1,""],extract_ego_features:[2,5,1,""],extract_other_veh_features:[2,5,1,""]},"env.simple_intersection.features.Features":{get_features_tuple:[2,2,1,""],reset:[2,2,1,""]},"env.simple_intersection.road_geokinemetry":{Route:[2,1,1,""]},"env.simple_intersection.road_geokinemetry.Route":{pos_range:[2,3,1,""]},"env.simple_intersection.road_networks":{RoadNetworkCross:[2,1,1,""]},"env.simple_intersection.road_networks.RoadNetworkCross":{draw:[2,2,1,""]},"env.simple_intersection.shapes":{Image:[2,1,1,""],Rectangle:[2,1,1,""],Shape:[2,1,1,""],Text:[2,1,1,""]},"env.simple_intersection.shapes.Image":{draw:[2,2,1,""]},"env.simple_intersection.shapes.Rectangle":{draw:[2,2,1,""]},"env.simple_intersection.shapes.Text":{draw:[2,2,1,""]},"env.simple_intersection.simple_intersection_env":{SimpleIntersectionEnv:[2,1,1,""]},"env.simple_intersection.simple_intersection_env.SimpleIntersectionEnv":{V2V_ref:[2,3,1,""],action_space:[2,3,1,""],aggressive_driving_policy:[2,2,1,""],check_ego_collision:[2,2,1,""],check_other_veh_collisions:[2,2,1,""],collision_happened:[2,3,1,""],copy:[2,2,1,""],cost:[2,2,1,""],cost_normalization_ranges:[2,3,1,""],cost_weights:[2,3,1,""],draw:[2,2,1,""],ego:[2,3,1,""],ego_info_text:[2,3,1,""],generate_scenario:[2,2,1,""],get_V2V_distance:[2,2,1,""],get_features_tuple:[2,2,1,""],goal_achieved:[2,3,1,""],init_APs:[2,2,1,""],is_ego_off_road:[2,2,1,""],is_terminal:[2,2,1,""],max_ego_theta:[2,3,1,""],n_other_vehs:[2,3,1,""],normalize_cost:[2,3,1,""],normalize_tuple:[2,2,1,""],observation_space:[2,3,1,""],render:[2,2,1,""],reset:[2,2,1,""],set_ego_info_text:[2,2,1,""],step:[2,2,1,""],termination_condition:[2,3,1,""],update_APs:[2,2,1,""],veh_ahead_max:[2,3,1,""],veh_ahead_min:[2,3,1,""],vehicle_network:[2,3,1,""],vehs:[2,3,1,""],window:[2,3,1,""]},"env.simple_intersection.utilities":{BoundingBox:[2,1,1,""],calculate_s:[2,5,1,""],calculate_v_max:[2,5,1,""],config_Pyglet:[2,5,1,""],draw_all_shapes:[2,5,1,""],get_APs:[2,5,1,""],get_veh_attributes:[2,5,1,""],road2image:[2,5,1,""]},"env.simple_intersection.utilities.BoundingBox":{all_same_sign_in_list:[2,6,1,""],does_bounding_box_cross_line:[2,6,1,""],does_bounding_box_intersect:[2,6,1,""],localize_bounding_box_wrt_line:[2,6,1,""],localize_point_wrt_line:[2,6,1,""]},"env.simple_intersection.vehicle_networks":{VehicleNetworkCross:[2,1,1,""]},"env.simple_intersection.vehicle_networks.VehicleNetworkCross":{draw:[2,2,1,""]},"env.simple_intersection.vehicles":{Vehicle:[2,1,1,""],VehicleState:[2,1,1,""]},"env.simple_intersection.vehicles.Vehicle":{init_local_discrete_var:[2,2,1,""],is_within_road_boundaries:[2,2,1,""],random_reset:[2,2,1,""],reset:[2,2,1,""],step:[2,2,1,""],update_local_APs:[2,2,1,""],update_waited_count:[2,2,1,""]},"env.simple_intersection.vehicles.VehicleState":{get_bounding_box:[2,2,1,""],step:[2,2,1,""]},"mcts.Logger":{flush:[5,2,1,""],write:[5,2,1,""]},"model_checker.LTL_property_base":{LTLPropertyBase:[6,1,1,""]},"model_checker.LTL_property_base.LTLPropertyBase":{APdict:[6,3,1,""],check:[6,2,1,""],check_incremental:[6,2,1,""],parser:[6,3,1,""],reset_property:[6,2,1,""]},"model_checker.atomic_propositions_base":{AtomicPropositionsBase:[6,1,1,""],Bits:[6,1,1,""]},"model_checker.atomic_propositions_base.AtomicPropositionsBase":{APdict:[6,3,1,""]},"model_checker.parser":{ErrorRec:[6,1,1,""],Errors:[6,1,1,""],Parser:[6,1,1,""]},"model_checker.parser.Errors":{Exception:[6,6,1,""],Init:[6,6,1,""],SemErr:[6,6,1,""],Summarize:[6,6,1,""],SynErr:[6,6,1,""],Warn:[6,6,1,""],count:[6,3,1,""],display:[6,6,1,""],eof:[6,3,1,""],errDist:[6,3,1,""],errMsgFormat:[6,3,1,""],errors:[6,3,1,""],fileName:[6,3,1,""],listName:[6,3,1,""],mergeErrors:[6,3,1,""],mergedList:[6,3,1,""],minErrDist:[6,3,1,""],printMsg:[6,6,1,""],storeError:[6,6,1,""]},"model_checker.parser.Parser":{Check:[6,2,1,""],CheckIncremental:[6,2,1,""],Check_old:[6,2,1,""],Conjunction:[6,2,1,""],Disjunction:[6,2,1,""],Expect:[6,2,1,""],ExpectWeak:[6,2,1,""],FALSE:[6,3,1,""],Factor:[6,2,1,""],Get:[6,2,1,""],Implication:[6,2,1,""],LexString:[6,2,1,""],LookAheadString:[6,2,1,""],Parse:[6,2,1,""],Property:[6,2,1,""],PyCheck:[6,2,1,""],ResetProperty:[6,2,1,""],SemErr:[6,2,1,""],SetProperty:[6,2,1,""],StartOf:[6,2,1,""],Successful:[6,2,1,""],SynErr:[6,2,1,""],T:[6,3,1,""],TRUE:[6,3,1,""],UNDECIDED:[6,3,1,""],UNDEFINED:[6,3,1,""],Warning:[6,2,1,""],WeakSeparator:[6,2,1,""],errorMessages:[6,3,1,""],getParsingPos:[6,2,1,""],maxT:[6,3,1,""],minErrDist:[6,3,1,""],set:[6,3,1,""],x:[6,3,1,""]},"model_checker.scanner":{Buffer:[6,1,1,""],Position:[6,1,1,""],Scanner:[6,1,1,""],Token:[6,1,1,""]},"model_checker.scanner.Buffer":{EOF:[6,3,1,""],Peek:[6,2,1,""],Read:[6,2,1,""],ReadChars:[6,2,1,""],getPos:[6,2,1,""],getString:[6,2,1,""],readPosition:[6,2,1,""],setPos:[6,2,1,""]},"model_checker.scanner.Position":{getSubstring:[6,2,1,""]},"model_checker.scanner.Scanner":{CheckLiteral:[6,2,1,""],Comment0:[6,2,1,""],EOL:[6,3,1,""],NextCh:[6,2,1,""],NextToken:[6,2,1,""],Peek:[6,2,1,""],ResetPeek:[6,2,1,""],Scan:[6,2,1,""],charSetSize:[6,3,1,""],eofSym:[6,3,1,""],maxT:[6,3,1,""],noSym:[6,3,1,""],start:[6,3,1,""]},"model_checker.simple_intersection":{AP_dict:[7,0,0,"-"],classes:[7,0,0,"-"]},"model_checker.simple_intersection.classes":{AtomicPropositions:[7,1,1,""],LTLProperty:[7,1,1,""]},"model_checker.simple_intersection.classes.AtomicPropositions":{APdict:[7,3,1,""]},"model_checker.simple_intersection.classes.LTLProperty":{APdict:[7,3,1,""]},"options.options_loader":{OptionsGraph:[9,1,1,""]},"options.options_loader.OptionsGraph":{adj:[9,3,1,""],current_node:[9,3,1,""],edges:[9,3,1,""],execute_controller_policy:[9,2,1,""],get_number_of_nodes:[9,2,1,""],load_trained_low_level_policies:[9,2,1,""],nodes:[9,3,1,""],render:[9,2,1,""],reset:[9,2,1,""],set_controller_args:[9,2,1,""],set_controller_policy:[9,2,1,""],set_current_node:[9,2,1,""],step:[9,2,1,""],visualize_low_level_steps:[9,3,1,""]},"options.simple_intersection":{maneuver_base:[10,0,0,"-"],maneuvers:[10,0,0,"-"],mcts_maneuvers:[10,0,0,"-"]},"options.simple_intersection.maneuver_base":{ManeuverBase:[10,1,1,""]},"options.simple_intersection.maneuver_base.ManeuverBase":{action_space:[10,3,1,""],extra_initiation_condition:[10,3,1,""],extra_termination_condition:[10,3,1,""],generate_learning_scenario:[10,2,1,""],generate_scenario:[10,2,1,""],generate_validation_scenario:[10,2,1,""],get_reduced_feature_length:[10,2,1,""],get_reduced_features_tuple:[10,2,1,""],goal_achieved:[10,3,1,""],high_level_extra_reward:[10,3,1,""],initiation_condition:[10,3,1,""],learning_mode:[10,3,1,""],low_level_policy:[10,2,1,""],observation_space:[10,3,1,""],render:[10,2,1,""],reset:[10,2,1,""],reset_maneuver:[10,2,1,""],set_low_level_trained_policy:[10,2,1,""],step:[10,2,1,""],termination_condition:[10,3,1,""],timeout:[10,3,1,""],timeout_happened:[10,3,1,""],trained_policy:[10,3,1,""]},"options.simple_intersection.maneuvers":{ChangeLane:[10,1,1,""],Follow:[10,1,1,""],KeepLane:[10,1,1,""],Stop:[10,1,1,""],Wait:[10,1,1,""]},"options.simple_intersection.maneuvers.ChangeLane":{generate_learning_scenario:[10,2,1,""],goal_achieved:[10,3,1,""],high_level_extra_reward:[10,3,1,""],min_y_distance:[10,3,1,""]},"options.simple_intersection.maneuvers.Follow":{generate_learning_scenario:[10,2,1,""]},"options.simple_intersection.maneuvers.KeepLane":{generate_learning_scenario:[10,2,1,""]},"options.simple_intersection.maneuvers.Stop":{generate_learning_scenario:[10,2,1,""]},"options.simple_intersection.maneuvers.Wait":{generate_learning_scenario:[10,2,1,""]},"options.simple_intersection.mcts_maneuvers":{MCTSChangeLane:[10,1,1,""],MCTSFollow:[10,1,1,""],MCTSKeepLane:[10,1,1,""],MCTSStop:[10,1,1,""],MCTSWait:[10,1,1,""]},"options.simple_intersection.mcts_maneuvers.MCTSChangeLane":{extra_initiation_condition:[10,3,1,""],extra_termination_condition:[10,3,1,""],generate_learning_scenario:[10,2,1,""],goal_achieved:[10,3,1,""],max_goal_distance:[10,3,1,""],min_y_distance:[10,3,1,""]},"options.simple_intersection.mcts_maneuvers.MCTSFollow":{extra_initiation_condition:[10,3,1,""],extra_termination_condition:[10,3,1,""],generate_learning_scenario:[10,2,1,""],generate_validation_scenario:[10,2,1,""]},"options.simple_intersection.mcts_maneuvers.MCTSKeepLane":{extra_initiation_condition:[10,3,1,""],generate_learning_scenario:[10,2,1,""],generate_validation_scenario:[10,2,1,""]},"options.simple_intersection.mcts_maneuvers.MCTSStop":{extra_initiation_condition:[10,3,1,""],generate_learning_scenario:[10,2,1,""],goal_achieved:[10,3,1,""]},"options.simple_intersection.mcts_maneuvers.MCTSWait":{extra_initiation_condition:[10,3,1,""],extra_termination_condition:[10,3,1,""],generate_learning_scenario:[10,2,1,""],goal_achieved:[10,3,1,""]},backends:{baselines_learner:[0,0,0,"-"],controller_base:[0,0,0,"-"],kerasrl_learner:[0,0,0,"-"],learner_base:[0,0,0,"-"],manual_policy:[0,0,0,"-"],mcts_learner:[0,0,0,"-"],online_mcts_controller:[0,0,0,"-"],policy_base:[0,0,0,"-"],rl_controller:[0,0,0,"-"]},env:{env_base:[1,0,0,"-"],road_env:[1,0,0,"-"],simple_intersection:[2,0,0,"-"]},high_level_policy_main:{evaluate_high_level_policy:[3,5,1,""],find_good_high_level_policy:[3,5,1,""],high_level_policy_testing:[3,5,1,""],high_level_policy_training:[3,5,1,""]},low_level_policy_main:{low_level_policy_testing:[4,5,1,""],low_level_policy_training:[4,5,1,""]},mcts:{Logger:[5,1,1,""],evaluate_online_mcts:[5,5,1,""],mcts_evaluation:[5,5,1,""],mcts_training:[5,5,1,""],mcts_visualize:[5,5,1,""],online_mcts:[5,5,1,""]},model_checker:{LTL_property_base:[6,0,0,"-"],atomic_propositions_base:[6,0,0,"-"],parser:[6,0,0,"-"],scanner:[6,0,0,"-"],simple_intersection:[7,0,0,"-"]},options:{options_loader:[9,0,0,"-"],simple_intersection:[10,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","attribute","Python attribute"],"4":["py","data","Python data"],"5":["py","function","Python function"],"6":["py","staticmethod","Python static method"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:attribute","4":"py:data","5":"py:function","6":"py:staticmethod"},terms:{"4th":2,"\u0101":6,"abstract":[0,2,10],"boolean":0,"case":2,"class":[0,1,2,5,6,8,9,10,14],"default":[0,1,2,4,9,10,14],"final":[0,14],"function":[1,2,9,10,14],"int":9,"new":[2,6],"return":[0,1,2,6,9,10],"static":[2,6],"true":[0,2,3,4,6,7,10,14],"while":14,APs:[2,7],And:2,For:[2,14],NNs:[3,4],The:[0,1,2,6,9,10,14],Then:2,These:14,Use:[10,14],Used:9,Uses:[2,14],_features_dim_reduct:10,_init_ltl_precondit:14,_ltl_precondit:14,_step:2,_text:2,abov:2,absolut:2,acc:2,acceler:[2,14],accord:[2,14],achiev:[1,2,10,14],action:[0,1,2,10],action_spac:[2,10],actor:0,add:[2,14],addit:[6,7],adj:[0,9],adjac:[0,2,9],after:[0,2,6,9,10,14],agent:[0,14],aggress:2,aggressive_driving_polici:2,ahead:[2,14],alia:[0,9],alias:9,all:[2,10,14],all_same_sign_in_list:2,allow:6,allow_vehicles_in_ego_lan:2,along:[2,14],alreadi:14,also:[1,2,9,14],alwai:[1,2,10,14],anchor:2,angl:[2,14],ani:[1,2,14],anoth:2,ap_dict:[6,8,14],ap_dict_len:7,apart:2,apdict:[6,7],apdict_len:6,append:14,appli:[6,10,14],approach:0,arg:[0,2,9],argument:[0,2,9,10,14],arrai:2,assum:[0,6,9,10],atom:[2,6],atomic_proposition_str:14,atomic_propositions_bas:[7,8],atomicproposit:[2,7],atomicpropositionsbas:[6,7],attribut:2,automat:2,autonom:14,avg:0,avoid:2,axi:2,backend:[8,12],background:2,base:[0,1,2,5,6,7,9,10],baselin:14,baselines_learn:[8,14],basic:2,becaus:14,been:14,befor:[2,14],before_but_close_to_stop_region:7,before_intersect:7,beg:6,behaviour:14,being:[0,2,14],below:[2,10],between:[2,9],beyond:14,bit:6,block:2,both:[2,7,14],bound:2,boundari:2,boundingbox:2,box:2,btw:2,buf:6,buffer:6,bumper:2,calcul:[2,10],calculate_:2,calculate_v_max:2,call:[2,6,10,14],can:[0,1,2,6,13,14],can_transit:0,cannot:0,car:2,carlo:[0,12],caus:[1,2],center:2,centr:2,certain:[2,14],chang:[2,14],change_low_level_refer:0,changelan:[10,14],charsets:6,check:[0,1,2,6,7,10,12],check_ego_collis:2,check_increment:6,check_old:6,check_other_veh_collis:2,checker:6,checkincrement:6,checkliter:6,checkpoint_interv:0,choos:14,chosen:[2,9],closest:2,code:2,col:6,collid:2,collis:[2,10,14],collision_happen:2,color:2,column:6,combin:14,come:14,comment0:6,comment:2,compar:2,comparison:2,complet:[0,2,9],compliant:[1,2,10],compon:[0,2],compos:14,comprehens:2,computation:14,concaten:0,condit:[1,2,9,10],config:[4,9,13,14],config_pyglet:2,configur:[2,9],conjunct:6,conserv:2,consist:[9,14],constant:[1,8],constrain:2,constraint:[2,14],construct:[6,14],constructor:2,cont:2,contain:[0,2,6,7],content:8,continu:2,control:[0,6,7,9,14],controller_bas:8,controllerbas:0,coordin:2,copi:2,correspond:[0,2,14],cost:2,cost_normalization_rang:2,cost_weight:2,could:2,count:[0,6,10],crash:14,creat:0,create_ag:0,critic:0,critic_action_input:0,cross:[2,14],curr_node_alia:0,curr_node_num:0,current:[0,1,2,9,14],current_model_checking_result:1,current_nod:9,custom:[9,14],data:2,ddpg:4,ddpgagent:0,ddpglearner:0,debug:2,decid:14,defin:[0,2,4,10,14],deg:2,depend:[0,2,9,14],deprec:6,describ:6,desir:2,detail:2,determinist:2,develop:2,dict:6,dictionari:[6,9],differ:2,dimens:2,dir:6,direct:2,disable_ltl_precondit:1,discret:[0,2],disjunct:6,displai:[2,6],dist:2,distanc:2,do_transit:0,doe:2,does_bounding_box_cross_lin:2,does_bounding_box_intersect:2,don:2,done:14,dot_phi:2,dot_psi:[2,10],dqn:0,dqnagent:0,dqnagentoveropt:0,dqnlearner:0,draw:2,draw_all_shap:2,drive:[2,10,14],dt_over_2:2,dtheta:2,dueling_typ:0,dummi:6,dure:[4,14],each:[0,2,10,14],easi:14,edg:[0,2,9],ego:[1,2,9,10],ego_heading_towards_lane_centr:2,ego_index:2,ego_info:2,ego_info_text:2,ego_lan:2,ego_perturb_lim:2,ego_pos_rang:2,ego_v_upper_lim:2,either:[2,4],element:2,enabl:[3,4,6,7,10],enable_double_dqn:0,enable_dueling_network:0,enable_ltl_precondit:[1,10],encapsul:[6,7],enclos:14,end:[2,6],end_po:2,enhanc:14,ensur:14,entir:6,entri:6,env:[0,8,9,10,14],env_arg:9,env_bas:[2,8,10],env_class:9,env_copi:0,env_kwarg:9,environ:[0,2,9,10,12],eof:6,eofsym:6,eol:6,episod:[0,1,2,3,4,9,10,14],episode_termination_flag:9,episodicenvbas:[1,2,10],equal:2,errdist:6,errmsg:6,errmsgformat:6,errnum:6,error:[2,6],errormessag:6,errorrec:6,errpo:6,etc:2,euler:2,evalu:14,evaluate_high_level_polici:3,evaluate_online_mct:5,even:14,eventu:14,everi:[0,2,5,14],exactli:2,exampl:[6,7,14],except:[2,6],exclud:2,execut:[0,2,9,14],execute_controller_polici:9,exhaust:2,exist:[0,2,6],exit:14,expect:6,expectweak:6,expens:14,experiment:13,explain:0,express:7,extra_initiation_condit:10,extra_termination_condit:10,extract_ego_featur:2,extract_other_veh_featur:2,extrem:2,factor:[2,6],fals:[0,1,2,3,4,5,6,7,9,10,14],fast:13,favour:14,featur:[1,8,9,10],features_tupl:2,few:14,file:[0,2,6,9],file_nam:[0,5],filenam:[0,6,14],find:2,find_good_high_level_polici:3,finish:2,first:[2,14],first_bb:2,fit:0,flag:9,flush:5,folder:14,follow:[2,6,9,10,14],font_siz:2,form:14,forward:0,four:2,framework:14,from:[0,2,6,9,10,14],front:14,fulli:2,further:14,gener:[1,2,10],generate_learning_scenario:10,generate_scenario:[2,10],generate_validation_scenario:10,geometri:2,get:[2,6,10],get_ap:2,get_best_nod:0,get_bounding_box:2,get_default_actor_model:0,get_default_critic_model:0,get_default_memori:0,get_default_model:0,get_default_polici:0,get_default_randomprocess:0,get_features_tupl:2,get_modified_q_valu:0,get_number_of_nod:9,get_q_valu:0,get_q_value_using_option_alia:0,get_reduced_feature_length:10,get_reduced_features_tupl:10,get_softq_value_using_option_alia:0,get_v2v_dist:2,get_veh_attribut:2,getparsingpo:6,getpo:6,getstr:6,getsubstr:6,give:[2,14],given:[0,2,4,5,6,14],gl_line:2,global:[2,14],goal:[1,2,10,14],goal_achiev:[1,2,10],goe:2,graph:9,graphic:[2,4],group:14,gym:[1,2,10],gymcompliantenvbas:1,h5f:[0,3,14],h_car_scal:2,h_space_scal:2,h_tile_scal:2,harder:14,has:[2,6,9,14],has_entered_stop_region:7,has_stopped_in_stop_region:[7,14],have:[1,2,14],head:2,height:2,help:14,hierarch:14,high:[2,3,9,12],high_level:13,high_level_extra_reward:10,high_level_policy_main:[8,14],high_level_policy_test:3,high_level_policy_train:[3,14],highest:14,highest_prior:[2,7],highlevel:14,highlevel_weight:[3,14],hlane:2,hold:2,holonom:2,horizont:2,human:[9,10,14],imag:2,image_typ:2,image_url:2,implement:[0,1,2,10],implic:[6,14],in_intersect:7,in_stop_region:[7,14],includ:[2,6],incorpor:14,increas:[2,10],increment:6,index:[2,6,7,9,12],indic:2,inevit:[2,14],inf:10,infer:0,infin:10,info:[2,9,10],inform:[2,6,7],infti:2,inherit:[0,2,10],iniiti:6,init:6,init_ap:2,init_local_discrete_var:2,init_properti:6,initi:[2,3,4,9,10],initialis:6,initialzi:2,initiation_condit:10,input:[0,2,14],input_shap:0,instanc:[0,2],integ:[6,7],intersect:[2,14],intersection_is_clear:[2,7],invalid:6,is_ego_off_road:2,is_termin:2,is_within_road_boundari:2,its:[2,6],json:[4,9,13,14],json_path:9,just:[2,14],keeplan:[10,14],kei:[9,14],kera:0,kerasrl:[0,14],kerasrl_learn:[8,14],kutta:2,kwarg:[0,2,9,10],label:2,lambda:2,lane:[2,7,14],lane_separator_half_width:2,lane_width:2,latest:0,lead:14,leaf:0,learn:[0,2,3,4,10,12],learner_bas:8,learnerbas:0,learning_mod:10,least:2,len:[2,6],length:[2,6,10],less:2,level:[0,2,3,4,5,9,10,12],lexstr:6,librari:14,lies:2,like:[2,9],limit:[2,14],line:[2,6],list:[0,2,6,9],listnam:6,liter:14,load:[0,3,4,14],load_model:0,load_trained_low_level_polici:9,load_weight:[0,3,4,14],local:2,localize_bounding_box_wrt_lin:2,localize_point_wrt_lin:2,locat:[2,14],log:[0,10],log_interv:0,log_path:0,logger:5,look:14,lookaheadstr:6,low:[0,2,4,5,9,10,12],low_level_manual_polici:10,low_level_polici:[0,10],low_level_policy_main:[8,14],low_level_policy_test:4,low_level_policy_train:4,low_level_step_current_nod:0,ltl:[6,7,10,14],ltl_property_bas:[7,8],ltl_str:[6,7],ltl_test:[6,8],ltlproperti:[7,14],ltlpropertybas:[6,7],machin:6,mai:[9,14],main:[6,10],make:2,manag:9,maneuv:[1,2,4,5,8,9,13,14],maneuver_bas:[8,9],maneuver_opt:2,maneuverbas:10,mani:5,manipul:[6,7],manual:[0,14],manual_polici:8,manualpolici:0,manuev:14,map:10,mark:14,max:[1,2],max_acceler:2,max_depth:0,max_ego_theta:2,max_goal_dist:10,max_nb_step:3,max_num_vehicl:2,max_po:2,max_steering_angl:2,max_steering_angle_r:2,maxim:2,maximum:[0,2],maxt:6,mct:[0,8,9,14],mcts_evalu:5,mcts_learner:8,mcts_maneuv:[8,9],mcts_train:5,mcts_visual:5,mctschangelan:10,mctsfollow:10,mctskeeplan:10,mctslearner:0,mctsstop:10,mctswait:10,mean:[2,14],memori:0,merg:6,mergedlist:6,mergeerror:6,messag:[5,14],met:9,method:[0,2,6,10],metric:0,middle_po:2,min_po:2,min_y_dist:10,minerrdist:6,minimum:2,mlppolici:0,mode:[9,10],model:[0,6,7,10,12],model_check:[8,14],model_checkpoint:0,modul:[8,12],mont:[0,12],more:2,msg:6,much:14,multilin:2,multipl:[2,14],multipli:2,must:[6,14],n_lane:2,n_other_veh:2,n_others_rang:2,n_others_stopped_in_stop_region:2,name:[2,4],nb_action:0,nb_episod:[0,5],nb_episodes_for_test:[3,4,14],nb_max_episode_step:0,nb_step:[0,3,4,14],nb_travers:5,nb_trial:[3,5,14],ndarrai:2,near_stop_region:2,nearest:2,necessari:[2,14],need:[2,6,9,14],neg:2,negat:14,nest:14,network:[0,2],neural:0,never:[1,10,14],new_node_alia:0,new_stat:2,next:[0,2,6,10,14],nextch:6,nexttoken:6,node:[0,9,14],node_alia:[0,9],non:2,none:[0,2,6,9,10],normal:2,normalize_cost:2,normalize_tupl:2,nosym:6,note:[2,14],num_hpixel:2,num_htil:2,num_trial:5,num_vpixel:2,num_vtil:2,number:[0,2,3,4,5,14],numbyt:6,o_star:0,obei:14,object:[0,1,2,5,6,9,14],observ:0,observation_spac:[2,10],obtain:2,off:2,offlin:14,on_rout:7,one:[2,9,14],ones:[2,14],onli:[0,2,10],onlin:[0,14],online_mct:5,online_mcts_control:8,onlinemctscontrol:0,opengl:2,oper:14,option:[0,2,8,14],option_alia:0,option_nam:14,options_load:8,optionsgraph:9,order:[2,14],orizont:10,ornsteinuhlenbeckprocess:0,other:[1,2,9,14],others_h_pos_rang:2,others_v_pos_rang:2,othervehfeatur:2,otherwis:[2,10],output:[0,4],over:[2,14],over_speed_limit:[7,14],overwrit:[0,14],packag:8,page:12,pair:9,paper:2,parallel:2,parallel_to_lan:7,param:[2,3,4,5,10],paramet:[0,2,6,9,10],parenthes:14,parenthet:14,pars:6,parser:8,part:[2,6,7,10],particular:9,pass:[0,2],path:14,paxton:0,peek:6,penalti:[6,7,14],per:[0,9],perfect:14,perform:[0,3,4,9],perturb:2,phi:14,pickl:0,pixel:2,place:9,plug:1,point:[2,6],polici:[0,2,3,4,5,9,10,12,13],policy_bas:8,policybas:0,pos:[2,6],pos_in_lan:2,pos_rang:2,pose:2,posit:[2,6],possibl:14,ppo2:[0,4],ppo2_train:8,ppo2ag:0,ppo:0,pre:[3,4,14],preced:14,precondit:10,predic:14,predict:0,present:0,pretrain:[3,4],previou:[2,6],previous:6,printmsg:6,privat:2,probabl:14,problem:1,process:0,progress:0,project:14,properti:[0,2,6,7,14],proposit:[2,6],propscann:6,provid:[2,14],psi:2,psi_dot:2,pycheck:6,pyglet:2,python:[2,14],quadrilater:2,quick:12,quotat:14,r_termin:1,random:[0,2],random_process:0,random_reset:2,randomize_special_scenario:2,randomli:2,rang:[2,7],rate:[2,14],rather:14,reach:[2,14],reachabl:2,read:6,readabl:14,readchar:6,readposit:6,reason:2,rectangl:2,reduced_features_tupl:10,refer:14,region:2,reinforc:[2,14],reiniti:[2,10],rel_i:2,rel_x:2,relat:2,relev:2,render:[0,1,2,5,9,10],repfol:6,repres:[2,9],requir:[2,7],reset:[0,1,2,6,9,10],reset_maneuv:10,reset_properti:6,resetpeek:6,resetproperti:6,restrict:2,restructur:2,result:[6,14],retriev:2,reward:[0,2,9,10],rk4:2,rl_control:8,rl_method:4,rlcontrol:0,road2imag:2,road:[1,2,7,14],road_env:[2,8],road_geokinemetri:[1,8],road_network:[1,8],road_tile_image_dim:2,roadenv:[1,2],roadnetworkcross:2,rollout:9,root:[0,9,14],rout:[2,10],rule:14,run:[0,14],rung:2,safe:14,same:[0,2,7],sampl:2,satisfi:[2,10],save:[0,5,14],save_everi:5,save_fil:14,save_model:0,save_path:3,save_weight:0,saved_policy_in_root:14,scale:2,scale_factor:2,scale_i:2,scale_x:2,scan:6,scanner:8,scenario:[2,7,10],search:0,second:2,second_bb:2,see:[2,4,6],select:13,self:[0,2,6,14],semerr:6,separ:2,seper:2,sequenc:6,sequentialmemori:0,set:[0,2,6,9,10,14],set_controller_arg:[0,9],set_controller_polici:9,set_current_nod:[0,9],set_ego_info_text:2,set_environ:0,set_low_level_trained_polici:10,set_trained_polici:0,setpo:6,setproperti:6,shape:[0,1,8],should:[0,7,14],show:[2,14],shown:[2,6,7],side:[2,14],sidewalk:2,sign:[2,14],signifi:0,similarli:2,simpl:14,simple_intersect:[1,6,8,9,14],simple_intersection_env:[1,8,14],simpleintersectionenv:2,singl:[0,14],singular:0,size:2,smaller:14,some:[2,14],sourcebuff:6,space:2,special:2,specif:[6,9,14],specifi:[0,1,2,9,10,14],speed:[2,14],squar:2,stabl:14,stable_baselin:0,stai:2,start:[2,6,9,12],start_node_alia:0,start_po:2,starting_nod:9,startof:6,state:[2,6,9,10,14],steer:[2,14],step:[0,1,2,3,4,6,9,10,14],step_current_nod:0,stop:[2,10,14],stop_region:[2,7],stop_region_centr:2,stopped_car_scenario:2,stopped_now:7,store:[0,2],storeerror:6,string:[2,14],structur:[9,14],subclass:[0,1,2,6,10],submodul:8,subpackag:8,success:6,success_reward_threshold:0,sum:2,summar:6,support:14,suppos:10,sure:2,syfol:6,synerr:6,syntact:14,system:2,take:[0,2,9,10,14],taken:0,target:2,target_lan:7,technic:10,tensorboard:[0,3,4,14],term:10,termin:[1,2,10],terminal_reward_typ:1,termination_condit:[1,2,10],test:[0,2,3,4,5,9],test_list:2,test_model:0,test_polici:0,test_weight:0,testpoint:2,text:[2,6],than:[2,14],thei:14,them:[2,14],theta:2,thi:[0,1,2,6,7,9,10,14],those:2,through:2,tile:2,tile_scal:2,time:[2,14],timeout:10,timeout_happen:10,todo:[1,2],togeth:14,token:6,top:2,total:0,total_centr:2,total_width:2,toward:2,trace:6,traffic:14,train:[0,3,4,9,10],trained_:14,trained_agent_fil:3,trained_polici:[9,10,14],transform:2,transit:[0,9,10],transition_adj:0,travel:2,travers:[0,5],tree:[0,12],trial:[2,14],tupl:[2,10],two:[2,14],type:[2,14],u_ego:[2,10],ucb1:0,ucb:0,undecid:6,undefin:6,under:2,understand:2,uniform:2,uniformli:2,until:14,unus:6,updat:[2,9,14],update_ap:2,update_highest_prior:2,update_local_ap:2,update_waited_count:2,updatelocalap:2,upon:2,usag:14,use:[10,14],use_ucb:0,used:[0,2,6,10,13,14],useful:2,user:14,uses:[2,14],using:[0,2,6,9,14],util:[1,8],v2f:2,v2v:2,v2v_ref:2,v2vdist:2,v_car_scal:2,v_max_multipl:2,v_max_multipli:2,v_space_scal:2,v_tile_scal:2,v_upper_lim:2,valid:[6,10],valu:[0,2,6,9],variabl:2,vec:2,vector:[2,9,10],veh:2,veh_ahead:[2,7],veh_ahead_max:2,veh_ahead_min:2,veh_ahead_scenario:2,veh_ahead_stopped_now:7,veh_ahead_too_clos:7,veh_index:2,vehicl:[1,8,10,14],vehicle_ahead_scenario:2,vehicle_network:[1,8],vehicle_nework:2,vehicle_wheel_bas:2,vehiclenetworkcross:2,vehiclest:2,veloc:2,verbos:0,version:14,vertic:2,via:2,view:14,violat:[1,2,14],violation_happen:1,virtual:6,visit:0,visual:[0,3,4,5,9,14],visualize_low_level_step:[0,9],vlane:2,wai:2,wait:[2,10,14],waited_count:2,waited_tim:2,walk:2,warn:6,weaksepar:6,weight:[0,2,3,4],well:14,were:6,whatev:[2,9,10],wheel:2,when:[0,2],where:[2,9,10,14],wherea:2,whether:[0,1,2,10],which:[0,1,2,6,9,10,14],which_dir:2,whose:2,widen:0,width:2,win_i:2,win_x:2,window:2,wise:[6,7],within:[2,10,14],without:14,work:[0,2],write:5,wrt:2,xmax:2,xmin:2,ymax:2,ymin:2,you:[2,6,14],zero:2},titles:["backends package","env package","env.simple_intersection package","high_level_policy_main module","low_level_policy_main module","mcts module","model_checker package","model_checker.simple_intersection package","wisemove","options package","options.simple_intersection package","ppo2_training module","Contents","Configuration File","Quick Start"],titleterms:{"class":7,ap_dict:7,atom:14,atomic_propositions_bas:6,backend:[0,14],baselines_learn:0,carlo:14,check:14,code:12,configur:13,constant:2,content:[0,1,2,6,7,9,10,12],controller_bas:0,document:12,env:[1,2],env_bas:1,environ:14,featur:2,file:13,guid:12,high:14,high_level_policy_main:3,kerasrl_learn:0,learn:14,learner_bas:0,level:14,linear:14,logic:14,low:14,low_level_policy_main:4,ltl_property_bas:6,ltl_test:7,maneuv:10,maneuver_bas:10,manual_polici:0,mct:5,mcts_learner:0,mcts_maneuv:10,model:14,model_check:[6,7],modul:[0,1,2,3,4,5,6,7,9,10,11],mont:14,online_mcts_control:0,option:[9,10],options_load:9,packag:[0,1,2,6,7,9,10],parser:6,polici:14,policy_bas:0,ppo2_train:11,proposit:14,quick:14,rl_control:0,road_env:1,road_geokinemetri:2,road_network:2,scanner:6,search:[12,14],shape:2,simple_intersect:[2,7,10],simple_intersection_env:2,start:14,submodul:[0,1,2,6,7,9,10],subpackag:[1,6,9],tempor:14,test:14,train:14,tree:14,user:12,util:2,vehicl:2,vehicle_network:2,wisemov:8}}) \ No newline at end of file diff --git a/documentation/sphinx/.build/usage/config.html b/documentation/sphinx/.build/usage/config.html new file mode 100644 index 0000000000000000000000000000000000000000..ca75cf1e5eb50fd307c40bd1536be7b3558b1cc0 --- /dev/null +++ b/documentation/sphinx/.build/usage/config.html @@ -0,0 +1,55 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Configuration File — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>Configuration File</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="configuration-file"> +<h1>Configuration File<a class="headerlink" href="#configuration-file" title="Permalink to this headline">¶</a></h1> +<p><code class="code docutils literal notranslate"><span class="pre">config.json</span></code> can be used to select the maneuvers and high_level policy for fast experimentation.</p> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.build/usage/quickstart.html b/documentation/sphinx/.build/usage/quickstart.html new file mode 100644 index 0000000000000000000000000000000000000000..3aca046517a37b4eb0cce4f362a2f36feb413f4c --- /dev/null +++ b/documentation/sphinx/.build/usage/quickstart.html @@ -0,0 +1,237 @@ + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Quick Start — WiseMove documentation</title> + <link rel="stylesheet" href="../_static/haiku.css" type="text/css" /> + <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> + <link rel="stylesheet" href="../_static/css/fonts.css" type="text/css" /> + <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script> + <script type="text/javascript" src="../_static/jquery.js"></script> + <script type="text/javascript" src="../_static/underscore.js"></script> + <script type="text/javascript" src="../_static/doctools.js"></script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + <link rel="index" title="Index" href="../genindex.html" /> + <link rel="search" title="Search" href="../search.html" /> + <link rel="prev" title="Contents" href="../index.html" /> + </head><body> + <div class="header" role="banner"><h1 class="heading"><a href="../index.html"> + <span>WiseMove documentation</span></a></h1> + <h2 class="heading"><span>Quick Start</span></h2> + </div> + <div class="topnav" role="navigation" aria-label="top navigation"> + + <p> + «  <a href="../index.html">Contents</a> +   ::   + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + <div class="content"> + + + <div class="section" id="quick-start"> +<h1>Quick Start<a class="headerlink" href="#quick-start" title="Permalink to this headline">¶</a></h1> +<div class="section" id="environment"> +<h2>Environment<a class="headerlink" href="#environment" title="Permalink to this headline">¶</a></h2> +<p>An environment that supports the use of options is already provided with the framework, called <em>simple-intersection</em>, which is an autonomous driving environment consisting of a single intersection with two-lane roads. The objective of the agent (the controllable vehicle) is to reach the other side of the intersection while obeying some defined traffic rules and without crashing. The agent takes rate of change of steering angle and acceleration as an input.</p> +<p>The environment supports the use of options/maneuvers, which model certain favourable behaviours. The number and type of maneuver are up to the user to define, but this framework comes with a few pre-defined maneuvers:</p> +<ul class="simple"> +<li>keeplane (drive on the current lane)</li> +<li>changelane (change to the other lane)</li> +<li>stop (come to a stop at a stop sign)</li> +<li>wait (wait at the stop sign until safe)</li> +<li>follow (follow the vehicle in front).</li> +</ul> +</div> +<div class="section" id="low-level-policies"> +<h2>Low-level Policies<a class="headerlink" href="#low-level-policies" title="Permalink to this headline">¶</a></h2> +<p>The policy for executing each maneuver is referred to as the low-level policy, which provides the agent with an input depending on the current state. They can be both manually-defined or learned. For the simple-intersection environment, low-level policies learned using reinforcement learning are provided in the framework. Learning is done using <cite>low_level_policy_main.py</cite>. Use <code class="code docutils literal notranslate"><span class="pre">low_level_policy_main.py</span> <span class="pre">--help</span></code> to view supported arguments and defaults.</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">usage</span><span class="p">:</span> <span class="n">low_level_policy_main</span><span class="o">.</span><span class="n">py</span> <span class="p">[</span><span class="o">-</span><span class="n">h</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">train</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">option</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">test</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">saved_policy_in_root</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">load_weights</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">tensorboard</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">visualize</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">nb_steps</span> <span class="n">NB_STEPS</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">nb_episodes_for_test</span> <span class="n">NB_EPISODES_FOR_TEST</span><span class="p">]</span> + +<span class="n">optional</span> <span class="n">arguments</span><span class="p">:</span> + <span class="o">-</span><span class="n">h</span><span class="p">,</span> <span class="o">--</span><span class="n">help</span> <span class="n">show</span> <span class="n">this</span> <span class="n">help</span> <span class="n">message</span> <span class="ow">and</span> <span class="n">exit</span> + <span class="o">--</span><span class="n">train</span> <span class="n">Train</span> <span class="n">a</span> <span class="n">high</span><span class="o">-</span><span class="n">level</span> <span class="n">policy</span> <span class="k">with</span> <span class="n">default</span> <span class="n">settings</span><span class="o">.</span> + <span class="n">Always</span> <span class="n">saved</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">root</span> <span class="n">folder</span><span class="o">.</span> <span class="n">Always</span> <span class="n">tests</span> <span class="n">after</span> + <span class="n">training</span> + <span class="o">--</span><span class="n">option</span> <span class="n">the</span> <span class="n">option</span> <span class="n">to</span> <span class="n">train</span><span class="o">.</span> <span class="n">Eg</span><span class="o">.</span> <span class="n">stop</span><span class="p">,</span> <span class="n">keeplane</span><span class="p">,</span> <span class="n">wait</span><span class="p">,</span> + <span class="n">changelane</span><span class="p">,</span> <span class="n">follow</span><span class="o">.</span> <span class="n">If</span> <span class="ow">not</span> <span class="n">defined</span><span class="p">,</span> <span class="n">trains</span> <span class="nb">all</span> <span class="n">options</span> + <span class="o">--</span><span class="n">test</span> <span class="n">Test</span> <span class="n">a</span> <span class="n">saved</span> <span class="n">high</span><span class="o">-</span><span class="n">level</span> <span class="n">policy</span><span class="o">.</span> <span class="n">Uses</span> <span class="n">backends</span><span class="o">/</span><span class="n">trained_</span> + <span class="n">policies</span><span class="o">/</span><span class="n">highlevel</span><span class="o">/</span><span class="n">highlevel_weights</span><span class="o">.</span><span class="n">h5f</span> <span class="n">by</span> <span class="n">default</span> + <span class="o">--</span><span class="n">saved_policy_in_root</span> + <span class="n">Use</span> <span class="n">saved</span> <span class="n">policies</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">root</span> <span class="n">of</span> <span class="n">the</span> <span class="n">project</span> <span class="n">rather</span> <span class="n">than</span> + <span class="n">backends</span><span class="o">/</span><span class="n">trained_policies</span><span class="o">/</span><span class="n">highlevel</span><span class="o">/</span> + <span class="o">--</span><span class="n">load_weights</span> <span class="n">Load</span> <span class="n">a</span> <span class="n">saved</span> <span class="n">policy</span> <span class="n">first</span> <span class="n">before</span> <span class="n">training</span> + <span class="o">--</span><span class="n">tensorboard</span> <span class="n">Use</span> <span class="n">tensorboard</span> <span class="k">while</span> <span class="n">training</span> + <span class="o">--</span><span class="n">visualize</span> <span class="n">Visualize</span> <span class="n">the</span> <span class="n">training</span><span class="o">.</span> <span class="n">Testing</span> <span class="ow">is</span> <span class="n">always</span> <span class="n">visualized</span><span class="o">.</span> + <span class="o">--</span><span class="n">nb_steps</span> <span class="n">NB_STEPS</span> <span class="n">Number</span> <span class="n">of</span> <span class="n">steps</span> <span class="n">to</span> <span class="n">train</span> <span class="k">for</span><span class="o">.</span> <span class="n">Default</span> <span class="ow">is</span> <span class="mi">100000</span> + <span class="o">--</span><span class="n">nb_episodes_for_test</span> <span class="n">NB_EPISODES_FOR_TEST</span> + <span class="n">The</span> <span class="n">number</span> <span class="n">of</span> <span class="n">episodes</span> <span class="n">to</span> <span class="n">test</span><span class="o">.</span> <span class="n">Default</span> <span class="ow">is</span> <span class="mi">20</span> +</pre></div> +</div> +<div class="section" id="training"> +<h3>Training<a class="headerlink" href="#training" title="Permalink to this headline">¶</a></h3> +<p>Run <code class="code docutils literal notranslate"><span class="pre">low_level_policy_main.py</span> <span class="pre">--train</span> <span class="pre">--option=OPTION_NAME</span></code>, where OPTION_NAME can be the key of any node defined in <a class="reference external" href="../../../../config.json">config.json</a> to learn the option using reinforcement learning default settings and save the result to root folder. If no option is specified, all options are trained. The training can be customized further using other supported arguments. For example, to train keeplane maneuver and visualize the training, run:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="n">low_level_policy_main</span><span class="o">.</span><span class="n">py</span> <span class="o">--</span><span class="n">train</span> <span class="o">--</span><span class="n">option</span><span class="o">=</span><span class="n">keeplane</span> <span class="o">--</span><span class="n">visualize</span> +</pre></div> +</div> +</div> +<div class="section" id="testing"> +<h3>Testing<a class="headerlink" href="#testing" title="Permalink to this headline">¶</a></h3> +<p>Run <code class="code docutils literal notranslate"><span class="pre">low_level_policy_main.py</span> <span class="pre">--test</span> <span class="pre">--option=OPTION_NAME</span></code> along with other supported arguments to test the trained policy. By default, uses the trained policies in <cite>/backends/trained_policies</cite>. For example:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="n">low_level_policy_main</span><span class="o">.</span><span class="n">py</span> <span class="o">--</span><span class="n">test</span> <span class="o">--</span><span class="n">option</span><span class="o">=</span><span class="n">wait</span> <span class="o">--</span><span class="n">nb_episodes_for_test</span><span class="o">=</span><span class="mi">20</span> +</pre></div> +</div> +</div> +</div> +<div class="section" id="high-level-policy"> +<h2>High-level Policy<a class="headerlink" href="#high-level-policy" title="Permalink to this headline">¶</a></h2> +<p>By composing smaller maneuvers together, the objective can be achieved. It is also possible to have just one maneuver, called ‘drive’ and train it to achieve the goal but it is much harder than defining smaller easy-to-achieve maneuvers and composing them together. This composing of the maneuvers is done by the high-level policy. It decides which maneuver to execute according to the state of the environment.</p> +<p>The high-level policy can also be manually-defined or learned. This framework comes with one learned with reinforcement learning for the simple-intersection environment. Learning is done using <cite>high_level_policy_main.py</cite>. Use <code class="code docutils literal notranslate"><span class="pre">high_level_policy_main.py</span> <span class="pre">--help</span></code> to view supported arguments and defaults.</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">usage</span><span class="p">:</span> <span class="n">high_level_policy_main</span><span class="o">.</span><span class="n">py</span> <span class="p">[</span><span class="o">-</span><span class="n">h</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">train</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">test</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">evaluate</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">saved_policy_in_root</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">load_weights</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">tensorboard</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span><span class="n">visualize</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">nb_steps</span> <span class="n">NB_STEPS</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">nb_episodes_for_test</span> <span class="n">NB_EPISODES_FOR_TEST</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">nb_trials</span> <span class="n">NB_TRIALS</span><span class="p">]</span> + <span class="p">[</span><span class="o">--</span><span class="n">save_file</span> <span class="n">SAVE_FILE</span><span class="p">]</span> + +<span class="n">optional</span> <span class="n">arguments</span><span class="p">:</span> + <span class="o">-</span><span class="n">h</span><span class="p">,</span> <span class="o">--</span><span class="n">help</span> <span class="n">show</span> <span class="n">this</span> <span class="n">help</span> <span class="n">message</span> <span class="ow">and</span> <span class="n">exit</span> + <span class="o">--</span><span class="n">train</span> <span class="n">Train</span> <span class="n">a</span> <span class="n">high</span><span class="o">-</span><span class="n">level</span> <span class="n">policy</span> <span class="k">with</span> <span class="n">default</span> <span class="n">settings</span><span class="o">.</span> + <span class="n">Always</span> <span class="n">saved</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">root</span> <span class="n">folder</span><span class="o">.</span> <span class="n">Always</span> <span class="n">tests</span> <span class="n">after</span> + <span class="n">training</span> + <span class="o">--</span><span class="n">test</span> <span class="n">Test</span> <span class="n">a</span> <span class="n">saved</span> <span class="n">high</span><span class="o">-</span><span class="n">level</span> <span class="n">policy</span><span class="o">.</span> <span class="n">Uses</span> <span class="n">backends</span><span class="o">/</span><span class="n">trained_</span> + <span class="n">policies</span><span class="o">/</span><span class="n">highlevel</span><span class="o">/</span><span class="n">highlevel_weights</span><span class="o">.</span><span class="n">h5f</span> <span class="n">by</span> <span class="n">default</span> + <span class="o">--</span><span class="n">evaluate</span> <span class="n">Evaluate</span> <span class="n">a</span> <span class="n">saved</span> <span class="n">high</span> <span class="n">level</span> <span class="n">policy</span> <span class="n">over</span> <span class="n">n</span> <span class="n">trials</span><span class="o">.</span> <span class="n">Uses</span> + <span class="n">backends</span><span class="o">/</span><span class="n">trained_policies</span><span class="o">/</span><span class="n">highlevel</span><span class="o">/</span><span class="n">highlevel_weights</span><span class="o">.</span> + <span class="n">h5f</span> <span class="n">by</span> <span class="n">default</span> + <span class="o">--</span><span class="n">saved_policy_in_root</span> + <span class="n">Use</span> <span class="n">saved</span> <span class="n">policies</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">root</span> <span class="n">of</span> <span class="n">the</span> <span class="n">project</span> <span class="n">rather</span> <span class="n">than</span> + <span class="n">backends</span><span class="o">/</span><span class="n">trained_policies</span><span class="o">/</span><span class="n">highlevel</span><span class="o">/</span> <span class="p">(</span><span class="n">which</span> <span class="ow">is</span> <span class="n">default</span><span class="p">)</span> + <span class="o">--</span><span class="n">load_weights</span> <span class="n">Load</span> <span class="n">a</span> <span class="n">saved</span> <span class="n">policy</span> <span class="kn">from</span> <span class="nn">root</span> <span class="n">folder</span> <span class="n">first</span> <span class="n">before</span> <span class="n">training</span> + <span class="o">--</span><span class="n">tensorboard</span> <span class="n">Use</span> <span class="n">tensorboard</span> <span class="k">while</span> <span class="n">training</span> + <span class="o">--</span><span class="n">visualize</span> <span class="n">Visualize</span> <span class="n">the</span> <span class="n">training</span><span class="o">.</span> <span class="n">Testing</span> <span class="ow">is</span> <span class="n">always</span> <span class="n">visualized</span><span class="o">.</span> + <span class="n">Evaluation</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">visualized</span> <span class="n">by</span> <span class="n">default</span> + <span class="o">--</span><span class="n">nb_steps</span> <span class="n">NB_STEPS</span> <span class="n">Number</span> <span class="n">of</span> <span class="n">steps</span> <span class="n">to</span> <span class="n">train</span> <span class="k">for</span><span class="o">.</span> <span class="n">Default</span> <span class="ow">is</span> <span class="mi">25000</span> + <span class="o">--</span><span class="n">nb_episodes_for_test</span> <span class="n">NB_EPISODES_FOR_TEST</span> + <span class="n">The</span> <span class="n">number</span> <span class="n">of</span> <span class="n">episodes</span> <span class="n">to</span> <span class="n">test</span><span class="o">/</span><span class="n">evaluate</span><span class="o">.</span> <span class="n">Default</span> <span class="ow">is</span> <span class="mi">20</span> + <span class="o">--</span><span class="n">nb_trials</span> <span class="n">NB_TRIALS</span> + <span class="n">The</span> <span class="n">number</span> <span class="n">of</span> <span class="n">trials</span> <span class="n">to</span> <span class="n">evaluate</span><span class="o">.</span> <span class="n">Default</span> <span class="ow">is</span> <span class="mi">10</span> + <span class="o">--</span><span class="n">save_file</span> <span class="n">SAVE_FILE</span> + <span class="n">filename</span> <span class="n">to</span> <span class="n">save</span><span class="o">/</span><span class="n">load</span> <span class="n">the</span> <span class="n">trained</span> <span class="n">policy</span><span class="o">.</span> <span class="n">Location</span> <span class="ow">is</span> + <span class="k">as</span> <span class="n">specified</span> <span class="n">by</span> <span class="o">--</span><span class="n">saved_policy_in_root</span> +</pre></div> +</div> +<div class="section" id="id1"> +<h3>Training<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h3> +<p>Run <code class="code docutils literal notranslate"><span class="pre">high_level_policy_main.py</span> <span class="pre">--train</span></code> along with other supported arguments to train a policy using reinforcement learning default settings. By default, it is saved to the root folder so as not to overwrite already trained policies. For example:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">high_level_policy_training</span><span class="o">.</span><span class="n">py</span> <span class="o">--</span><span class="n">train</span> <span class="o">--</span><span class="n">nb_steps</span><span class="o">=</span><span class="mi">25000</span> <span class="o">--</span><span class="n">nb_episodes_for_test</span><span class="o">=</span><span class="mi">20</span> +</pre></div> +</div> +</div> +<div class="section" id="id2"> +<h3>Testing<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h3> +<p>Run <code class="code docutils literal notranslate"><span class="pre">high_level_policy_main.py</span> <span class="pre">--test</span></code> or <code class="code docutils literal notranslate"><span class="pre">high_level_policy_main.py</span> <span class="pre">--evaluate</span></code> along with other supported arguments to test the trained policy. By default, uses the trained policies in <cite>/backends/trained_policies/highlevel</cite>. For example:</p> +<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">high_level_policy_training</span><span class="o">.</span><span class="n">py</span> <span class="o">--</span><span class="n">evaluate</span> <span class="o">--</span><span class="n">nb_trials</span><span class="o">=</span><span class="mi">5</span> <span class="o">--</span><span class="n">nb_episodes_for_test</span><span class="o">=</span><span class="mi">20</span> +</pre></div> +</div> +</div> +</div> +<div class="section" id="model-checking"> +<h2>Model Checking<a class="headerlink" href="#model-checking" title="Permalink to this headline">¶</a></h2> +<p>Both low-level and high-level policies, while being trained, use model checking to ensure that user-defined temporal logic constraints are not violated. The user can define global LTL properties that apply to all maneuvers as well as maneuver-specific LTL constraints.</p> +<div class="section" id="atomic-propositions"> +<h3>Atomic Propositions<a class="headerlink" href="#atomic-propositions" title="Permalink to this headline">¶</a></h3> +<p>Atomic propositions for the simple_intersection environment are defined as human-readable strings in <cite>model_checker/simple_intersection/AP_dict.py</cite>. These should evaluate to True or False depending on the state of the environment and they need to be updated in every step of the environment. The temporal logic properties are constructed using a combination of atomic propositions and logic operators.</p> +</div> +<div class="section" id="linear-temporal-logic"> +<h3>Linear Temporal Logic<a class="headerlink" href="#linear-temporal-logic" title="Permalink to this headline">¶</a></h3> +<p>Global temporal logic properties are defined in <cite>env/simple_intersection/simple_intersection_env.py</cite> in _init_LTL_preconditions() function. For example, to add a global constraint that speed must not go beyond speed-limit, you may add <code class="code docutils literal notranslate"><span class="pre">self._LTL_preconditions.append(LTLProperty("G(</span> <span class="pre">not</span> <span class="pre">over_speed_limit)",</span> <span class="pre">200))</span></code> to give a penalty of -200 if the agent crosses the speed limit while using any maneuver.</p> +<p>Maneuver-specific LTL properties can be defined in the corresponding maneuver class in <cite>options/simple_intersection/manuevers.py</cite> in _init_LTL_preconditions() function.</p> +<p>Temporal logic properties are specified using the following syntactic forms, where literal strings are given within quotation marks.</p> +<table border="1" class="docutils"> +<colgroup> +<col width="36%" /> +<col width="64%" /> +</colgroup> +<thead valign="bottom"> +<tr class="row-odd"><th class="head">Form</th> +<th class="head">Meaning</th> +</tr> +</thead> +<tbody valign="top"> +<tr class="row-even"><td>“F†phi</td> +<td>Finally, eventually</td> +</tr> +<tr class="row-odd"><td>“G†phi</td> +<td>Globally, always</td> +</tr> +<tr class="row-even"><td>“X†phi</td> +<td>neXt state</td> +</tr> +<tr class="row-odd"><td>phi “U†phi</td> +<td>Until</td> +</tr> +<tr class="row-even"><td>phi “=>†phi</td> +<td>logical implication</td> +</tr> +<tr class="row-odd"><td>phi “or†phi</td> +<td>logical or</td> +</tr> +<tr class="row-even"><td>phi “and†phi</td> +<td>logical and</td> +</tr> +<tr class="row-odd"><td>“not†phi</td> +<td>logical negation</td> +</tr> +<tr class="row-even"><td>“(†phi “)â€</td> +<td>parenthetic grouping</td> +</tr> +<tr class="row-odd"><td>atomic</td> +<td>atomic_proposition_string</td> +</tr> +</tbody> +</table> +<p>Operator precedence (evaluation order), highest first, is: {atomic, “(“…â€)â€} > “not†> “and†> “or†> “=>†> {“Fâ€, “Gâ€, “Xâ€, “Uâ€}</p> +<p>Nested temporal operators must be enclosed in parentheses, e.g. G in_stop_region => (in_stop_region U has_stopped_in_stop_region).</p> +<p>Note that the arguments of “U†should be predicates over atomic propositions.</p> +</div> +</div> +<div class="section" id="monte-carlo-tree-search"> +<h2>Monte-Carlo Tree Search<a class="headerlink" href="#monte-carlo-tree-search" title="Permalink to this headline">¶</a></h2> +<p>Even after using such a hierarchical structure and model-checking during learning, collisions and constraint violations can be inevitable because the policies are never perfect. This framework supports the safe execution of the high-level policy by using an MCTS to look ahead in time and choose paths that do not lead to a collision or a temporal logic violation. <cite>mcts.py</cite> is used to execute the learned policies using MCTS. As online execution can be computationally expensive the framework also provides an offline version of MCTS that learns probabilities of safe paths and uses it to enhance trained policies.</p> +</div> +<div class="section" id="learning-backend"> +<h2>Learning Backend<a class="headerlink" href="#learning-backend" title="Permalink to this headline">¶</a></h2> +<p>The framework also supports multiple learning backends and it is easy to add and use other ones as necessary. The KerasRL reinforcement learning framework was used to learn and test policies for the simple-intersection environment using <cite>backends/kerasrl_learner.py</cite>. The stable-baselines library has also been incorporated in <cite>backends/baselines_learner.py</cite>.</p> +</div> +</div> + + + </div> + <div class="bottomnav" role="navigation" aria-label="bottom navigation"> + + <p> + «  <a href="../index.html">Contents</a> +   ::   + <a class="uplink" href="../index.html">Contents</a> + </p> + + </div> + + <div class="footer" role="contentinfo"> + © Copyright 2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan. + Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.7.8. + </div> + </body> +</html> \ No newline at end of file diff --git a/documentation/sphinx/.static/css/LibreBaskerville-Regular.ttf b/documentation/sphinx/.static/css/LibreBaskerville-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..57e3c23b5250fa5b1e61277e6f47f2d56c3194b8 Binary files /dev/null and b/documentation/sphinx/.static/css/LibreBaskerville-Regular.ttf differ diff --git a/documentation/sphinx/.static/css/OverpassMono-Regular.ttf b/documentation/sphinx/.static/css/OverpassMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..67bdb9a8dbe28b60dd71e0cd9ec035b9d959cc3c Binary files /dev/null and b/documentation/sphinx/.static/css/OverpassMono-Regular.ttf differ diff --git a/documentation/sphinx/.static/css/OverpassMono-SemiBold.ttf b/documentation/sphinx/.static/css/OverpassMono-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5109b5b88a5c7378b4e0cb630eb706fd4362e0c2 Binary files /dev/null and b/documentation/sphinx/.static/css/OverpassMono-SemiBold.ttf differ diff --git a/documentation/sphinx/.static/css/fonts.css b/documentation/sphinx/.static/css/fonts.css new file mode 100644 index 0000000000000000000000000000000000000000..6e16fc8d4d3a3b3047021cb6a39f8244ca0cafae --- /dev/null +++ b/documentation/sphinx/.static/css/fonts.css @@ -0,0 +1,14 @@ +@font-face { + font-family: "LibreBaskerville"; + src: url("LibreBaskerville-Regular.ttf"); +} +@font-face { + font-family: "OverpassMono"; + src: url("OverpassMono-Regular.ttf"); +} +body, p, ul, ol, li, table { + font-family: LibreBaskerville, Optima, Candara, Calibri, Arial, sans-serif; +} +code, code#descclassname, code#descname, span#pre { + font-family: OverpassMono, "Lucida Console", Monaco, monospace; +} diff --git a/documentation/sphinx/conf.py b/documentation/sphinx/conf.py new file mode 100644 index 0000000000000000000000000000000000000000..b1044e2a9b2b168290a82ba2cad249610e9e5aef --- /dev/null +++ b/documentation/sphinx/conf.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.append(os.path.abspath('.')) +sys.path.append(os.path.abspath('../../.')) +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'WiseMove' +copyright = '2018, Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan' +author = 'Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = '' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.mathjax', + 'sphinx.ext.napoleon', +] + +# Render these files as indicated +source_parsers = { + '.md': 'recommonmark.parser.CommonMarkParser' +} + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['.templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = ['.build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'haiku' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['.static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'wisemovedoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'wisemove.tex', 'wisemove Documentation', + 'Sean Sedwards, Jaeyoung Lee, Ashish Gaurav, Aravind Balakrishnan', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'wisemove', 'wisemove Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'wisemove', 'wisemove Documentation', + author, 'wisemove', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Extension configuration ------------------------------------------------- + +# -- Options for todo extension ---------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + +def setup(app): + app.add_stylesheet('css/fonts.css') \ No newline at end of file diff --git a/documentation/sphinx/index.rst b/documentation/sphinx/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..b6cbd66157cf20bd657ebf949ba0bf8bf0707ff2 --- /dev/null +++ b/documentation/sphinx/index.rst @@ -0,0 +1,25 @@ +.. saferl documentation master file, created by + sphinx-quickstart on Tue Sep 4 16:50:18 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +######## +Contents +######## + +User Guide +=========== +.. toctree:: + :maxdepth: 2 + + usage/quickstart + +Code documentation +================== + +* :ref:`genindex` +* :ref:`modindex` + +Search +================== +* :ref:`search` diff --git a/documentation/sphinx/logfile.log b/documentation/sphinx/logfile.log new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/documentation/sphinx/usage/config.rst b/documentation/sphinx/usage/config.rst new file mode 100644 index 0000000000000000000000000000000000000000..913e769e177b28edf98b4cb3c61bb3b2466b57c6 --- /dev/null +++ b/documentation/sphinx/usage/config.rst @@ -0,0 +1,5 @@ +================== +Configuration File +================== + +:code:`config.json` can be used to select the maneuvers and high_level policy for fast experimentation. \ No newline at end of file diff --git a/documentation/sphinx/usage/quickstart.rst b/documentation/sphinx/usage/quickstart.rst new file mode 100644 index 0000000000000000000000000000000000000000..d1f825abca85a1afb51112e0f6c81bc670ab1d96 --- /dev/null +++ b/documentation/sphinx/usage/quickstart.rst @@ -0,0 +1,174 @@ +########### +Quick Start +########### + +=========== +Environment +=========== + +An environment that supports the use of options is already provided with the framework, called *simple-intersection*, which is an autonomous driving environment consisting of a single intersection with two-lane roads. The objective of the agent (the controllable vehicle) is to reach the other side of the intersection while obeying some defined traffic rules and without crashing. The agent takes rate of change of steering angle and acceleration as an input. + +The environment supports the use of options/maneuvers, which model certain favourable behaviours. The number and type of maneuver are up to the user to define, but this framework comes with a few pre-defined maneuvers: + +* keeplane (drive on the current lane) +* changelane (change to the other lane) +* stop (come to a stop at a stop sign) +* wait (wait at the stop sign until safe) +* follow (follow the vehicle in front). + +================== +Low-level Policies +================== +The policy for executing each maneuver is referred to as the low-level policy, which provides the agent with an input depending on the current state. They can be both manually-defined or learned. For the simple-intersection environment, low-level policies learned using reinforcement learning are provided in the framework. Learning is done using `low_level_policy_main.py`. Use :code:`low_level_policy_main.py --help` to view supported arguments and defaults. + +:: + + usage: low_level_policy_main.py [-h] [--train] [--option] [--test] + [--saved_policy_in_root] [--load_weights] + [--tensorboard] [--visualize] + [--nb_steps NB_STEPS] + [--nb_episodes_for_test NB_EPISODES_FOR_TEST] + + optional arguments: + -h, --help show this help message and exit + --train Train a high-level policy with default settings. + Always saved in the root folder. Always tests after + training + --option the option to train. Eg. stop, keeplane, wait, + changelane, follow. If not defined, trains all options + --test Test a saved high-level policy. Uses backends/trained_ + policies/highlevel/highlevel_weights.h5f by default + --saved_policy_in_root + Use saved policies in the root of the project rather than + backends/trained_policies/highlevel/ + --load_weights Load a saved policy first before training + --tensorboard Use tensorboard while training + --visualize Visualize the training. Testing is always visualized. + --nb_steps NB_STEPS Number of steps to train for. Default is 100000 + --nb_episodes_for_test NB_EPISODES_FOR_TEST + The number of episodes to test. Default is 20 + +Training +======== +Run :code:`low_level_policy_main.py --train --option=OPTION_NAME`, where OPTION_NAME can be the key of any node defined in `config.json <../../../../config.json>`_ to learn the option using reinforcement learning default settings and save the result to root folder. If no option is specified, all options are trained. The training can be customized further using other supported arguments. For example, to train keeplane maneuver and visualize the training, run: + +:: + + python low_level_policy_main.py --train --option=keeplane --visualize + +Testing +======= +Run :code:`low_level_policy_main.py --test --option=OPTION_NAME` along with other supported arguments to test the trained policy. By default, uses the trained policies in `/backends/trained_policies`. For example: + +:: + + python low_level_policy_main.py --test --option=wait --nb_episodes_for_test=20 + +================= +High-level Policy +================= +By composing smaller maneuvers together, the objective can be achieved. It is also possible to have just one maneuver, called 'drive' and train it to achieve the goal but it is much harder than defining smaller easy-to-achieve maneuvers and composing them together. This composing of the maneuvers is done by the high-level policy. It decides which maneuver to execute according to the state of the environment. + +The high-level policy can also be manually-defined or learned. This framework comes with one learned with reinforcement learning for the simple-intersection environment. Learning is done using `high_level_policy_main.py`. Use :code:`high_level_policy_main.py --help` to view supported arguments and defaults. + +:: + + usage: high_level_policy_main.py [-h] [--train] [--test] [--evaluate] + [--saved_policy_in_root] [--load_weights] + [--tensorboard] [--visualize] + [--nb_steps NB_STEPS] + [--nb_episodes_for_test NB_EPISODES_FOR_TEST] + [--nb_trials NB_TRIALS] + [--save_file SAVE_FILE] + + optional arguments: + -h, --help show this help message and exit + --train Train a high-level policy with default settings. + Always saved in the root folder. Always tests after + training + --test Test a saved high-level policy. Uses backends/trained_ + policies/highlevel/highlevel_weights.h5f by default + --evaluate Evaluate a saved high level policy over n trials. Uses + backends/trained_policies/highlevel/highlevel_weights. + h5f by default + --saved_policy_in_root + Use saved policies in the root of the project rather than + backends/trained_policies/highlevel/ (which is default) + --load_weights Load a saved policy from root folder first before training + --tensorboard Use tensorboard while training + --visualize Visualize the training. Testing is always visualized. + Evaluation is not visualized by default + --nb_steps NB_STEPS Number of steps to train for. Default is 25000 + --nb_episodes_for_test NB_EPISODES_FOR_TEST + The number of episodes to test/evaluate. Default is 20 + --nb_trials NB_TRIALS + The number of trials to evaluate. Default is 10 + --save_file SAVE_FILE + filename to save/load the trained policy. Location is + as specified by --saved_policy_in_root + +Training +======== +Run :code:`high_level_policy_main.py --train` along with other supported arguments to train a policy using reinforcement learning default settings. By default, it is saved to the root folder so as not to overwrite already trained policies. For example: + +:: + + high_level_policy_training.py --train --nb_steps=25000 --nb_episodes_for_test=20 + +Testing +======= +Run :code:`high_level_policy_main.py --test` or :code:`high_level_policy_main.py --evaluate` along with other supported arguments to test the trained policy. By default, uses the trained policies in `/backends/trained_policies/highlevel`. For example: + +:: + + high_level_policy_training.py --evaluate --nb_trials=5 --nb_episodes_for_test=20 + +============== +Model Checking +============== + +Both low-level and high-level policies, while being trained, use model checking to ensure that user-defined temporal logic constraints are not violated. The user can define global LTL properties that apply to all maneuvers as well as maneuver-specific LTL constraints. + +Atomic Propositions +=================== +Atomic propositions for the simple_intersection environment are defined as human-readable strings in `model_checker/simple_intersection/AP_dict.py`. These should evaluate to True or False depending on the state of the environment and they need to be updated in every step of the environment. The temporal logic properties are constructed using a combination of atomic propositions and logic operators. + +Linear Temporal Logic +===================== +Global temporal logic properties are defined in `env/simple_intersection/simple_intersection_env.py` in _init_LTL_preconditions() function. For example, to add a global constraint that speed must not go beyond speed-limit, you may add :code:`self._LTL_preconditions.append(LTLProperty("G( not over_speed_limit)", 200))` to give a penalty of -200 if the agent crosses the speed limit while using any maneuver. + +Maneuver-specific LTL properties can be defined in the corresponding maneuver class in `options/simple_intersection/manuevers.py` in _init_LTL_preconditions() function. + +Temporal logic properties are specified using the following syntactic forms, where literal strings are given within quotation marks. + +============== ========================= + Form Meaning +============== ========================= +"F" phi Finally, eventually +"G" phi Globally, always +"X" phi neXt state +phi "U" phi Until +phi "=>" phi logical implication +phi "or" phi logical or +phi "and" phi logical and +"not" phi logical negation +"(" phi ")" parenthetic grouping +atomic atomic_proposition_string +============== ========================= + +Operator precedence (evaluation order), highest first, is: {atomic, "("...")"} > "not" > "and" > "or" > "=>" > {"F", "G", "X", "U"} + +Nested temporal operators must be enclosed in parentheses, e.g. G in_stop_region => (in_stop_region U has_stopped_in_stop_region). + +Note that the arguments of "U" should be predicates over atomic propositions. + +======================= +Monte-Carlo Tree Search +======================= +Even after using such a hierarchical structure and model-checking during learning, collisions and constraint violations can be inevitable because the policies are never perfect. This framework supports the safe execution of the high-level policy by using an MCTS to look ahead in time and choose paths that do not lead to a collision or a temporal logic violation. `mcts.py` is used to execute the learned policies using MCTS. As online execution can be computationally expensive the framework also provides an offline version of MCTS that learns probabilities of safe paths and uses it to enhance trained policies. + +================ +Learning Backend +================ + +The framework also supports multiple learning backends and it is easy to add and use other ones as necessary. The KerasRL reinforcement learning framework was used to learn and test policies for the simple-intersection environment using `backends/kerasrl_learner.py`. The stable-baselines library has also been incorporated in `backends/baselines_learner.py`. \ No newline at end of file diff --git a/env/__init__.py b/env/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8b335d2b591e6d8dc3fd32cf7e0aa35b7fa1f3f9 --- /dev/null +++ b/env/__init__.py @@ -0,0 +1,2 @@ +from .env_base import EpisodicEnvBase +from .road_env import RoadEnv diff --git a/env/env_base.py b/env/env_base.py new file mode 100644 index 0000000000000000000000000000000000000000..4aa50f23b32517c3de5494d2f553b54b7a96b6a3 --- /dev/null +++ b/env/env_base.py @@ -0,0 +1,189 @@ +from model_checker import Parser + + +class GymCompliantEnvBase: + def step(self, action): + """ Gym compliant step function which + will be implemented in the subclass. + """ + raise NotImplemented(self.__class__.__name__ + "step is not implemented.") + + def reset(self): + """ Gym compliant reset function which + will be implemented in the subclass. + """ + raise NotImplemented(self.__class__.__name__ + "reset is not implemented.") + + def render(self): + """ Gym compliant step function which + will be implemented in the subclass. + """ + raise NotImplemented(self.__class__.__name__ + "render is not implemented.") + + +class EpisodicEnvBase(GymCompliantEnvBase): + + # three types possible ('min', 'max', or 'sum'); + # See _reward_superposition below. + terminal_reward_type = 'max' + + #: If true, the maneuver terminates when the goal has been achieved. + _terminate_in_goal = False + + #: the reward given at the end of the episode when achieving the goal + # (only active when _terminate_in_goal = True). + _reward_in_goal = 200 + + def enable_LTL_preconditions(self): + self._LTL_preconditions_enable = True + + def disable_LTL_preconditions(self): + self._LTL_preconditions_enable = False + + @property + def r_terminal(self): + return self._r_terminal + + def _init_LTL_preconditions(self): + """Initialize the LTL preconditions (self._LTL_preconditions).. + in the subclass. + """ + return + + def __init__(self): + + #: the set of LTL preconditions that initiate and terminate the envoronment. + self._LTL_preconditions = list() + + #: If True, then the LTLs in _LTL_preconditions above + # determines the termination + self._LTL_preconditions_enable = True + + #: the atomic proposition for model-checking (initially all False) + self.__mc_AP = 0 + + self._init_LTL_preconditions() + + #: the terminal reward calculated via step; + # it is not None only when the episode (or maneuver) ends. + self._r_terminal = None + + def _terminal_reward_superposition(self, r_obs): + """Calculate the next value when observing "obs," from the prior + using min, max, or summation depending on the superposition_type. + """ + + if r_obs is None: + return + + if self.terminal_reward_type == 'min': + self._r_terminal = r_obs if self._r_terminal is None else min(self._r_terminal, r_obs) + elif self.terminal_reward_type == 'max': + self._r_terminal = r_obs if self._r_terminal is None else max(self._r_terminal, r_obs) + elif self.terminal_reward_type == 'sum': + self._r_terminal = r_obs if self._r_terminal is None else self._r_terminal + r_obs + else: + raise AssertionError("The terminal_reward_type has to be 'min', 'max', or 'sum'") + + def step(self, u): + # the penalty is a negative reward. + # So, "penalty" will be summed up to the final reward with its sign + # reversed, i.e., the reward = - penalty + (the other reward terms). + self._r_terminal = None + + if self._LTL_preconditions_enable: + terminal, info = self._incremental_model_checking() + if terminal: + info['episode_termination_reason'] = "LTL_violation" + else: + terminal = False + info = dict() + + if self._terminate_in_goal and self.goal_achieved: + self._terminal_reward_superposition(self._reward_in_goal) + terminal = True + + reward = 0 if self._r_terminal is None else self._r_terminal + + return None, reward, terminal, info + + def _incremental_model_checking(self, AP=None): + + if AP is not None: + self.__mc_AP = int(AP) + + info = dict() + violate = False + for LTL_precondition in self._LTL_preconditions: + if LTL_precondition.enabled: + LTL_precondition.check_incremental(self.__mc_AP) + if LTL_precondition.result == Parser.FALSE: + self._terminal_reward_superposition(EpisodicEnvBase._reward(LTL_precondition.penalty)) + violate = True + info['ltl_violation'] = LTL_precondition.str + # print("\nViolation of \"" + LTL_precondition.str + "\"") + + return violate, info + + def current_model_checking_result(self): + """Returns whether or not any of the conditions is currently violated.""" + + for LTL_precondition in self._LTL_preconditions: + if LTL_precondition.result == Parser.FALSE: + return True + return False + + def _reset_model_checker(self, AP): + + self.__mc_AP = int(AP) + + if self._LTL_preconditions_enable: + for LTL_precondition in self._LTL_preconditions: + LTL_precondition.reset_property() + if LTL_precondition.enabled: + LTL_precondition.check_incremental(self.__mc_AP) + + def _set_mc_AP(self, AP): + self.__mc_AP = int(AP) + + @property + def termination_condition(self): + """In the subclass, specify the condition for termination of the episode + (or the maneuver). + """ + if self._terminate_in_goal and self.goal_achieved: + return True + + return self.violation_happened and self._LTL_preconditions_enable + + @property + def goal_achieved(self): + """Check whether the ego vehicle achieves the goal of the maneuver or + not. + + By default, there is no goal, so the ego vehicle never achieves + it (i.e., goal_achieved is always False). + """ + + return False + + @property + def violation_happened(self): + if not self._LTL_preconditions_enable: + return False + + for LTL_precondition in self._LTL_preconditions: + if LTL_precondition.result == Parser.FALSE: + return True + return False + + + # TODO: replace these confusing methods reward and penalty, or not to use both reward and penalty for the property naming. + @staticmethod + def _reward(penalty): + return None if penalty is None else -penalty + + @staticmethod + def _penalty(reward): + return None if reward is None else -reward + diff --git a/env/road_env.py b/env/road_env.py new file mode 100644 index 0000000000000000000000000000000000000000..3a189ed347a78fc9d74f13073966b6f57baf5d58 --- /dev/null +++ b/env/road_env.py @@ -0,0 +1,6 @@ +class RoadEnv: + """The generic road env + + TODO: Implement this generic road env for plugging-in other road envs. + TODO: roadEnv also having a step() function can cause a problem. + """ \ No newline at end of file diff --git a/env/simple_intersection/__init__.py b/env/simple_intersection/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..59614fb13035876090125ab06883b59cb6d7e576 --- /dev/null +++ b/env/simple_intersection/__init__.py @@ -0,0 +1 @@ +from .simple_intersection_env import SimpleIntersectionEnv \ No newline at end of file diff --git a/env/simple_intersection/constants.py b/env/simple_intersection/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..73254ce4e5e79f5333536ff7a4f3759e4b89bdbf --- /dev/null +++ b/env/simple_intersection/constants.py @@ -0,0 +1,76 @@ +from . import road_geokinemetry as rd +import numpy as np + +#: Index of the ego vehicle in the vehicles list +EGO_INDEX = 0 + +#: Number of pixels in the horizontal direction +NUM_HPIXELS = 640 + +#: Number of pixels in the vertical direction +NUM_VPIXELS = round(NUM_HPIXELS * rd.vlanes.length / rd.hlanes.length) + +#: Horizontal space scale +H_SPACE_SCALE = NUM_HPIXELS / rd.hlanes.length + +#: Vertical space scale +V_SPACE_SCALE = NUM_VPIXELS / rd.vlanes.length + +#: Number of horizontal tiles +NUM_HTILES = round(rd.hlanes.length / rd.hlanes.total_width) + +#: Number of horizontal tiles +NUM_VTILES = round(rd.vlanes.length / rd.vlanes.total_width) + +#: Lambda function that takes in tile width and returns scale_x for road tile +H_TILE_SCALE = lambda w: (NUM_HPIXELS / NUM_HTILES) / w + +#: Lambda function that takes in tile height and returns scale_y for road tile +V_TILE_SCALE = lambda h: (NUM_VPIXELS / NUM_VTILES) / h + +#: half of the (x,y)-size of the car as a bounding box when\ +# horizontally aligned +VEHICLE_SIZE_HALF = [2.5 / 2.0, 1.7 / 2.0] + +#: vehicle wheel base ( = L in the paper) +VEHICLE_WHEEL_BASE = 1.7 + +#: maximum acceleration +MAX_ACCELERATION = 2.0 + +#: maximum steering angle - 33 deg. (extreme case: 53 deg.) +MAX_STEERING_ANGLE = 33.0 * np.pi / 108.0 + +#: maximum rate of change of steering angle +MAX_STEERING_ANGLE_RATE = 1.0 + +#: the time difference btw. the current and the next time steps. +DT = 0.1 + +#: Constants for state-constrained Runge-Kutta 4 method in vehicles.py +DT_over_2 = DT / 2 +DT_2_over_3 = 2 * DT / 3 +DT_over_3 = DT / 3 +DT_over_6 = DT / 6 + +#: time scale of the animation; 1 sec in the road environment +# corresponds to "time_scale" sec in the animation. +TIME_SCALE = 1 + +#: Lambda function that takes in car width and returns scale_x for car +H_CAR_SCALE = lambda w: VEHICLE_SIZE_HALF[0] * 2 * H_SPACE_SCALE / w + +#: Lambda function that takes in car height and returns scale_y for car +V_CAR_SCALE = lambda h: VEHICLE_SIZE_HALF[1] * 2 * V_SPACE_SCALE / h + +#: Lane separator width +LANE_SEPARATOR_HALF_WIDTH = 1 + +#: Road tile image dimension +ROAD_TILE_IMAGE_DIM = 300 + +#: Lane width +LANE_WIDTH = ROAD_TILE_IMAGE_DIM * V_TILE_SCALE(ROAD_TILE_IMAGE_DIM) / 2 + +#: MAX NUMBER OF VEHICLES +MAX_NUM_VEHICLES = 6 \ No newline at end of file diff --git a/env/simple_intersection/features.py b/env/simple_intersection/features.py new file mode 100644 index 0000000000000000000000000000000000000000..6b63e101a5580587020e44096f69fa17aab8e54b --- /dev/null +++ b/env/simple_intersection/features.py @@ -0,0 +1,173 @@ +from . import road_geokinemetry as rd +import numpy as np +from .constants import * + +#: con_ego_feature_dict contains the indexing information regarding elements +# of the ego vehicle's continuous feature vector. +# +# * e_stop: the error between the x-pos and the end of the stop region +# (this is clipped by some threshold). +# * v: velocity +# * v_ref: reference velocity +# * e_y: lateral error btw the ego and the target lane centreline +# * psi: steering angle +# * v tan(psi/L): the term v tan( psi / L ) -- see VehicleState in +# vehicles.py +# * theta: heading angle +# * lane: current lane (0: left, 1: right) +# * e_y,lane: lateral error btw the ego and the current lane centreline +# * acc: acceleration at the previous time +# * psi_dot: the time derivative at steering angle at the previous time +# * pos_stop_region: position in the stop region +con_ego_feature_dict = { + 'pos_near_stop_region': 0, + 'v': 1, + 'v_ref': 2, + 'e_y': 3, + 'psi': 4, + 'v tan(psi/L)': 5, + 'theta': 6, + 'lane': 7, + 'e_y,lane': 8, + 'acc': 9, + 'psi_dot': 10, + 'pos_stop_region': 11 +} + +#: dis_ego_feature_dict contains all indexing information regarding +# each element of the ego vehicle's discrete feature vector. +# +# * not_in_stop_region: True if the ego is in stop region; +# * has_entered_stop_region: True if the ego has entered the stop region; +# * has_stop_in_stop_region: True if the ego has stopped in the stop region; +# * in_intersection: True if the ego is in the intersection +# * over_speed_limit: True if the speed of the ego is over the speed limit; +# * on_route: True if the ego is on the horizontal route; +# * intersection_is_clear: True when the intersection is clear; +# * highest_priority: True if the ego has the highest priority in the +# intersection. +dis_ego_feature_dict = { + 'not_in_stop_region': 0, + 'has_entered_stop_region': 1, + 'has_stopped_in_stop_region': 2, + 'in_intersection': 3, + 'over_speed_limit': 4, + 'on_route': 5, + 'intersection_is_clear': 6, + 'highest_priority': 7 +} + +other_veh_feature_dict = { + 'rel_x': 0, + 'rel_y': 1, + 'v': 2, + 'acc': 3, + 'waited_time': 4 +} + +ego_feature_dict = dict() +for key in con_ego_feature_dict.keys(): + ego_feature_dict[key] = con_ego_feature_dict[key] +for key in dis_ego_feature_dict.keys(): + ego_feature_dict[key] = dis_ego_feature_dict[key] + len(con_ego_feature_dict) + +ego_feature_len = len(ego_feature_dict) +other_veh_feature_len = len(other_veh_feature_dict) + + +def extract_ego_features(features_tuple, *args): + return tuple(features_tuple[ego_feature_dict[key]] for key in args) + + +def extract_other_veh_features(features_tuple, veh_index, *args): + return tuple(features_tuple[ego_feature_len + + (veh_index - 1) * other_veh_feature_len + other_veh_feature_dict[key]] + for key in args) + + +class OtherVehFeatures(object): + def __init__(self, rel_x, rel_y, v, acc, waited_time): + self.rel_x = rel_x + self.rel_y = rel_y + self.v = v + self.acc = acc + self.waited_time = waited_time + + +class Features(object): + def __init__(self, env): + """For the current state, get the feature vector of the ego vehicle. + + Args: + target_lane: 0 if the target lane is the left one, and + 1 if the target is the right lane. + + Returns: + a tuple of the complete features + """ + + ego = env.ego + v_ref = env.v_ref + target_lane = env.target_lane + stop_region_length = np.abs(rd.hlanes.stop_region[1] - rd.hlanes.stop_region[0]) + + assert (target_lane == True) or (target_lane == False) + + # Continuous feature vector of the ego-vehicle. + self.con_ego = ( + # TODO: separate this into the two, one for Default and one for Finish, and try to learn. + min(rd.hlanes.stop_region[1] - ego.x, 50)/50, + ego.v, v_ref, ego.y - rd.hlanes.centres[target_lane], + ego.psi, ego.v * np.tan(ego.psi) / VEHICLE_WHEEL_BASE, + ego.theta, ego.APs['lane'], + ego.y - rd.hlanes.centres[ego.APs['lane']], + ego.acc, ego.psi_dot, + np.clip(rd.hlanes.stop_region[1] - ego.x, 0, stop_region_length)/stop_region_length) + + # Discrete feature vector of the ego-vehicle. + self.dis_ego = ( + not ego.APs['in_stop_region'], + ego.APs['has_entered_stop_region'], + ego.APs['has_stopped_in_stop_region'], + ego.APs['in_intersection'], + ego.APs['over_speed_limit'], + ego.APs['on_route'], + ego.APs['intersection_is_clear'], + ego.APs['highest_priority'], + ) + + self.other_vehs = () + + # Features of the other vehicles (relative distance (x,y), + # velocity, acceleration, waited_j). + for veh in env.vehs[1:]: + self.other_vehs += (OtherVehFeatures( + ego.x - veh.x, ego.y - veh.y, veh.v, veh.acc, + veh.waited_count * DT), ) + + def reset(self, env): + self.__init__(env) + + def __getitem__(self, index): + if index in con_ego_feature_dict: + return self.con_ego[con_ego_feature_dict[index]] + elif index in dis_ego_feature_dict: + return self.dis_ego[dis_ego_feature_dict[index]] + else: + return self.other_vehs[index] + + def get_features_tuple(self): + """ + continuous + discrete features + """ + feature = self.con_ego + self.dis_ego + + for other_veh in self.other_vehs: + feature += (other_veh.rel_x, other_veh.rel_y, other_veh.v, + other_veh.acc, other_veh.waited_time) + + # Add buffer features to make a fixed length feature vector + for i in range(MAX_NUM_VEHICLES-len(self.other_vehs)): + feature += (0.0, 0.0, 0.0, 0.0, -1) + + return feature diff --git a/env/simple_intersection/graphics/background.png b/env/simple_intersection/graphics/background.png new file mode 100644 index 0000000000000000000000000000000000000000..8866897c391a446daeb584d95b18646f2db9c031 Binary files /dev/null and b/env/simple_intersection/graphics/background.png differ diff --git a/env/simple_intersection/graphics/car_agent.png b/env/simple_intersection/graphics/car_agent.png new file mode 100644 index 0000000000000000000000000000000000000000..0a921dab2ec748faeeec067de1e0da272bde66f6 Binary files /dev/null and b/env/simple_intersection/graphics/car_agent.png differ diff --git a/env/simple_intersection/graphics/ego_vehicle.svg b/env/simple_intersection/graphics/ego_vehicle.svg new file mode 100644 index 0000000000000000000000000000000000000000..a4ba048b1c2223bf6d4dcbc495b4fb4bf2ef03a6 --- /dev/null +++ b/env/simple_intersection/graphics/ego_vehicle.svg @@ -0,0 +1,404 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + id="svg2" + version="1.1" + viewBox="0 0 960 476" + inkscape:version="0.91 r13725" + sodipodi:docname="car2.svg"> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1855" + inkscape:window-height="1056" + id="namedview62" + showgrid="false" + inkscape:zoom="1.2416667" + inkscape:cx="395.1322" + inkscape:cy="275.63242" + inkscape:window-x="65" + inkscape:window-y="24" + inkscape:window-maximized="1" + inkscape:current-layer="svg2" /> + <title + id="title3968">Red Car - Top View</title> + <defs + id="defs4"> + <linearGradient + id="linearGradient3759"> + <stop + id="stop3761" + style="stop-color:#1a1a1a" + offset="0" /> + <stop + id="stop3763" + style="stop-color:#000000;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient4149" + y2="834.68" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="848.16" + gradientTransform="translate(-44.6285,-489.3418)" + y1="842.3" + x1="871.33" /> + <linearGradient + id="linearGradient4153" + y2="533.5" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="812.14" + gradientTransform="matrix(0.89332,0,0,0.89332,27.412,-121.54)" + y1="537.5" + x1="879.9" /> + <linearGradient + id="linearGradient4155" + y2="531.91" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="815.82" + gradientTransform="translate(-25.312,-190.2)" + y1="537.5" + x1="879.9" /> + <linearGradient + id="linearGradient4185" + y2="834.68" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="848.16" + gradientTransform="matrix(1,0,0,-1,-44.6285,965.31)" + y1="842.3" + x1="871.33" /> + <linearGradient + id="linearGradient4187" + y2="528.42" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="876.14" + gradientTransform="matrix(1,0,0,-1,-31.499,664.81)" + y1="528.36" + x1="887.9" /> + <linearGradient + id="linearGradient4189" + y2="531.91" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="815.82" + gradientTransform="matrix(1,0,0,-1,-25.312,666.21)" + y1="537.5" + x1="879.9" /> + <linearGradient + id="linearGradient4191" + y2="535.37" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="883.76" + gradientTransform="matrix(1,0,0,-1,-31.499,664.81)" + y1="542.4" + x1="897.22" /> + <linearGradient + id="linearGradient4193" + y2="501.08" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="835.99" + gradientTransform="matrix(1,0,0,-1,-31.499,664.81)" + y1="552.05" + x1="880.71" /> + <linearGradient + id="linearGradient4195" + y2="529.61" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="805.29" + gradientTransform="matrix(0.89332,0,0,-0.89332,41.219,601.11)" + y1="528.36" + x1="887.9" /> + <linearGradient + id="linearGradient4197" + y2="533.5" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="812.14" + gradientTransform="matrix(0.89332,0,0,-0.89332,27.412,597.51)" + y1="537.5" + x1="879.9" /> + <linearGradient + id="linearGradient4199" + y2="867.68" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="205.59" + gradientTransform="matrix(0.99043,-0.13799,-0.13799,-0.99043,93.113,996.61)" + y1="873.14" + x1="229.7" /> + <linearGradient + id="linearGradient4201" + y2="872.65" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="216.56" + gradientTransform="matrix(0.99043,-0.13799,-0.13799,-0.99043,103.373,995.31)" + y1="873.06" + x1="238.83" /> + <linearGradient + id="linearGradient4203" + y2="528.42" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="876.14" + gradientTransform="translate(-31.499,-188.78)" + y1="528.36" + x1="887.9" /> + <linearGradient + id="linearGradient4205" + y2="535.37" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="883.76" + gradientTransform="translate(-31.499,-188.78)" + y1="542.4" + x1="897.22" /> + <linearGradient + id="linearGradient4207" + y2="501.08" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="835.99" + gradientTransform="translate(-31.499,-188.78)" + y1="552.05" + x1="880.71" /> + <linearGradient + id="linearGradient4209" + y2="529.61" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="805.29" + gradientTransform="matrix(0.89332,0,0,0.89332,41.219,-125.12)" + y1="528.36" + x1="887.9" /> + <linearGradient + id="linearGradient4211" + y2="867.68" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="205.59" + gradientTransform="matrix(0.99043,0.13799,-0.13799,0.99043,93.113,-520.575)" + y1="873.14" + x1="229.7" /> + <linearGradient + id="linearGradient4213" + y2="872.65" + xlink:href="#linearGradient3759" + gradientUnits="userSpaceOnUse" + x2="216.56" + gradientTransform="matrix(0.99043,0.13799,-0.13799,0.99043,103.373,-519.293)" + y1="873.06" + x1="238.83" /> + </defs> + <path + id="path3855" + style="fill-opacity:0.99607999;stroke:#191919;stroke-width:14" + d="m 557.583,7 c -1.5086,0.009 -4.7211,0.30491 -6.4687,0.9375 l -3.5,1.5 8.6562,35.938 -124.81,0.28125 c -2.4363,0.005 -4.8876,-0.014 -7.3437,-0.0312 -4.912,-0.0343 -9.8649,-0.10455 -14.844,-0.21875 -7.2926,-0.16728 -14.669,-0.41288 -22.062,-0.71875 -0.39591,-0.0164 -0.79137,-0.0457 -1.1875,-0.0625 -14.932,-0.63018 -30.007,-1.4917 -45.031,-2.4375 -20.326,-1.2827 -40.52,-2.7074 -60.124,-3.875 -14.528,-0.8653 -28.732,-1.5796 -42.375,-2 -9.3692,-0.28873 -18.464,-0.45655 -27.25,-0.40625 -4.3158,0.0247 -8.5678,0.0933 -12.719,0.21875 -4.1508,0.12546 -8.3801,0.3553 -12.656,0.65625 -2.138,0.15047 -4.2778,0.31024 -6.4374,0.5 -6.4689,0.5684 -13.045,1.3214 -19.594,2.1875 -0.0101,0.001 -0.0211,-10e-4 -0.0312,0 -4.3725,0.57858 -8.7185,1.2255 -13.062,1.9062 -4.3439,0.68073 -8.6734,1.3978 -12.937,2.1562 -4.2537,0.75662 -8.4704,1.5654 -12.594,2.375 -0.01,0.002 -0.0212,-0.002 -0.0312,0 -2.0664,0.40586 -4.0697,0.80417 -6.0937,1.2188 -6.0614,1.2416 -11.934,2.516 -17.5,3.7812 -0.0101,0.002 -0.0211,-0.002 -0.0312,0 -3.7165,0.8449 -7.2872,1.6752 -10.719,2.5 -6.8638,1.6484 -13.115,3.2346 -18.531,4.6562 -8.1236,2.1325 -14.382,3.9272 -18.094,5 -2.4736,0.71578 -3.8125,1.125 -3.8125,1.125 l -13.687,3.75 c -0.9024,0.24873 -1.7781,0.6929 -2.625,1.3125 -0.28771,0.2105 -0.56234,0.43593 -0.84374,0.6875 -1.0996,0.9796 -2.151,2.2707 -3.1562,3.8438 -0.0046,0.007 0.0046,0.0243 0,0.0312 -0.50036,0.78473 -1.0225,1.6405 -1.5,2.5625 -0.0042,0.008 0.0042,0.0232 0,0.0312 -0.47757,0.9237 -0.95114,1.9142 -1.4062,2.9688 -0.0037,0.009 0.0037,0.0222 0,0.0312 -3.667,8.5095 -6.62,21.131 -8.9374,36.219 -0.0015,0.01 0.0015,0.0212 0,0.0312 -0.03595,0.23416 -0.0581,0.48342 -0.09375,0.71875 -0.50462,3.3315 -0.99204,6.7982 -1.4375,10.344 -0.03048,0.24265 -0.06355,0.47519 -0.09375,0.71875 -0.50157,4.0432 -0.94672,8.2025 -1.375,12.469 -10e-4,0.01 9.99e-4,0.0211 0,0.0312 -0.21354,2.1284 -0.42912,4.2948 -0.62499,6.4688 -9.21e-4,0.01 9.21e-4,0.0209 0,0.0312 -0.19581,2.1743 -0.38397,4.3492 -0.56249,6.5625 -8.26e-4,0.01 8.25e-4,0.0209 0,0.0312 -0.35775,4.4376 -0.67817,8.9458 -0.96874,13.5 -6.56e-4,0.0101 6.55e-4,0.0209 0,0.0312 -0.8726,13.684 -1.4596,27.789 -1.7812,41.562 -2.45e-4,0.0104 2.44e-4,0.0207 0,0.0312 -0.21443,9.1894 -0.3126,18.213 -0.3126,26.907 0,0.96763 0.02755,1.9629 0.03125,2.9375 -0.0037,0.97462 -0.03125,1.9699 -0.03125,2.9375 0,8.6932 0.09816,17.717 0.3125,26.906 2.44e-4,0.0105 -2.45e-4,0.0208 0,0.0312 0.32165,13.774 0.90864,27.878 1.7812,41.562 6.55e-4,0.0103 -6.56e-4,0.0211 0,0.0312 0.29057,4.5542 0.61099,9.0624 0.96874,13.5 8.25e-4,0.0103 -8.26e-4,0.0211 0,0.0312 0.17852,2.2133 0.36668,4.3882 0.56249,6.5625 9.21e-4,0.0103 -9.21e-4,0.0211 0,0.0312 0.19588,2.174 0.41145,4.3404 0.62499,6.4688 9.99e-4,0.0102 -10e-4,0.0211 0,0.0312 0.42826,4.2663 0.87342,8.4256 1.375,12.469 0.0302,0.24356 0.06327,0.4761 0.09375,0.71875 0.44545,3.5456 0.93287,7.0123 1.4375,10.344 0.03565,0.23533 0.0578,0.48459 0.09375,0.71875 0.0015,0.01 -0.0015,0.0215 0,0.0312 2.3174,15.087 5.2704,27.709 8.9374,36.219 0.0037,0.009 -0.0037,0.0226 0,0.0312 0.45509,1.0546 0.92866,2.045 1.4062,2.9688 0.0042,0.008 -0.0042,0.0231 0,0.0312 0.47753,0.92204 0.99962,1.7778 1.5,2.5625 0.0046,0.007 -0.0046,0.0242 0,0.0312 1.0052,1.5731 2.0566,2.8642 3.1562,3.8438 0.2814,0.25157 0.55603,0.477 0.84374,0.6875 0.84686,0.6196 1.7226,1.0638 2.625,1.3125 l 13.687,3.75 c 0,0 1.3388,0.40922 3.8125,1.125 3.7111,1.0728 9.97,2.8675 18.094,5 5.4157,1.4217 11.667,3.0078 18.531,4.6562 3.4314,0.82484 7.0022,1.6551 10.719,2.5 0.0102,0.002 0.0211,-0.002 0.0312,0 5.5661,1.2652 11.438,2.5396 17.5,3.7812 2.024,0.41458 4.0273,0.81289 6.0937,1.2188 0.0101,0.002 0.0212,-0.002 0.0312,0 4.1232,0.80965 8.3399,1.6184 12.594,2.375 4.264,0.75843 8.5935,1.4755 12.937,2.1562 4.3439,0.68073 8.6898,1.3277 13.062,1.9062 0.0102,10e-4 0.0211,-0.001 0.0312,0 6.5486,0.86611 13.125,1.6191 19.594,2.1875 2.1597,0.18976 4.2994,0.34953 6.4374,0.5 4.276,0.30095 8.5053,0.53079 12.656,0.65625 4.1508,0.12546 8.4028,0.19403 12.719,0.21875 8.7859,0.0503 17.881,-0.11752 27.25,-0.40625 13.642,-0.42043 27.847,-1.1347 42.375,-2 19.604,-1.1676 39.798,-2.5923 60.124,-3.875 15.024,-0.94578 30.098,-1.8073 45.031,-2.4375 0.39612,-0.0168 0.79158,-0.0461 1.1875,-0.0625 7.3934,-0.30587 14.77,-0.55147 22.062,-0.71875 4.9787,-0.1142 9.9316,-0.18447 14.844,-0.21875 2.456,-0.0172 4.9073,-0.0365 7.3437,-0.0312 l 124.81,0.28125 -8.6562,35.938 3.5,1.5 c 1.7476,0.63259 4.9601,0.92851 6.4687,0.9375 0.8486,0.005 1.7551,-0.0741 2.6875,-0.25 0.31069,-0.0585 0.62352,-0.14105 0.93749,-0.21875 0.30459,-0.0756 0.63258,-0.15668 0.93749,-0.25 0.62844,-0.19306 1.2635,-0.42156 1.875,-0.6875 1.8215,-0.79351 3.5342,-1.9314 4.7812,-3.3125 0.01,-0.0107 0.0217,-0.0206 0.0312,-0.0312 0.6248,-0.6979 1.1123,-1.4512 1.4687,-2.2812 l 12.156,-31.312 109.94,0.25 c 0.7469,0.3739 1.4761,0.74511 2.2187,1.0938 2.9792,1.3995 5.911,2.597 8.8436,3.625 1.4623,0.51259 2.9178,0.97549 4.375,1.4062 5.1,1.5075 10.188,2.5515 15.344,3.25 2.9462,0.39932 5.9259,0.69388 8.9374,0.90625 1.5057,0.1061 3.034,0.18011 4.5624,0.25 3.057,0.13994 6.1386,0.21283 9.3124,0.25 6.3475,0.0741 12.979,0 20,0 10.41,0 20.322,-0.53122 29.781,-1.5625 3.7835,-0.41251 7.4911,-0.89749 11.125,-1.4688 7.2676,-1.1425 14.228,-2.6189 20.906,-4.375 1.6694,-0.43903 3.3357,-0.89874 4.9687,-1.375 4.899,-1.4288 9.6128,-3.0254 14.187,-4.7812 1.5248,-0.58527 3.042,-1.1605 4.5312,-1.7812 2.9783,-1.2414 5.882,-2.557 8.7186,-3.9375 1.4183,-0.69027 2.8355,-1.4006 4.2187,-2.125 2.7664,-1.4488 5.4668,-2.98 8.0937,-4.5625 1.3135,-0.79125 2.5961,-1.6135 3.875,-2.4375 6.3943,-4.1201 12.363,-8.6255 17.906,-13.531 4.4286,-3.9195 8.6015,-8.0798 12.5,-12.469 0.005,-0.006 -0.005,-0.0254 0,-0.0312 0.97044,-1.0929 1.937,-2.1916 2.875,-3.3125 0.005,-0.006 -0.005,-0.0251 0,-0.0312 0.93773,-1.1209 1.8757,-2.2578 2.7812,-3.4062 0.005,-0.006 -0.005,-0.0249 0,-0.0312 2.7256,-3.4582 5.3132,-7.0189 7.7499,-10.719 0.005,-0.007 -0.005,-0.024 0,-0.0312 0.80882,-1.2286 1.6289,-2.4644 2.4062,-3.7188 0.005,-0.008 -0.005,-0.0238 0,-0.0312 2.3405,-3.7781 4.5668,-7.6525 6.6249,-11.656 0.004,-0.008 -0.004,-0.0231 0,-0.0312 0.68299,-1.3292 1.3477,-2.6781 2,-4.0312 0.004,-0.008 -0.004,-0.0229 0,-0.0312 0.65204,-1.3533 1.316,-2.7169 1.9375,-4.0938 0.004,-0.009 -0.004,-0.0227 0,-0.0312 1.2464,-2.7625 2.438,-5.5517 3.5625,-8.4062 0.004,-0.009 -0.004,-0.0224 0,-0.0312 0.56023,-1.4229 1.0948,-2.8674 1.625,-4.3125 0.003,-0.009 -0.003,-0.0222 0,-0.0312 0.53002,-1.4452 1.0623,-2.908 1.5625,-4.375 0.49999,-1.4671 0.99842,-2.949 1.4687,-4.4375 0.003,-0.009 -0.003,-0.022 0,-0.0312 0.47013,-1.4886 0.93435,-2.9905 1.375,-4.5 0.003,-0.01 -0.003,-0.0217 0,-0.0312 0.44045,-1.5096 0.87009,-3.0324 1.2812,-4.5625 0.003,-0.01 -0.003,-0.0217 0,-0.0312 1.2381,-4.6101 2.3684,-9.306 3.34372,-14.094 l 0,-0.0312 c 0.3236,-1.5894 0.6112,-3.2044 0.9063,-4.8125 l 0,-0.0312 c 2.0747,-11.318 3.4621,-23.062 4.1562,-35.219 5e-4,-0.0103 -6e-4,-0.0211 0,-0.0312 0.098,-1.7279 0.1787,-3.4757 0.25,-5.2188 4e-4,-0.0103 -4e-4,-0.0211 0,-0.0312 0.1426,-3.4969 0.2467,-7.0072 0.2812,-10.562 0,-0.0103 -10e-5,-0.0211 0,-0.0312 0.017,-1.783 0.01,-3.578 0,-5.375 0,-0.6358 -0.022,-1.2714 -0.031,-1.9062 0.01,-0.63485 0.031,-1.2704 0.031,-1.9062 0.01,-1.797 0.017,-3.592 0,-5.375 -10e-5,-0.0102 0,-0.0209 0,-0.0312 -0.034,-3.5553 -0.1386,-7.0656 -0.2812,-10.562 -4e-4,-0.0102 4e-4,-0.0209 0,-0.0312 -0.071,-1.7431 -0.152,-3.4908 -0.25,-5.2188 -6e-4,-0.0102 5e-4,-0.0209 0,-0.0312 -0.6941,-12.157 -2.0815,-23.9 -4.1562,-35.219 l 0,-0.0312 c -0.2951,-1.6081 -0.5827,-3.2231 -0.9063,-4.8125 l 0,-0.0312 c -0.97541,-4.7878 -2.10562,-9.4836 -3.34372,-14.094 -0.003,-0.01 0.003,-0.0213 0,-0.0312 -0.41115,-1.5301 -0.84079,-3.0529 -1.2812,-4.5625 -0.003,-0.01 0.003,-0.0213 0,-0.0312 -0.44063,-1.5095 -0.90485,-3.0114 -1.375,-4.5 -0.003,-0.009 0.003,-0.0223 0,-0.0312 -0.47032,-1.4885 -0.96875,-2.9704 -1.4687,-4.4375 -0.50017,-1.467 -1.0325,-2.9298 -1.5625,-4.375 -0.003,-0.009 0.003,-0.0223 0,-0.0312 -0.53021,-1.4451 -1.0648,-2.8896 -1.625,-4.3125 -0.004,-0.009 0.004,-0.0223 0,-0.0312 -1.1244,-2.8546 -2.3161,-5.6438 -3.5625,-8.4062 -0.004,-0.008 0.004,-0.0223 0,-0.0312 -0.62148,-1.3768 -1.2854,-2.7405 -1.9375,-4.0938 -0.004,-0.008 0.004,-0.0233 0,-0.0312 -0.65224,-1.3532 -1.317,-2.7021 -2,-4.0312 -0.004,-0.008 0.004,-0.0233 0,-0.0312 -2.0582,-4.0038 -4.2844,-7.8782 -6.6249,-11.656 -0.005,-0.007 0.005,-0.0233 0,-0.0312 -0.77733,-1.2543 -1.5974,-2.4902 -2.4062,-3.7188 -0.005,-0.007 0.005,-0.0242 0,-0.0312 -2.4367,-3.6999 -5.0243,-7.2606 -7.7499,-10.719 -0.005,-0.006 0.005,-0.0253 0,-0.0312 -0.90549,-1.1485 -1.8435,-2.2853 -2.7812,-3.4062 -0.005,-0.006 0.005,-0.0253 0,-0.0312 -0.93801,-1.1209 -1.9045,-2.2196 -2.875,-3.3125 -0.005,-0.006 0.005,-0.0253 0,-0.0312 -3.8983,-4.3889 -8.0712,-8.5493 -12.5,-12.469 -5.543,-4.9058 -11.512,-9.4112 -17.906,-13.531 -1.2789,-0.82402 -2.5615,-1.6462 -3.875,-2.4375 -2.6269,-1.5825 -5.3273,-3.1137 -8.0937,-4.5625 -1.3832,-0.72439 -2.8004,-1.4347 -4.2187,-2.125 -2.8367,-1.3806 -5.7403,-2.6961 -8.7186,-3.9375 -1.4892,-0.62071 -3.0064,-1.196 -4.5312,-1.7812 -4.5746,-1.7558 -9.2883,-3.3525 -14.187,-4.7812 -1.633,-0.47626 -3.2993,-0.93597 -4.9687,-1.375 -6.6777,-1.7561 -13.638,-3.2325 -20.906,-4.375 -3.6338,-0.57126 -7.3414,-1.0562 -11.125,-1.4688 -9.4586,-1.0326 -19.371,-1.5638 -29.781,-1.5638 -7.0204,0 -13.652,-0.0741 -20,0 -3.1738,0.0372 -6.2554,0.11006 -9.3124,0.25 -1.5285,0.0699 -3.0568,0.1439 -4.5624,0.25 -3.0115,0.21237 -5.9912,0.50693 -8.9374,0.90625 -5.1556,0.69849 -10.244,1.7425 -15.344,3.25 -1.4572,0.43076 -2.9127,0.89366 -4.375,1.4062 -2.9327,1.028 -5.8645,2.2255 -8.8436,3.625 -0.74267,0.34864 -1.4718,0.71985 -2.2187,1.0938 l -109.94,0.25 -12.156,-31.312 c -0.35644,-0.83 -0.84393,-1.5834 -1.4687,-2.2812 -0.01,-0.0105 -0.0213,-0.0206 -0.0312,-0.0312 -1.247,-1.3811 -2.9597,-2.519 -4.7812,-3.3125 -0.61146,-0.26594 -1.2465,-0.49444 -1.875,-0.6875 -0.30491,-0.0933 -0.6329,-0.1744 -0.93749,-0.25 -0.31402,-0.0777 -0.62685,-0.16025 -0.93754,-0.21875 -0.9324,-0.1759 -1.8389,-0.255 -2.6875,-0.25 z" + inkscape:connector-curvature="0" /> + <path + id="path2853" + style="fill:#c83737;fill-opacity:0.99607999" + d="m 557.583,7 c -1.5086,0.009 -4.7211,0.30611 -6.4687,0.9375 l -3.5,1.5 8.6562,35.844 -124.81,0.28125 c -77.963,0.1654 -166.52,-11.504 -232.93,-9.5 -66.412,2.0037 -152.12,28 -152.12,28 l -13.687,3.7812 c -19.251,5.2963 -25.718,97.367 -25.718,166.78 0,1.113 0.02665,2.2531 0.03125,3.375 -0.0046,1.1219 -0.03125,2.262 -0.03125,3.375 0,69.414 6.4673,161.48 25.718,166.78 l 13.687,3.7812 c 0,0 85.711,25.996 152.12,28 66.412,2.0037 154.97,-9.6654 232.93,-9.5 l 124.81,0.28125 -8.6562,35.844 3.5,1.5 c 1.7476,0.63139 4.96,0.92854 6.4687,0.9375 0.84859,0.005 1.7551,-0.0744 2.6875,-0.25 0.3107,-0.0584 0.62352,-0.14119 0.93749,-0.21875 0.30459,-0.0754 0.63259,-0.15686 0.93749,-0.25 0.62844,-0.19269 1.2635,-0.42206 1.875,-0.6875 1.8215,-0.79201 3.5342,-1.9028 4.7812,-3.2812 0.01,-0.0107 0.0217,-0.0208 0.0312,-0.0312 0.6248,-0.69658 1.1123,-1.4528 1.4687,-2.2812 l 12.156,-31.25 109.94,0.25 c 23.9,11.942 45.511,10.719 73.593,10.719 133.25,0 187.63002,-86.586 187.00002,-201.38 0,-0.7802 -0.019,-1.5656 -0.031,-2.3438 0.012,-0.77811 0.031,-1.5636 0.031,-2.3438 0.6282,-114.79 -53.74902,-201.38 -187.00002,-201.38 -28.082,0 -49.693,-1.2236 -73.593,10.719 l -109.94,0.25 -12.156,-31.25 c -0.35645,-0.82844 -0.84393,-1.5847 -1.4687,-2.2812 -0.01,-0.0104 -0.0213,-0.0206 -0.0312,-0.0312 -1.247,-1.3785 -2.9597,-2.4892 -4.7812,-3.2812 -0.61148,-0.26544 -1.2465,-0.49481 -1.875,-0.6875 -0.3049,-0.0931 -0.6329,-0.1746 -0.93749,-0.25 C 560.89402,7.37975 560.5812,7.297 560.2705,7.2386 559.33811,7.063 558.4316,6.9836 557.583,6.9886 Z" + inkscape:connector-curvature="0" /> + <path + id="path3643" + style="opacity:0.9;fill:#262626;fill-opacity:0.99607999" + d="m 347.403,368.55 c -33.364,0 -65.307,1.8 -94.811,5.0625 25.66,48.714 97.985,30.265 205.56,31.531 49.686,0.58471 89.543,1.8793 121.53,2.375 -47.16,-23.334 -133.53,-38.969 -232.28,-38.969 z" + inkscape:connector-curvature="0" /> + <path + id="path3658" + style="opacity:0.5;fill-opacity:0.99607999" + d="m 347.403,368.55 c -3.2064,0 -6.3831,0.0295 -9.5624,0.0625 0.81825,16.171 6.4281,30.257 14.594,38.844 4.6714,-0.0756 9.4951,-0.19655 14.437,-0.34375 -8.5657,-8.1923 -14.593,-22.228 -15.719,-38.562 -1.2512,-0.005 -2.4947,0 -3.75,0 z" + inkscape:connector-curvature="0" /> + <path + id="path3707" + style="color:#000000;text-indent:0;text-transform:none;block-progression:tb;fill:#212121;stroke:#191919;stroke-width:5" + d="m 936.083,340.81 -5.0937,0.59375 c -21.545,2.5127 -37.688,25.979 -39.281,54.531 l -0.37499,7.125 5.2499,-4.8438 c 15.889,-14.68 28.303,-32.507 37.406,-52.75 l 2.09,-4.65 z" + inkscape:connector-curvature="0" /> + <path + id="path3715" + style="opacity:0.5;fill:none;stroke:#292929;stroke-width:6;stroke-linecap:round;stroke-linejoin:round" + d="m 730.533,351.81 c 0,0 79.677,-22.596 105.38,-31.982 26.839,-9.8018 98.859,-39.146 98.859,-39.146 0,0 -8.7409,42.47 -30.483,57.918 -77.23,54.87 -232.69,53.85 -232.69,53.85" + inkscape:connector-curvature="0" /> + <path + id="path3757" + style="fill:url(#linearGradient4149)" + d="m 817.033,331.15 -4.4374,2.3438 c 0.98912,1.1568 1.7955,2.4286 2.375,3.8438 4.7979,11.717 -10.736,29.236 -26.875,35.781 -0.51675,0.20958 -1.8129,0.84066 -3.4062,1.6562 l 13.625,-3.875 c 17.306,-8.4576 27.47,-23.082 23,-34 -0.91615,-2.2373 -2.3752,-4.1661 -4.2812,-5.75 z" + inkscape:connector-curvature="0" /> + <path + id="path3787" + style="fill:url(#linearGradient4203)" + d="m 825.613,326.69 -4.4375,2.3438 c 0.98913,1.1568 1.7955,2.4286 2.375,3.8438 4.7979,11.717 -10.736,29.236 -26.875,35.781 -0.51676,0.20958 -1.8129,0.84066 -3.4062,1.6562 l 13.625,-3.875 c 17.306,-8.4576 27.47,-23.082 23,-34 -0.91615,-2.2373 -2.3752,-4.1661 -4.2812,-5.75 z" + inkscape:connector-curvature="0" /> + <path + id="path3752" + style="fill:url(#linearGradient4155)" + d="m 831.803,325.27 -4.4374,2.3438 c 0.98913,1.1568 1.7955,2.4286 2.375,3.8438 4.7979,11.717 -10.736,29.236 -26.875,35.781 -0.51675,0.20958 -1.8129,0.84066 -3.4062,1.6562 l 13.625,-3.875 c 17.306,-8.4576 27.47,-23.082 23,-34 -0.91615,-2.2373 -2.3752,-4.1661 -4.2812,-5.75 z" + inkscape:connector-curvature="0" /> + <path + id="path3735" + style="fill:url(#linearGradient4205)" + d="m 848.713,321 -6.1874,1.8438 c 0.96015,1.7128 1.6545,3.5323 2.0312,5.4688 3.1194,16.034 -20.962,34.284 -43.031,38.5 -3.395,0.64864 -28.884,8.576 -32.158,8.8044 l 0,4.125 41.439,-12.148 c 26.285,-5.4963 44.949,-22.448 41.875,-38.25 -0.59564,-3.0616 -1.956,-5.8595 -3.9687,-8.3438 z" + inkscape:connector-curvature="0" /> + <path + id="path3783" + style="fill:url(#linearGradient4207)" + d="m 848.713,321 -6.1874,1.8438 c 0.96015,1.7128 1.6545,3.5323 2.0312,5.4688 3.1194,16.034 -20.962,34.284 -43.031,38.5 -3.395,0.64864 -28.884,8.576 -32.158,8.8044 l 0,4.125 41.439,-12.148 c 26.285,-5.4963 44.949,-22.448 41.875,-38.25 -0.59564,-3.0616 -1.956,-5.8595 -3.9687,-8.3438 z" + inkscape:connector-curvature="0" /> + <path + id="path3799" + style="fill:url(#linearGradient4209)" + d="m 804.183,335.77 -3.9641,2.0937 c 0.88361,1.0334 1.604,2.1696 2.1216,3.4337 4.2861,10.467 -9.5906,26.117 -24.008,31.964 -0.46163,0.18723 -1.6195,0.75098 -3.0428,1.4796 l 12.171,-3.4616 c 15.46,-7.5554 24.54,-20.62 20.546,-30.373 -0.81842,-1.9987 -2.1218,-3.7216 -3.8245,-5.1366 z" + inkscape:connector-curvature="0" /> + <path + id="path3803" + style="fill:url(#linearGradient4153)" + d="m 790.383,339.34 -3.9641,2.0937 c 0.88361,1.0334 1.604,2.1696 2.1216,3.4337 4.2861,10.467 -9.5906,26.117 -24.008,31.964 -0.46162,0.18723 -1.6195,0.75098 -3.0428,1.4796 l 12.171,-3.4616 c 15.46,-7.5554 24.54,-20.62 20.546,-30.373 -0.81842,-1.9987 -2.1218,-3.7216 -3.8245,-5.1366 z" + inkscape:connector-curvature="0" /> + <path + id="rect3861" + style="fill:url(#linearGradient4211)" + d="m 180.333,359.03 c 8.293,-2.0234 15.486,-1.4788 19.797,5.7872 l -2.4934,17.897 c -6.8751,6.1732 -13.75,4.9509 -20.625,0.15543 l 3.3212,-23.839 z" + inkscape:connector-curvature="0" /> + <path + id="path3864" + style="fill:url(#linearGradient4213)" + d="m 200.603,362.3 c 8.1502,-1.2102 15.167,-0.5728 18.843,5.5081 l -2.3731,17.034 c -6.4839,2.9748 -12.983,5.2096 -19.631,0.14793 l 3.1611,-22.69 z" + inkscape:connector-curvature="0" /> + <path + id="path4025" + style="color:#000000;text-indent:0;text-transform:none;block-progression:tb;opacity:0.9;fill:#191919" + d="m 347.403,366.06 c -33.454,0 -65.492,1.7894 -95.093,5.0625 l -3.6562,0.40625 1.7187,3.25 c 6.6711,12.664 16.562,21.113 29.062,26.438 12.501,5.3241 27.572,7.6126 45.093,8.4375 35.042,1.6498 79.954,-2.6312 133.59,-2 49.659,0.58438 89.508,1.8787 121.53,2.375 l 1.125,-4.75 c -47.84,-23.68 -134.34,-39.22 -233.36,-39.22 z m 0,5 c 91.169,0 171.75,13.479 220.09,33.719 -29.952,-0.58241 -65.212,-1.606 -109.31,-2.125 -53.937,-0.63473 -98.976,3.6522 -133.4,2.0312 -17.214,-0.81046 -31.767,-3.1054 -43.406,-8.0625 -10.453,-4.4521 -18.485,-11.154 -24.5,-20.906 28.307,-2.9831 58.735,-4.6562 90.53,-4.6562 z" + inkscape:connector-curvature="0" /> + <path + id="rect2864" + style="opacity:0.9;fill:#262626;fill-opacity:0.99607999;stroke:#191919;stroke-width:5" + d="m 207.563,120.69 -77.749,12.469 c -27.15,4.3542 -48.947,48.773 -50.999,104.84 2.0523,56.071 23.849,100.49 50.999,104.84 l 77.749,12.469 c 13.296,0 24,-10.704 24,-24 l 0,-186.62 c 0,-13.296 -10.704,-24 -24,-24 z" + inkscape:connector-curvature="0" /> + <path + id="path3703" + style="opacity:0.9;fill:#262626;fill-opacity:0.99607999;stroke:#191919;stroke-width:5" + d="m 639.023,86.47 c -2.9692,0 -5.8933,0.33215 -8.7812,0.96875 -0.0104,-0.01 -0.0208,-0.021 -0.0312,-0.0312 l -63.843,12.312 c -17.728,6.6047 -32,14.272 -32,32 l 0,212.56 c 0,17.728 14.272,25.395 32,32 l 63.843,12.312 c 0.0105,-0.0102 0.0208,-0.0211 0.0312,-0.0312 2.8879,0.6366 5.812,0.96875 8.7812,0.96875 45.395,0 82.198,-57.363 82.312,-151.53 -0.11408,-94.169 -36.916,-151.53 -82.312,-151.53 z" + inkscape:connector-curvature="0" /> + <path + id="path4157" + style="opacity:0.9;fill:#262626;fill-opacity:0.99607999" + d="m 347.403,107.46 c -33.364,0 -65.307,-1.8 -94.811,-5.0625 25.66,-48.714 97.985,-30.265 205.56,-31.531 49.686,-0.58471 89.543,-1.8793 121.53,-2.375 -47.16,23.334 -133.53,38.969 -232.28,38.969 z" + inkscape:connector-curvature="0" /> + <path + id="path4159" + style="opacity:0.5;fill-opacity:0.99607999" + d="m 347.403,107.46 c -3.2064,0 -6.3831,-0.0295 -9.5624,-0.0625 0.81825,-16.171 6.4281,-30.257 14.594,-38.844 4.6714,0.0756 9.4951,0.19655 14.437,0.34375 -8.5657,8.1923 -14.593,22.228 -15.719,38.562 -1.2512,0.005 -2.4947,0 -3.75,0 z" + inkscape:connector-curvature="0" /> + <path + id="path4161" + style="color:#000000;text-indent:0;text-transform:none;block-progression:tb;fill:#212121;stroke:#191919;stroke-width:5" + d="m 936.083,135.2 -5.0937,-0.59375 c -21.545,-2.5127 -37.688,-25.979 -39.281,-54.531 l -0.37499,-7.125 5.2499,4.8438 c 15.889,14.68 28.303,32.507 37.406,52.75 l 2.0937,4.6562 z" + inkscape:connector-curvature="0" /> + <path + id="path4163" + style="opacity:0.5;fill:none;stroke:#292929;stroke-width:6;stroke-linecap:round;stroke-linejoin:round" + d="m 730.533,124.2 c 0,0 79.677,22.596 105.38,31.982 26.839,9.8018 98.859,39.146 98.859,39.146 0,0 -8.7409,-42.47 -30.483,-57.918 -77.23,-54.87 -232.69,-53.86 -232.69,-53.86" + inkscape:connector-curvature="0" /> + <path + id="path4165" + style="fill:url(#linearGradient4185)" + d="m 817.033,144.86 -4.4374,-2.3438 c 0.98912,-1.1568 1.7955,-2.4286 2.375,-3.8438 4.7979,-11.717 -10.736,-29.236 -26.875,-35.781 -0.51675,-0.20958 -1.8129,-0.84066 -3.4062,-1.6562 l 13.625,3.875 c 17.306,8.4576 27.47,23.082 23,34 -0.91615,2.2373 -2.3752,4.1661 -4.2812,5.75 z" + inkscape:connector-curvature="0" /> + <path + id="path4167" + style="fill:url(#linearGradient4187)" + d="m 825.613,149.32 -4.4375,-2.3438 c 0.98913,-1.1568 1.7955,-2.4286 2.375,-3.8438 4.7979,-11.717 -10.736,-29.236 -26.875,-35.781 -0.51676,-0.20958 -1.8129,-0.84066 -3.4062,-1.6562 l 13.625,3.875 c 17.306,8.4576 27.47,23.082 23,34 -0.91615,2.2373 -2.3752,4.1661 -4.2812,5.75 z" + inkscape:connector-curvature="0" /> + <path + id="path4169" + style="fill:url(#linearGradient4189)" + d="m 831.803,150.73 -4.4374,-2.3438 c 0.98913,-1.1568 1.7955,-2.4286 2.375,-3.8438 4.7979,-11.717 -10.736,-29.236 -26.875,-35.781 -0.51675,-0.20958 -1.8129,-0.84066 -3.4062,-1.6562 l 13.625,3.875 c 17.306,8.4576 27.47,23.082 23,34 -0.91615,2.2373 -2.3752,4.1661 -4.2812,5.75 z" + inkscape:connector-curvature="0" /> + <path + id="path4171" + style="fill:url(#linearGradient4191)" + d="m 848.713,155.01 -6.1874,-1.8438 c 0.96015,-1.7128 1.6545,-3.5323 2.0312,-5.4688 3.1194,-16.034 -20.962,-34.284 -43.031,-38.5 -3.395,-0.64864 -28.884,-8.576 -32.158,-8.8044 l 0,-4.125 41.439,12.148 c 26.285,5.4963 44.949,22.448 41.875,38.25 -0.59564,3.0616 -1.956,5.8595 -3.9687,8.3438 z" + inkscape:connector-curvature="0" /> + <path + id="path4173" + style="fill:url(#linearGradient4193)" + d="m 848.713,155.01 -6.1874,-1.8438 c 0.96015,-1.7128 1.6545,-3.5323 2.0312,-5.4688 3.1194,-16.034 -20.962,-34.284 -43.031,-38.5 -3.395,-0.64864 -28.884,-8.576 -32.158,-8.8044 l 0,-4.125 41.439,12.148 c 26.285,5.4963 44.949,22.448 41.875,38.25 -0.59564,3.0616 -1.956,5.8595 -3.9687,8.3438 z" + inkscape:connector-curvature="0" /> + <path + id="path4175" + style="fill:url(#linearGradient4195)" + d="m 804.183,140.24 -3.9641,-2.0937 c 0.88361,-1.0334 1.604,-2.1696 2.1216,-3.4337 4.2861,-10.467 -9.5906,-26.117 -24.008,-31.964 -0.46163,-0.18723 -1.6195,-0.75098 -3.0428,-1.4796 l 12.171,3.4616 c 15.46,7.5554 24.54,20.62 20.546,30.373 -0.81842,1.9987 -2.1218,3.7216 -3.8245,5.1366 z" + inkscape:connector-curvature="0" /> + <path + id="path4177" + style="fill:url(#linearGradient4197)" + d="m 790.383,136.67 -3.9641,-2.0937 c 0.88361,-1.0334 1.604,-2.1696 2.1216,-3.4337 4.2861,-10.467 -9.5906,-26.117 -24.008,-31.964 -0.46162,-0.18723 -1.6195,-0.75098 -3.0428,-1.4796 l 12.171,3.4616 c 15.46,7.5554 24.54,20.62 20.546,30.373 -0.81842,1.9987 -2.1218,3.7216 -3.8245,5.1366 z" + inkscape:connector-curvature="0" /> + <path + id="path4179" + style="fill:url(#linearGradient4199)" + d="m 180.333,116.97 c 8.293,2.0234 15.486,1.4788 19.797,-5.7872 l -2.4934,-17.897 c -6.8751,-6.1732 -13.75,-4.9509 -20.625,-0.15543 l 3.3212,23.839 z" + inkscape:connector-curvature="0" /> + <path + id="path4181" + style="fill:url(#linearGradient4201)" + d="m 200.603,113.71 c 8.1502,1.2102 15.167,0.5728 18.843,-5.5081 l -2.3731,-17.034 c -6.4839,-2.9748 -12.983,-5.2096 -19.631,-0.14793 l 3.1611,22.69 z" + inkscape:connector-curvature="0" /> + <path + id="path4183" + style="color:#000000;text-indent:0;text-transform:none;block-progression:tb;opacity:0.9;fill:#191919" + d="m 347.403,109.95 c -33.454,0 -65.492,-1.7894 -95.093,-5.0625 l -3.6562,-0.40625 1.7187,-3.25 c 6.6711,-12.664 16.562,-21.113 29.062,-26.438 12.501,-5.3241 27.572,-7.6126 45.093,-8.4375 35.042,-1.6498 79.954,2.6312 133.59,2 49.659,-0.58438 89.508,-1.8787 121.53,-2.375 l 1.125,4.75 c -47.849,23.675 -134.36,39.219 -233.37,39.219 z m 0,-5 c 91.169,0 171.75,-13.479 220.09,-33.719 -29.952,0.58241 -65.212,1.606 -109.31,2.125 -53.937,0.63473 -98.976,-3.6522 -133.4,-2.0312 -17.214,0.81046 -31.767,3.1054 -43.406,8.0625 -10.453,4.4521 -18.485,11.154 -24.5,20.906 28.307,2.9831 58.735,4.6562 90.53,4.6562 z" + inkscape:connector-curvature="0" /> + <metadata + id="metadata60"> + <rdf:RDF> + <cc:Work> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <cc:license + rdf:resource="http://creativecommons.org/licenses/publicdomain/" /> + <dc:publisher> + <cc:Agent + rdf:about="http://openclipart.org/"> + <dc:title>Openclipart</dc:title> + </cc:Agent> + </dc:publisher> + <dc:title>Red Car - Top View</dc:title> + </cc:Work> + <cc:License + rdf:about="http://creativecommons.org/licenses/publicdomain/"> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Reproduction" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#Distribution" /> + <cc:permits + rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /> + </cc:License> + </rdf:RDF> + </metadata> +</svg> diff --git a/env/simple_intersection/graphics/other_vehicle.svg b/env/simple_intersection/graphics/other_vehicle.svg new file mode 100644 index 0000000000000000000000000000000000000000..6f3b23bffa6c2fafa58da17c130732eea890df7b --- /dev/null +++ b/env/simple_intersection/graphics/other_vehicle.svg @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:ns1="http://sozi.baierouge.fr" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" id="svg2" version="1.1" viewBox="0 0 960 476" inkscape:version="0.91 r13725"> + <title id="title3968">Red Car - Top View</title> + <defs id="defs4"> + <linearGradient id="linearGradient3759"> + <stop id="stop3761" style="stop-color:#1a1a1a" offset="0"/> + <stop id="stop3763" style="stop-color:#000000;stop-opacity:0" offset="1"/> + </linearGradient> + <linearGradient id="linearGradient4149" y2="834.68" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="848.16" gradientTransform="translate(8.3085,-2.6518)" y1="842.3" x1="871.33"/> + <linearGradient id="linearGradient4153" y2="533.5" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="812.14" gradientTransform="matrix(.89332 0 0 .89332 80.349 365.15)" y1="537.5" x1="879.9"/> + <linearGradient id="linearGradient4155" y2="531.91" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="815.82" gradientTransform="translate(27.625,296.49)" y1="537.5" x1="879.9"/> + <linearGradient id="linearGradient4185" y2="834.68" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="848.16" gradientTransform="matrix(1,0,0,-1,8.3085,1452)" y1="842.3" x1="871.33"/> + <linearGradient id="linearGradient4187" y2="528.42" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="876.14" gradientTransform="matrix(1,0,0,-1,21.438,1151.5)" y1="528.36" x1="887.9"/> + <linearGradient id="linearGradient4189" y2="531.91" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="815.82" gradientTransform="matrix(1,0,0,-1,27.625,1152.9)" y1="537.5" x1="879.9"/> + <linearGradient id="linearGradient4191" y2="535.37" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="883.76" gradientTransform="matrix(1,0,0,-1,21.438,1151.5)" y1="542.4" x1="897.22"/> + <linearGradient id="linearGradient4193" y2="501.08" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="835.99" gradientTransform="matrix(1,0,0,-1,21.438,1151.5)" y1="552.05" x1="880.71"/> + <linearGradient id="linearGradient4195" y2="529.61" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="805.29" gradientTransform="matrix(.89332 0 0 -.89332 94.156 1087.8)" y1="528.36" x1="887.9"/> + <linearGradient id="linearGradient4197" y2="533.5" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="812.14" gradientTransform="matrix(.89332 0 0 -.89332 80.349 1084.2)" y1="537.5" x1="879.9"/> + <linearGradient id="linearGradient4199" y2="867.68" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="205.59" gradientTransform="matrix(.99043 -.13799 -.13799 -.99043 146.05 1483.3)" y1="873.14" x1="229.7"/> + <linearGradient id="linearGradient4201" y2="872.65" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="216.56" gradientTransform="matrix(.99043 -.13799 -.13799 -.99043 156.31 1482)" y1="873.06" x1="238.83"/> + <linearGradient id="linearGradient4203" y2="528.42" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="876.14" gradientTransform="translate(21.438,297.91)" y1="528.36" x1="887.9"/> + <linearGradient id="linearGradient4205" y2="535.37" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="883.76" gradientTransform="translate(21.438,297.91)" y1="542.4" x1="897.22"/> + <linearGradient id="linearGradient4207" y2="501.08" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="835.99" gradientTransform="translate(21.438,297.91)" y1="552.05" x1="880.71"/> + <linearGradient id="linearGradient4209" y2="529.61" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="805.29" gradientTransform="matrix(.89332 0 0 .89332 94.156 361.57)" y1="528.36" x1="887.9"/> + <linearGradient id="linearGradient4211" y2="867.68" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="205.59" gradientTransform="matrix(.99043 .13799 -.13799 .99043 146.05 -33.885)" y1="873.14" x1="229.7"/> + <linearGradient id="linearGradient4213" y2="872.65" xlink:href="#linearGradient3759" gradientUnits="userSpaceOnUse" x2="216.56" gradientTransform="matrix(.99043 .13799 -.13799 .99043 156.31 -32.603)" y1="873.06" x1="238.83"/> + </defs> + <g id="layer1" transform="translate(-52.937,-486.69)"> + <g id="g3890"> + <path id="path3855" style="stroke:#191919;stroke-width:14;fill-opacity:.99608" d="m610.52 493.69c-1.5086 0.009-4.7211 0.30491-6.4687 0.9375l-3.5 1.5 8.6562 35.938-124.81 0.28125c-2.4363 0.005-4.8876-0.014-7.3437-0.0312-4.912-0.0343-9.8649-0.10455-14.844-0.21875-7.2926-0.16728-14.669-0.41288-22.062-0.71875-0.39591-0.0164-0.79137-0.0457-1.1875-0.0625-14.932-0.63018-30.007-1.4917-45.031-2.4375-20.326-1.2827-40.52-2.7074-60.124-3.875-14.528-0.8653-28.732-1.5796-42.375-2-9.3692-0.28873-18.464-0.45655-27.25-0.40625-4.3158 0.0247-8.5678 0.0933-12.719 0.21875-4.1508 0.12546-8.3801 0.3553-12.656 0.65625-2.138 0.15047-4.2778 0.31024-6.4374 0.5-6.4689 0.5684-13.045 1.3214-19.594 2.1875-0.0101 0.001-0.0211-0.001-0.0312 0-4.3725 0.57858-8.7185 1.2255-13.062 1.9062-4.3439 0.68073-8.6734 1.3978-12.937 2.1562-4.2537 0.75662-8.4704 1.5654-12.594 2.375-0.01 0.002-0.0212-0.002-0.0312 0-2.0664 0.40586-4.0697 0.80417-6.0937 1.2188-6.0614 1.2416-11.934 2.516-17.5 3.7812-0.0101 0.002-0.0211-0.002-0.0312 0-3.7165 0.8449-7.2872 1.6752-10.719 2.5-6.8638 1.6484-13.115 3.2346-18.531 4.6562-8.1236 2.1325-14.382 3.9272-18.094 5-2.4736 0.71578-3.8125 1.125-3.8125 1.125l-13.687 3.75c-0.9024 0.24873-1.7781 0.6929-2.625 1.3125-0.28771 0.2105-0.56234 0.43593-0.84374 0.6875-1.0996 0.9796-2.151 2.2707-3.1562 3.8438-0.0046 0.007 0.0046 0.0243 0 0.0312-0.50036 0.78473-1.0225 1.6405-1.5 2.5625-0.0042 0.008 0.0042 0.0232 0 0.0312-0.47757 0.9237-0.95114 1.9142-1.4062 2.9688-0.0037 0.009 0.0037 0.0222 0 0.0312-3.667 8.5095-6.62 21.131-8.9374 36.219-0.0015 0.01 0.0015 0.0212 0 0.0312-0.03595 0.23416-0.0581 0.48342-0.09375 0.71875-0.50462 3.3315-0.99204 6.7982-1.4375 10.344-0.03048 0.24265-0.06355 0.47519-0.09375 0.71875-0.50157 4.0432-0.94672 8.2025-1.375 12.469-0.001 0.01 0.000999 0.0211 0 0.0312-0.21354 2.1284-0.42912 4.2948-0.62499 6.4688-0.000921 0.01 0.000921 0.0209 0 0.0312-0.19581 2.1743-0.38397 4.3492-0.56249 6.5625-0.000826 0.01 0.000825 0.0209 0 0.0312-0.35775 4.4376-0.67817 8.9458-0.96874 13.5-0.000656 0.0101 0.000655 0.0209 0 0.0312-0.8726 13.684-1.4596 27.789-1.7812 41.562-0.000245 0.0104 0.000244 0.0207 0 0.0312-0.21443 9.1894-0.3126 18.213-0.3126 26.907 0 0.96763 0.02755 1.9629 0.03125 2.9375-0.0037 0.97462-0.03125 1.9699-0.03125 2.9375 0 8.6932 0.09816 17.717 0.3125 26.906 0.000244 0.0105-0.000245 0.0208 0 0.0312 0.32165 13.774 0.90864 27.878 1.7812 41.562 0.000655 0.0103-0.000656 0.0211 0 0.0312 0.29057 4.5542 0.61099 9.0624 0.96874 13.5 0.000825 0.0103-0.000826 0.0211 0 0.0312 0.17852 2.2133 0.36668 4.3882 0.56249 6.5625 0.000921 0.0103-0.000921 0.0211 0 0.0312 0.19588 2.174 0.41145 4.3404 0.62499 6.4688 0.000999 0.0102-0.001 0.0211 0 0.0312 0.42826 4.2663 0.87342 8.4256 1.375 12.469 0.0302 0.24356 0.06327 0.4761 0.09375 0.71875 0.44545 3.5456 0.93287 7.0123 1.4375 10.344 0.03565 0.23533 0.0578 0.48459 0.09375 0.71875 0.0015 0.01-0.0015 0.0215 0 0.0312 2.3174 15.087 5.2704 27.709 8.9374 36.219 0.0037 0.009-0.0037 0.0226 0 0.0312 0.45509 1.0546 0.92866 2.045 1.4062 2.9688 0.0042 0.008-0.0042 0.0231 0 0.0312 0.47753 0.92204 0.99962 1.7778 1.5 2.5625 0.0046 0.007-0.0046 0.0242 0 0.0312 1.0052 1.5731 2.0566 2.8642 3.1562 3.8438 0.2814 0.25157 0.55603 0.477 0.84374 0.6875 0.84686 0.6196 1.7226 1.0638 2.625 1.3125l13.687 3.75s1.3388 0.40922 3.8125 1.125c3.7111 1.0728 9.97 2.8675 18.094 5 5.4157 1.4217 11.667 3.0078 18.531 4.6562 3.4314 0.82484 7.0022 1.6551 10.719 2.5 0.0102 0.002 0.0211-0.002 0.0312 0 5.5661 1.2652 11.438 2.5396 17.5 3.7812 2.024 0.41458 4.0273 0.81289 6.0937 1.2188 0.0101 0.002 0.0212-0.002 0.0312 0 4.1232 0.80965 8.3399 1.6184 12.594 2.375 4.264 0.75843 8.5935 1.4755 12.937 2.1562 4.3439 0.68073 8.6898 1.3277 13.062 1.9062 0.0102 0.001 0.0211-0.001 0.0312 0 6.5486 0.86611 13.125 1.6191 19.594 2.1875 2.1597 0.18976 4.2994 0.34953 6.4374 0.5 4.276 0.30095 8.5053 0.53079 12.656 0.65625 4.1508 0.12546 8.4028 0.19403 12.719 0.21875 8.7859 0.0503 17.881-0.11752 27.25-0.40625 13.642-0.42043 27.847-1.1347 42.375-2 19.604-1.1676 39.798-2.5923 60.124-3.875 15.024-0.94578 30.098-1.8073 45.031-2.4375 0.39612-0.0168 0.79158-0.0461 1.1875-0.0625 7.3934-0.30587 14.77-0.55147 22.062-0.71875 4.9787-0.1142 9.9316-0.18447 14.844-0.21875 2.456-0.0172 4.9073-0.0365 7.3437-0.0312l124.81 0.28125-8.6562 35.938 3.5 1.5c1.7476 0.63259 4.9601 0.92851 6.4687 0.9375 0.8486 0.005 1.7551-0.0741 2.6875-0.25 0.31069-0.0585 0.62352-0.14105 0.93749-0.21875 0.30459-0.0756 0.63258-0.15668 0.93749-0.25 0.62844-0.19306 1.2635-0.42156 1.875-0.6875 1.8215-0.79351 3.5342-1.9314 4.7812-3.3125 0.01-0.0107 0.0217-0.0206 0.0312-0.0312 0.6248-0.6979 1.1123-1.4512 1.4687-2.2812l12.156-31.312 109.94 0.25c0.7469 0.3739 1.4761 0.74511 2.2187 1.0938 2.9792 1.3995 5.911 2.597 8.8436 3.625 1.4623 0.51259 2.9178 0.97549 4.375 1.4062 5.1 1.5075 10.188 2.5515 15.344 3.25 2.9462 0.39932 5.9259 0.69388 8.9374 0.90625 1.5057 0.1061 3.034 0.18011 4.5624 0.25 3.057 0.13994 6.1386 0.21283 9.3124 0.25 6.3475 0.0741 12.979 0 20 0 10.41 0 20.322-0.53122 29.781-1.5625 3.7835-0.41251 7.4911-0.89749 11.125-1.4688 7.2676-1.1425 14.228-2.6189 20.906-4.375 1.6694-0.43903 3.3357-0.89874 4.9687-1.375 4.899-1.4288 9.6128-3.0254 14.187-4.7812 1.5248-0.58527 3.042-1.1605 4.5312-1.7812 2.9783-1.2414 5.882-2.557 8.7186-3.9375 1.4183-0.69027 2.8355-1.4006 4.2187-2.125 2.7664-1.4488 5.4668-2.98 8.0937-4.5625 1.3135-0.79125 2.5961-1.6135 3.875-2.4375 6.3943-4.1201 12.363-8.6255 17.906-13.531 4.4286-3.9195 8.6015-8.0798 12.5-12.469 0.005-0.006-0.005-0.0254 0-0.0312 0.97044-1.0929 1.937-2.1916 2.875-3.3125 0.005-0.006-0.005-0.0251 0-0.0312 0.93773-1.1209 1.8757-2.2578 2.7812-3.4062 0.005-0.006-0.005-0.0249 0-0.0312 2.7256-3.4582 5.3132-7.0189 7.7499-10.719 0.005-0.007-0.005-0.024 0-0.0312 0.80882-1.2286 1.6289-2.4644 2.4062-3.7188 0.005-0.008-0.005-0.0238 0-0.0312 2.3405-3.7781 4.5668-7.6525 6.6249-11.656 0.004-0.008-0.004-0.0231 0-0.0312 0.68299-1.3292 1.3477-2.6781 2-4.0312 0.004-0.008-0.004-0.0229 0-0.0312 0.65204-1.3533 1.316-2.7169 1.9375-4.0938 0.004-0.009-0.004-0.0227 0-0.0312 1.2464-2.7625 2.438-5.5517 3.5625-8.4062 0.004-0.009-0.004-0.0224 0-0.0312 0.56023-1.4229 1.0948-2.8674 1.625-4.3125 0.003-0.009-0.003-0.0222 0-0.0312 0.53002-1.4452 1.0623-2.908 1.5625-4.375 0.49999-1.4671 0.99842-2.949 1.4687-4.4375 0.003-0.009-0.003-0.022 0-0.0312 0.47013-1.4886 0.93435-2.9905 1.375-4.5 0.003-0.01-0.003-0.0217 0-0.0312 0.44045-1.5096 0.87009-3.0324 1.2812-4.5625 0.003-0.01-0.003-0.0217 0-0.0312 1.2381-4.6101 2.3684-9.306 3.3437-14.094v-0.0312c0.3236-1.5894 0.6112-3.2044 0.9063-4.8125v-0.0312c2.0747-11.318 3.4621-23.062 4.1562-35.219 0.0005-0.0103-0.0006-0.0211 0-0.0312 0.098-1.7279 0.1787-3.4757 0.25-5.2188 0.0004-0.0103-0.0004-0.0211 0-0.0312 0.1426-3.4969 0.2467-7.0072 0.2812-10.562 0-0.0103-0.0001-0.0211 0-0.0312 0.017-1.783 0.01-3.578 0-5.375 0-0.6358-0.022-1.2714-0.031-1.9062 0.01-0.63485 0.031-1.2704 0.031-1.9062 0.01-1.797 0.017-3.592 0-5.375-0.0001-0.0102 0-0.0209 0-0.0312-0.034-3.5553-0.1386-7.0656-0.2812-10.562-0.0004-0.0102 0.0004-0.0209 0-0.0312-0.071-1.7431-0.152-3.4908-0.25-5.2188-0.0006-0.0102 0.0005-0.0209 0-0.0312-0.6941-12.157-2.0815-23.9-4.1562-35.219v-0.0312c-0.2951-1.6081-0.5827-3.2231-0.9063-4.8125v-0.0312c-0.97539-4.7878-2.1056-9.4836-3.3437-14.094-0.003-0.01 0.003-0.0213 0-0.0312-0.41115-1.5301-0.84079-3.0529-1.2812-4.5625-0.003-0.01 0.003-0.0213 0-0.0312-0.44063-1.5095-0.90485-3.0114-1.375-4.5-0.003-0.009 0.003-0.0223 0-0.0312-0.47032-1.4885-0.96875-2.9704-1.4687-4.4375-0.50017-1.467-1.0325-2.9298-1.5625-4.375-0.003-0.009 0.003-0.0223 0-0.0312-0.53021-1.4451-1.0648-2.8896-1.625-4.3125-0.004-0.009 0.004-0.0223 0-0.0312-1.1244-2.8546-2.3161-5.6438-3.5625-8.4062-0.004-0.008 0.004-0.0223 0-0.0312-0.62148-1.3768-1.2854-2.7405-1.9375-4.0938-0.004-0.008 0.004-0.0233 0-0.0312-0.65224-1.3532-1.317-2.7021-2-4.0312-0.004-0.008 0.004-0.0233 0-0.0312-2.0582-4.0038-4.2844-7.8782-6.6249-11.656-0.005-0.007 0.005-0.0233 0-0.0312-0.77733-1.2543-1.5974-2.4902-2.4062-3.7188-0.005-0.007 0.005-0.0242 0-0.0312-2.4367-3.6999-5.0243-7.2606-7.7499-10.719-0.005-0.006 0.005-0.0253 0-0.0312-0.90549-1.1485-1.8435-2.2853-2.7812-3.4062-0.005-0.006 0.005-0.0253 0-0.0312-0.93801-1.1209-1.9045-2.2196-2.875-3.3125-0.005-0.006 0.005-0.0253 0-0.0312-3.8983-4.3889-8.0712-8.5493-12.5-12.469-5.543-4.9058-11.512-9.4112-17.906-13.531-1.2789-0.82402-2.5615-1.6462-3.875-2.4375-2.6269-1.5825-5.3273-3.1137-8.0937-4.5625-1.3832-0.72439-2.8004-1.4347-4.2187-2.125-2.8367-1.3806-5.7403-2.6961-8.7186-3.9375-1.4892-0.62071-3.0064-1.196-4.5312-1.7812-4.5746-1.7558-9.2883-3.3525-14.187-4.7812-1.633-0.47626-3.2993-0.93597-4.9687-1.375-6.6777-1.7561-13.638-3.2325-20.906-4.375-3.6338-0.57126-7.3414-1.0562-11.125-1.4688-9.4586-1.0326-19.371-1.5638-29.781-1.5638-7.0204 0-13.652-0.0741-20 0-3.1738 0.0372-6.2554 0.11006-9.3124 0.25-1.5285 0.0699-3.0568 0.1439-4.5624 0.25-3.0115 0.21237-5.9912 0.50693-8.9374 0.90625-5.1556 0.69849-10.244 1.7425-15.344 3.25-1.4572 0.43076-2.9127 0.89366-4.375 1.4062-2.9327 1.028-5.8645 2.2255-8.8436 3.625-0.74267 0.34864-1.4718 0.71985-2.2187 1.0938l-109.94 0.25-12.156-31.312c-0.35644-0.83-0.84393-1.5834-1.4687-2.2812-0.01-0.0105-0.0213-0.0206-0.0312-0.0312-1.247-1.3811-2.9597-2.519-4.7812-3.3125-0.61146-0.26594-1.2465-0.49444-1.875-0.6875-0.30491-0.0933-0.6329-0.1744-0.93749-0.25-0.31402-0.0777-0.62685-0.16025-0.93754-0.21875-0.9324-0.1759-1.8389-0.255-2.6875-0.25z"/> + <path id="path2853" style="fill-opacity:.99608;fill:#32c0ff" d="m610.52 493.69c-1.5086 0.009-4.7211 0.30611-6.4687 0.9375l-3.5 1.5 8.6562 35.844-124.81 0.28125c-77.963 0.1654-166.52-11.504-232.93-9.5-66.412 2.0037-152.12 28-152.12 28l-13.687 3.7812c-19.251 5.2963-25.718 97.367-25.718 166.78 0 1.113 0.02665 2.2531 0.03125 3.375-0.0046 1.1219-0.03125 2.262-0.03125 3.375 0 69.414 6.4673 161.48 25.718 166.78l13.687 3.7812s85.711 25.996 152.12 28c66.412 2.0037 154.97-9.6654 232.93-9.5l124.81 0.28125-8.6562 35.844 3.5 1.5c1.7476 0.63139 4.96 0.92854 6.4687 0.9375 0.84859 0.005 1.7551-0.0744 2.6875-0.25 0.3107-0.0584 0.62352-0.14119 0.93749-0.21875 0.30459-0.0754 0.63259-0.15686 0.93749-0.25 0.62844-0.19269 1.2635-0.42206 1.875-0.6875 1.8215-0.79201 3.5342-1.9028 4.7812-3.2812 0.01-0.0107 0.0217-0.0208 0.0312-0.0312 0.6248-0.69658 1.1123-1.4528 1.4687-2.2812l12.156-31.25 109.94 0.25c23.9 11.942 45.511 10.719 73.593 10.719 133.25 0 187.63-86.586 187-201.38 0-0.7802-0.019-1.5656-0.031-2.3438 0.012-0.77811 0.031-1.5636 0.031-2.3438 0.6282-114.79-53.749-201.38-187-201.38-28.082 0-49.693-1.2236-73.593 10.719l-109.94 0.25-12.156-31.25c-0.35645-0.82844-0.84393-1.5847-1.4687-2.2812-0.01-0.0104-0.0213-0.0206-0.0312-0.0312-1.247-1.3785-2.9597-2.4892-4.7812-3.2812-0.61148-0.26544-1.2465-0.49481-1.875-0.6875-0.3049-0.0931-0.6329-0.1746-0.93749-0.25-0.31397-0.0776-0.62679-0.16035-0.93749-0.21875-0.93239-0.1756-1.8389-0.255-2.6875-0.25z"/> + <path id="path3643" style="opacity:.9;fill-opacity:.99608;fill:#262626" d="m400.34 855.24c-33.364 0-65.307 1.8-94.811 5.0625 25.66 48.714 97.985 30.265 205.56 31.531 49.686 0.58471 89.543 1.8793 121.53 2.375-47.16-23.334-133.53-38.969-232.28-38.969z"/> + <path id="path3658" style="opacity:.5;fill-opacity:.99608" d="m400.34 855.24c-3.2064 0-6.3831 0.0295-9.5624 0.0625 0.81825 16.171 6.4281 30.257 14.594 38.844 4.6714-0.0756 9.4951-0.19655 14.437-0.34375-8.5657-8.1923-14.593-22.228-15.719-38.562-1.2512-0.005-2.4947 0-3.75 0z"/> + <path id="path3707" style="block-progression:tb;text-indent:0;color:#000000;stroke:#191919;stroke-width:5;text-transform:none;fill:#212121" d="m989.02 827.5-5.0937 0.59375c-21.545 2.5127-37.688 25.979-39.281 54.531l-0.37499 7.125 5.2499-4.8438c15.889-14.68 28.303-32.507 37.406-52.75l2.09-4.65z"/> + <path id="path3715" style="opacity:.5;stroke-linejoin:round;stroke:#292929;stroke-linecap:round;stroke-width:6;fill:none" d="m783.47 838.5s79.677-22.596 105.38-31.982c26.839-9.8018 98.859-39.146 98.859-39.146s-8.7409 42.47-30.483 57.918c-77.23 54.87-232.69 53.85-232.69 53.85"/> + <path id="path3757" style="fill:url(#linearGradient4149)" d="m869.97 817.84-4.4374 2.3438c0.98912 1.1568 1.7955 2.4286 2.375 3.8438 4.7979 11.717-10.736 29.236-26.875 35.781-0.51675 0.20958-1.8129 0.84066-3.4062 1.6562l13.625-3.875c17.306-8.4576 27.47-23.082 23-34-0.91615-2.2373-2.3752-4.1661-4.2812-5.75z"/> + <path id="path3787" style="fill:url(#linearGradient4203)" d="m878.55 813.38-4.4375 2.3438c0.98913 1.1568 1.7955 2.4286 2.375 3.8438 4.7979 11.717-10.736 29.236-26.875 35.781-0.51676 0.20958-1.8129 0.84066-3.4062 1.6562l13.625-3.875c17.306-8.4576 27.47-23.082 23-34-0.91615-2.2373-2.3752-4.1661-4.2812-5.75z"/> + <path id="path3752" style="fill:url(#linearGradient4155)" d="m884.74 811.96-4.4374 2.3438c0.98913 1.1568 1.7955 2.4286 2.375 3.8438 4.7979 11.717-10.736 29.236-26.875 35.781-0.51675 0.20958-1.8129 0.84066-3.4062 1.6562l13.625-3.875c17.306-8.4576 27.47-23.082 23-34-0.91615-2.2373-2.3752-4.1661-4.2812-5.75z"/> + <path id="path3735" style="fill:url(#linearGradient4205)" d="m901.65 807.69-6.1874 1.8438c0.96015 1.7128 1.6545 3.5323 2.0312 5.4688 3.1194 16.034-20.962 34.284-43.031 38.5-3.395 0.64864-28.884 8.576-32.158 8.8044v4.125l41.439-12.148c26.285-5.4963 44.949-22.448 41.875-38.25-0.59564-3.0616-1.956-5.8595-3.9687-8.3438z"/> + <path id="path3783" style="fill:url(#linearGradient4207)" d="m901.65 807.69-6.1874 1.8438c0.96015 1.7128 1.6545 3.5323 2.0312 5.4688 3.1194 16.034-20.962 34.284-43.031 38.5-3.395 0.64864-28.884 8.576-32.158 8.8044v4.125l41.439-12.148c26.285-5.4963 44.949-22.448 41.875-38.25-0.59564-3.0616-1.956-5.8595-3.9687-8.3438z"/> + <path id="path3799" style="fill:url(#linearGradient4209)" d="m857.12 822.46-3.9641 2.0937c0.88361 1.0334 1.604 2.1696 2.1216 3.4337 4.2861 10.467-9.5906 26.117-24.008 31.964-0.46163 0.18723-1.6195 0.75098-3.0428 1.4796l12.171-3.4616c15.46-7.5554 24.54-20.62 20.546-30.373-0.81842-1.9987-2.1218-3.7216-3.8245-5.1366z"/> + <path id="path3803" style="fill:url(#linearGradient4153)" d="m843.32 826.03-3.9641 2.0937c0.88361 1.0334 1.604 2.1696 2.1216 3.4337 4.2861 10.467-9.5906 26.117-24.008 31.964-0.46162 0.18723-1.6195 0.75098-3.0428 1.4796l12.171-3.4616c15.46-7.5554 24.54-20.62 20.546-30.373-0.81842-1.9987-2.1218-3.7216-3.8245-5.1366z"/> + <path id="rect3861" style="fill:url(#linearGradient4211)" d="m233.27 845.72c8.293-2.0234 15.486-1.4788 19.797 5.7872l-2.4934 17.897c-6.8751 6.1732-13.75 4.9509-20.625 0.15543l3.3212-23.839z"/> + <path id="path3864" style="fill:url(#linearGradient4213)" d="m253.54 848.99c8.1502-1.2102 15.167-0.5728 18.843 5.5081l-2.3731 17.034c-6.4839 2.9748-12.983 5.2096-19.631 0.14793l3.1611-22.69z"/> + <path id="path4025" style="opacity:.9;block-progression:tb;text-indent:0;color:#000000;text-transform:none;fill:#191919" d="m400.34 852.75c-33.454 0-65.492 1.7894-95.093 5.0625l-3.6562 0.40625 1.7187 3.25c6.6711 12.664 16.562 21.113 29.062 26.438 12.501 5.3241 27.572 7.6126 45.093 8.4375 35.042 1.6498 79.954-2.6312 133.59-2 49.659 0.58438 89.508 1.8787 121.53 2.375l1.125-4.75c-47.84-23.68-134.34-39.22-233.36-39.22zm0 5c91.169 0 171.75 13.479 220.09 33.719-29.952-0.58241-65.212-1.606-109.31-2.125-53.937-0.63473-98.976 3.6522-133.4 2.0312-17.214-0.81046-31.767-3.1054-43.406-8.0625-10.453-4.4521-18.485-11.154-24.5-20.906 28.307-2.9831 58.735-4.6562 90.53-4.6562z"/> + <path id="rect2864" style="opacity:.9;stroke:#191919;stroke-width:5;fill-opacity:.99608;fill:#262626" d="m260.5 607.38-77.749 12.469c-27.15 4.3542-48.947 48.773-50.999 104.84 2.0523 56.071 23.849 100.49 50.999 104.84l77.749 12.469c13.296 0 24-10.704 24-24v-186.62c0-13.296-10.704-24-24-24z"/> + <path id="path3703" style="opacity:.9;stroke:#191919;stroke-width:5;fill-opacity:.99608;fill:#262626" d="m691.96 573.16c-2.9692 0-5.8933 0.33215-8.7812 0.96875-0.0104-0.01-0.0208-0.021-0.0312-0.0312l-63.843 12.312c-17.728 6.6047-32 14.272-32 32v212.56c0 17.728 14.272 25.395 32 32l63.843 12.312c0.0105-0.0102 0.0208-0.0211 0.0312-0.0312 2.8879 0.6366 5.812 0.96875 8.7812 0.96875 45.395 0 82.198-57.363 82.312-151.53-0.11408-94.169-36.916-151.53-82.312-151.53z"/> + <path id="path4157" style="opacity:.9;fill-opacity:.99608;fill:#262626" d="m400.34 594.15c-33.364 0-65.307-1.8-94.811-5.0625 25.66-48.714 97.985-30.265 205.56-31.531 49.686-0.58471 89.543-1.8793 121.53-2.375-47.16 23.334-133.53 38.969-232.28 38.969z"/> + <path id="path4159" style="opacity:.5;fill-opacity:.99608" d="m400.34 594.15c-3.2064 0-6.3831-0.0295-9.5624-0.0625 0.81825-16.171 6.4281-30.257 14.594-38.844 4.6714 0.0756 9.4951 0.19655 14.437 0.34375-8.5657 8.1923-14.593 22.228-15.719 38.562-1.2512 0.005-2.4947 0-3.75 0z"/> + <path id="path4161" style="block-progression:tb;text-indent:0;color:#000000;stroke:#191919;stroke-width:5;text-transform:none;fill:#212121" d="m989.02 621.89-5.0937-0.59375c-21.545-2.5127-37.688-25.979-39.281-54.531l-0.37499-7.125 5.2499 4.8438c15.889 14.68 28.303 32.507 37.406 52.75l2.0937 4.6562z"/> + <path id="path4163" style="opacity:.5;stroke-linejoin:round;stroke:#292929;stroke-linecap:round;stroke-width:6;fill:none" d="m783.47 610.89s79.677 22.596 105.38 31.982c26.839 9.8018 98.859 39.146 98.859 39.146s-8.7409-42.47-30.483-57.918c-77.23-54.87-232.69-53.86-232.69-53.86"/> + <path id="path4165" style="fill:url(#linearGradient4185)" d="m869.97 631.55-4.4374-2.3438c0.98912-1.1568 1.7955-2.4286 2.375-3.8438 4.7979-11.717-10.736-29.236-26.875-35.781-0.51675-0.20958-1.8129-0.84066-3.4062-1.6562l13.625 3.875c17.306 8.4576 27.47 23.082 23 34-0.91615 2.2373-2.3752 4.1661-4.2812 5.75z"/> + <path id="path4167" style="fill:url(#linearGradient4187)" d="m878.55 636.01-4.4375-2.3438c0.98913-1.1568 1.7955-2.4286 2.375-3.8438 4.7979-11.717-10.736-29.236-26.875-35.781-0.51676-0.20958-1.8129-0.84066-3.4062-1.6562l13.625 3.875c17.306 8.4576 27.47 23.082 23 34-0.91615 2.2373-2.3752 4.1661-4.2812 5.75z"/> + <path id="path4169" style="fill:url(#linearGradient4189)" d="m884.74 637.42-4.4374-2.3438c0.98913-1.1568 1.7955-2.4286 2.375-3.8438 4.7979-11.717-10.736-29.236-26.875-35.781-0.51675-0.20958-1.8129-0.84066-3.4062-1.6562l13.625 3.875c17.306 8.4576 27.47 23.082 23 34-0.91615 2.2373-2.3752 4.1661-4.2812 5.75z"/> + <path id="path4171" style="fill:url(#linearGradient4191)" d="m901.65 641.7-6.1874-1.8438c0.96015-1.7128 1.6545-3.5323 2.0312-5.4688 3.1194-16.034-20.962-34.284-43.031-38.5-3.395-0.64864-28.884-8.576-32.158-8.8044v-4.125l41.439 12.148c26.285 5.4963 44.949 22.448 41.875 38.25-0.59564 3.0616-1.956 5.8595-3.9687 8.3438z"/> + <path id="path4173" style="fill:url(#linearGradient4193)" d="m901.65 641.7-6.1874-1.8438c0.96015-1.7128 1.6545-3.5323 2.0312-5.4688 3.1194-16.034-20.962-34.284-43.031-38.5-3.395-0.64864-28.884-8.576-32.158-8.8044v-4.125l41.439 12.148c26.285 5.4963 44.949 22.448 41.875 38.25-0.59564 3.0616-1.956 5.8595-3.9687 8.3438z"/> + <path id="path4175" style="fill:url(#linearGradient4195)" d="m857.12 626.93-3.9641-2.0937c0.88361-1.0334 1.604-2.1696 2.1216-3.4337 4.2861-10.467-9.5906-26.117-24.008-31.964-0.46163-0.18723-1.6195-0.75098-3.0428-1.4796l12.171 3.4616c15.46 7.5554 24.54 20.62 20.546 30.373-0.81842 1.9987-2.1218 3.7216-3.8245 5.1366z"/> + <path id="path4177" style="fill:url(#linearGradient4197)" d="m843.32 623.36-3.9641-2.0937c0.88361-1.0334 1.604-2.1696 2.1216-3.4337 4.2861-10.467-9.5906-26.117-24.008-31.964-0.46162-0.18723-1.6195-0.75098-3.0428-1.4796l12.171 3.4616c15.46 7.5554 24.54 20.62 20.546 30.373-0.81842 1.9987-2.1218 3.7216-3.8245 5.1366z"/> + <path id="path4179" style="fill:url(#linearGradient4199)" d="m233.27 603.66c8.293 2.0234 15.486 1.4788 19.797-5.7872l-2.4934-17.897c-6.8751-6.1732-13.75-4.9509-20.625-0.15543l3.3212 23.839z"/> + <path id="path4181" style="fill:url(#linearGradient4201)" d="m253.54 600.4c8.1502 1.2102 15.167 0.5728 18.843-5.5081l-2.3731-17.034c-6.4839-2.9748-12.983-5.2096-19.631-0.14793l3.1611 22.69z"/> + <path id="path4183" style="opacity:.9;block-progression:tb;text-indent:0;color:#000000;text-transform:none;fill:#191919" d="m400.34 596.64c-33.454 0-65.492-1.7894-95.093-5.0625l-3.6562-0.40625 1.7187-3.25c6.6711-12.664 16.562-21.113 29.062-26.438 12.501-5.3241 27.572-7.6126 45.093-8.4375 35.042-1.6498 79.954 2.6312 133.59 2 49.659-0.58438 89.508-1.8787 121.53-2.375l1.125 4.75c-47.849 23.675-134.36 39.219-233.37 39.219zm0-5c91.169 0 171.75-13.479 220.09-33.719-29.952 0.58241-65.212 1.606-109.31 2.125-53.937 0.63473-98.976-3.6522-133.4-2.0312-17.214 0.81046-31.767 3.1054-43.406 8.0625-10.453 4.4521-18.485 11.154-24.5 20.906 28.307 2.9831 58.735 4.6562 90.53 4.6562z"/> + </g> + </g> + <metadata> + <rdf:RDF> + <cc:Work> + <dc:format>image/svg+xml</dc:format> + <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <cc:license rdf:resource="http://creativecommons.org/licenses/publicdomain/"/> + <dc:publisher> + <cc:Agent rdf:about="http://openclipart.org/"> + <dc:title>Openclipart</dc:title> + </cc:Agent> + </dc:publisher> + </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/publicdomain/"> + <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> + <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> + </cc:License> + </rdf:RDF> + </metadata> +</svg> \ No newline at end of file diff --git a/env/simple_intersection/graphics/road_texture.png b/env/simple_intersection/graphics/road_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..1e15ff6cd9c46cfabd87486faa3f86c87376ef25 Binary files /dev/null and b/env/simple_intersection/graphics/road_texture.png differ diff --git a/env/simple_intersection/road_geokinemetry.py b/env/simple_intersection/road_geokinemetry.py new file mode 100644 index 0000000000000000000000000000000000000000..acb68cd1a69718057fc047e8352abbe1f5bc880e --- /dev/null +++ b/env/simple_intersection/road_geokinemetry.py @@ -0,0 +1,101 @@ +# from constants import VEHICLE_SIZE_HALF + + +class Route(object): + """A class that contains the lane(s) information for each route ('h' for + horizontal or 'v' for vertical). + + The current implementation is tested when the number of lanes is "2". + + Properties: + * direction: 'h' for hlanes or 'v' for vlanes + * n_lanes: the number of lanes (has to be multiples of 2) + * start_pos: the position that the route starts + * end_pos: the position that the route ends + * min_pos: the minimum value of the position on the route + * max_pos: the maximum value of the position on the route + * middle_pos: the center value of the position on the route + * length: the length of the route + * width: the width of each lane + * centres: an array containing each lane's center point + * stop_region: an array defining the stop region on the route + * near_stop_region: the position before stop_region[1] defining + the region near the stop region + * stop_region_centre: the center position of the stop region + * sidewalks: the side walk points of the route + * total_width: the width of the route + * total_centre: the center of the route + """ + + def __init__(self, direction, n_lanes, start_pos, end_pos, width, centres, + stop_region, near_stop_region, sidewalks): + if (direction != 'h') and (direction != 'v'): + raise ValueError("Route.direction has to be either 'h' or 'v'.") + + self.direction = direction + self.n_lanes = n_lanes + self.start_pos = start_pos + self.end_pos = end_pos + self.min_pos = min([start_pos, end_pos]) + self.max_pos = max([start_pos, end_pos]) + self.middle_pos = (start_pos + end_pos) / 2 + self.length = abs(end_pos - start_pos) + self.width = width + self.centres = centres + self.stop_region = stop_region + self.stop_region_centre = (stop_region[0] + stop_region[1]) / 2 + self.stop_region_width = max(stop_region) - min(stop_region) + self.sidewalks = sidewalks + self.total_width = max(sidewalks) - min(sidewalks) + self.total_centre = (sidewalks[0] + sidewalks[1]) / 2 + self.near_stop_region = stop_region[0] - abs(near_stop_region) + + @property + def pos_range(self): + return self.min_pos, self.max_pos + +#: the intersection is posed at (0, 0) in the coordinate. +# The variable "intersection_pos" indicates this position of +# the intersection, but not used at all in the current implementation. +intersection_pos = [0.0, 0.0] + +#: the horizontal offset between the edges of the intersection and +# the end points of the stop regions. +# TODO: Fix the inter-referencing problem between constants.py and road_geokinemetry.py and substitute VEHICLE_SIZE_HALF[0] to 2.5/2.0 +intersection_hoffset = 2.5 / 2.0 + +#: the vertical offset between the edges of the intersection and +# the end points of the stop regions. +# TODO: Fix the inter-referencing problem between constants.py and road_geokinemetry.py and substitute VEHICLE_SIZE_HALF[0] to 2.5/2.0 +intersection_voffset = 2.5 / 2.0 + +#: the speed limit of the road environment. +# This is the only one regarding the road kinemetry. +# 11.176 m/s = 40 km/h +speed_limit = 11.176 + +#: the lanes defined with computer graphics coordinate system +# (i.e., y-axis flipped). The coordination system we consider +# is the same: y-axis flipped. +hwidth = 4.0 +hlanes = Route('h', 2, -75.0, 40.0, hwidth, [-2, 2], + [- hwidth - 5.0 - intersection_hoffset, - hwidth - intersection_hoffset], + 35, [-4.0, 4.0]) + + +#: the lanes defined with computer graphics coordinate system +# (i.e., y-axis flipped). The coordination system we consider +# is the same: y-axis flipped. +vwidth = 4.0 +vlanes = Route('v', 2, -75.0, 15.0, 4.0, [2, -2], + [- vwidth - 5.0 - intersection_voffset, - vwidth - intersection_voffset], + 35, [-4.0, 4.0]) + +intersection_width = vlanes.n_lanes * vlanes.width +intersection_height = hlanes.n_lanes * hlanes.width + +intersection_width_w_offset = intersection_width + 2 * intersection_hoffset +intersection_height_w_offset = intersection_height + 2 * intersection_voffset + +intersection_width_wo_offset = intersection_width +intersection_height_wo_offset = intersection_height \ No newline at end of file diff --git a/env/simple_intersection/road_networks.py b/env/simple_intersection/road_networks.py new file mode 100644 index 0000000000000000000000000000000000000000..5d9b13ee71c7a513ba4dcc5f78f7c38198648058 --- /dev/null +++ b/env/simple_intersection/road_networks.py @@ -0,0 +1,78 @@ +from .constants import * +from .shapes import Shape, Image, Rectangle +from .utilities import road2image, draw_all_shapes +from . import road_geokinemetry as rd + + +class RoadNetworkCross(Shape): + """Road network for the cross scenario. + + This scenario has just one horizontal lane and one vertical lane. + Relevant constants are used from the constants file. + """ + + def __init__(self, image_url): + """Constructor for RoadNetworkCross. + + Args: + image_url: url for the image file, relative to the graphics folder + """ + + self.hlane_sprites, self.vlane_sprites = [], [] + + # Pyglet sprites for drawing horizontal road + for i in range(NUM_HTILES): + road_tile = Image(image_url, tile_scale=True) + self.hlane_sprites.append(road_tile) + road_tile.sprite.set_position( + (i + 0.5) * NUM_HPIXELS / NUM_HTILES, road2image(0, 'v')) + + # Pyglet sprites for drawing vertical road + for j in range(NUM_VTILES): + road_tile = Image(image_url, tile_scale=True) + self.vlane_sprites.append(road_tile) + road_tile.sprite.set_position( + road2image(0, 'h'), (j + 0.5) * NUM_VPIXELS / NUM_VTILES) + + # Draw the lane separators. There should be 4 of them, 2 on the + # horizontal road, 2 on the vertical road. + originx, originy = road2image(0, 'h'), road2image(0, 'v') + hlane_width, vlane_width = LANE_WIDTH, LANE_WIDTH + self.lane_separators = [ + Rectangle(0, originx-vlane_width, + originy - LANE_SEPARATOR_HALF_WIDTH, + originy + LANE_SEPARATOR_HALF_WIDTH, + color=(200, 200, 200, 255)), + Rectangle(originx+vlane_width, NUM_HPIXELS, + originy - LANE_SEPARATOR_HALF_WIDTH, + originy + LANE_SEPARATOR_HALF_WIDTH, + color=(200, 200, 200, 255)), + Rectangle(originx - LANE_SEPARATOR_HALF_WIDTH, + originx + LANE_SEPARATOR_HALF_WIDTH, 0, originy-hlane_width, + color=(200, 200, 200, 255)), + Rectangle(originx - LANE_SEPARATOR_HALF_WIDTH, + originx + LANE_SEPARATOR_HALF_WIDTH, originy+hlane_width, + NUM_VPIXELS, + color=(200, 200, 200, 255)), + ] + + # Draw the stop region + self.stop_regions = [ + Rectangle(road2image(rd.hlanes.stop_region[0], 'h'), + road2image(rd.hlanes.stop_region[1], 'h'), + originy - vlane_width, + originy + vlane_width, + color=(180, 180, 180, 255)), + # Rectangle(originx - hlane_width, + # originx + hlane_width, + # originy + rd.vlanes.stop_region[0] * NUM_VPIXELS / NUM_VTILES, + # originy + rd.vlanes.stop_region[1] * NUM_VPIXELS / NUM_VTILES, + # color=(30, 30, 30, 255)), + ] + + def draw(self): + """Draw the horizontal and vertical lane.""" + draw_all_shapes(self.hlane_sprites) + draw_all_shapes(self.vlane_sprites) + draw_all_shapes(self.lane_separators) + draw_all_shapes(self.stop_regions) \ No newline at end of file diff --git a/env/simple_intersection/shapes.py b/env/simple_intersection/shapes.py new file mode 100644 index 0000000000000000000000000000000000000000..7a93c7f530a5102d592dc6ac2040b0a1e4bf7ada --- /dev/null +++ b/env/simple_intersection/shapes.py @@ -0,0 +1,140 @@ +import pyglet +from pyglet import gl +from .constants import * +# TODO: some of these shapes could be moved to utilities, since these +# are general classes could be used anywhere, not just in env.simple_intersection + + +class Shape: + """Shape abstract class.""" + + +class Rectangle(Shape): + """Rectangle using OpenGL.""" + + def __init__(self, xmin, xmax, ymin, ymax, color=(0, 0, 0, 255)): + """ Constructor for Rectangle. + + The rectangle has the four points (xmin, ymin), (xmin, ymax), + (xmax, ymax), (xmax, ymin). + + Args: + xmin: minimum x coordinate + xmax: maximum x coordinate + ymin: minimum y coordinate + ymax: maximum y coordinate + color: rectangle color + """ + + self.xmin = xmin + self.xmax = xmax + self.ymin = ymin + self.ymax = ymax + self.color = list(map(lambda x: x/255.0, color)) + + def draw(self): + """Draw Rectangle object using OpenGL.""" + gl.glBegin(gl.GL_QUADS) + gl.glColor4f(*self.color) + gl.glVertex3f(self.xmin, self.ymin, 0) + gl.glVertex3f(self.xmin, self.ymax, 0) + gl.glVertex3f(self.xmax, self.ymax, 0) + gl.glVertex3f(self.xmax, self.ymin, 0) + gl.glEnd() + + +class Text(Shape): + """Holds a pyglet label.""" + + def __init__(self, + text, + x, + y, + font_size=12, + color=(0, 0, 0, 255), + multiline=False, + width=None): + """Constructor for Text. + + Args: + text: the text this label contains + x: x position + y: y position in the inverted y frame (computer graphics) + font_size: font size for text + color: RGBA color for text + multiline: whether or not this text is multiline + width: to be set whenever the text is multiline + """ + + if multiline == True and width is None: + width = 300 + self.label = pyglet.text.Label( + text, + font_size=font_size, + color=color, + x=x, + y=y, + multiline=multiline, + width=width) + + def draw(self): + """Draw Text object.""" + + self.label.draw() + + +class Image(Shape): + """Holds an image.""" + + def __init__(self, + image_url, + anchor=None, + tile_scale=False, + image_type=None): + """Constructor for Image. + + Args: + image_url: url for the image file, relative to the graphics folder + anchor: anchor coordinates, if None then by default at the center + tile_scale: if True, then use H_TILE_SCALE and V_TILE_SCALE defined + in the constants + image_type: could be None (simple image), "bg" (background, ordered + group), "car" (represents a car) + """ + + self.image = pyglet.image.load('env/simple_intersection/graphics/' + image_url) + + if anchor is None: + self.image.anchor_x = self.image.width // 2 + self.image.anchor_y = self.image.height // 2 + else: + self.image.anchor_x, self.image.anchor_y = anchor + + self.image_type = image_type + if image_type == "bg": + self.batch = pyglet.graphics.Batch() + self.sprite = pyglet.sprite.Sprite( + self.image, + batch=self.batch, + group=pyglet.graphics.OrderedGroup(0)) + else: + self.sprite = pyglet.sprite.Sprite(self.image) + + if tile_scale == True: + if self.image_type == "car": + self.sprite.update( + scale_x=H_CAR_SCALE(self.image.width), + scale_y=V_CAR_SCALE(self.image.height)) + else: + self.sprite.update( + scale_x=H_TILE_SCALE(self.image.width), + scale_y=V_TILE_SCALE(self.image.height)) + + def draw(self): + """Draw Image object.""" + + if self.sprite is not None: + if self.image_type == "bg": + self.batch.draw() + else: + self.sprite.draw() diff --git a/env/simple_intersection/simple_intersection_env.py b/env/simple_intersection/simple_intersection_env.py new file mode 100644 index 0000000000000000000000000000000000000000..ae3524c378d1c979ddf77547238c0c61da381181 --- /dev/null +++ b/env/simple_intersection/simple_intersection_env.py @@ -0,0 +1,1215 @@ + +import pyglet +import gym +from copy import deepcopy + +from env import RoadEnv, EpisodicEnvBase + +from .vehicles import Vehicle +from .utilities import calculate_s, calculate_v_max +from .utilities import BoundingBox as bb_utils +from .features import Features +from .constants import * + +from model_checker.simple_intersection import LTLProperty + + +# import the classes for graphical output. +from .shapes import Text, Image +from .road_networks import RoadNetworkCross +from .vehicle_networks import VehicleNetworkCross +from .utilities import get_APs, get_veh_attributes, config_Pyglet + + +class SimpleIntersectionEnv(RoadEnv, EpisodicEnvBase): + """Road environment corresponding to the cross scenario. + + This scenario has just one horizontal lane and one vertical lane. + Relevant constants are used from the constants file. + """ + + #: The vehicle-to-vehicle desired distance in the aggressive driving policy + V2V_ref = 6.0 + + #: The maximum distance within which self.vehs[i].APs['veh_ahead'] = True + veh_ahead_max = 40.0 + + #: The minimum distance that every two adjacent vehicles has to be apart from each other. + veh_ahead_min = 2*VEHICLE_SIZE_HALF[0] + + #: The penalty (i.e., the negative reward) given at the end of the maneuver when + # the ego has a collision. A penalty is a negative reward so will be summed up to + # the reward with subtraction. + _penalty_in_ego_collision = 200 + + #: the penalty for the LTL constraint violation. + _penalty_in_violation = 200 + + #: the penalty for the ego's heading angle out-of-range. + _penalty_in_ego_theta_out_of_range = 200 + + #: the maximum of the ego's heading angle + max_ego_theta = np.pi/3 + + #: The weight vector to calculate the cost. In the maneuver, cost_weights + # can be set to a specific value which may be different than the default. + cost_weights = (1.0, 0.25, 0.1, 1.0, 100.0, 0.1, 0.25, 0.1) + + #TODO: Move this to constants + # The empirical min and max of each term in the cost vector, which is used to normalize the values + cost_normalization_ranges = \ + [[-3.5, 3.5], [-6.2, 6.2], + [-12*np.tan(MAX_STEERING_ANGLE) / VEHICLE_WHEEL_BASE, -12*np.tan(MAX_STEERING_ANGLE) / VEHICLE_WHEEL_BASE], + [-12, 12], [0, 12], [-2, 2], [-16, 16], [-2, 2]] + + # Flag to normalize cost (see the cost method). False by default + normalize_cost = False + + window = None + + def _init_LTL_preconditions(self): + self._LTL_preconditions.append(LTLProperty( + "G( in_intersection => intersection_is_clear)", + self._penalty_in_violation)) + self._LTL_preconditions.append(LTLProperty( + "G( not in_intersection U highest_priority)", + self._penalty_in_violation)) + self._LTL_preconditions.append(LTLProperty( + "G( in_stop_region => (in_stop_region U has_stopped_in_stop_region) )", + self._penalty_in_violation)) + + def __init__(self, **kwargs): + """SimpleIntersectionEnv constructor. + + Args: + options: high level options instance + n_other_vehs: number of other vehicles + """ + + super().__init__() + + # load the background texture + self.background = Image( + 'background.png', anchor=(0, 0), image_type="bg") + + # load the road network + self.road_network = RoadNetworkCross('road_texture.png') + + #: the reward for achieving goal is 200 by default. + self._reward_in_goal = 200 + + #: Terminate the episode when the goal is achieved (see SimpleIntersectionEnv.goal_achieved) + self._terminate_in_goal = True + + #: info for displaying on top of ego + self.ego_info_text = "" + + #: the number of the other vehicles, initialized in generate_scenario + self.n_other_vehs = None + + #: the list of the vehicles, initialized in generate_scenario + self.vehs = list() + + #: the vehicle_nework for render, initialized in generate_scenario + self.vehicle_network = None + + #: the index of the vehicle immediately ahead from the ego, + # initialized in generate_scenario when vehicle_ahead_scenario = True + self.veh_ahead_index = None + + #: the index of the vehicle always stopped after intersection + # on the same lane as the egos's, initialized in generate_scenario + # when stopped_car_scenario = True + self.stopped_veh_index = None + + #: the list of indices of the vehicles stopped in the stop region, + # initialized in generate_scenario when n_others_stopped_in_stop_region >= 1 + self.stopped_veh_in_stop_region_indices = list() + + #: a collision btw the other vehicles happened + self.__others_collision_happened = False + #: a collision of the ego happened + self.__ego_collision_happened = False + #: A boolean representing whether the ego is driving right (False) or in reverse (True). + self.__ego_theta_out_of_range = False + + #: the reference velocity that the ego tries to follow + # (= rd.speed_limit by default). + self.v_ref = rd.speed_limit + + #: the target_lane (0: left, 1: right) of the ego to follow + # (it will be set to the ego's lane by default) + self.target_lane = 0 + + # Save the scenario option to reuse it in reset + self.scenario_option = kwargs + + self.generate_scenario(**kwargs) + + + @property + def ego(self): + return self.vehs[EGO_INDEX] + + def generate_scenario(self, **kwargs): + """Randomly generate a road scenario with + + "the N-number of vehicles + an ego vehicle" + + (n_others_range[0] <= N <= n_others_range[1]), + all of whose speeds are also set randomly (or deterministically depending + on the options) between 0 and the speed limit of the road environment. + The position and speed of the vehicles are set (some of them randomly) but + not in a way that causes inevitable collision or violation. The ego vehicle is + always posed on a horizontal lane and there is initially no or only one + vehicle posed in the intersection. + + TODO: More debugging + TODO: Add more comments for each block within the function for comprehensive understanding. + TODO: restructure the code by making private method for each part for a certain option. + + Args: + n_others_range: a tuple (n1, n2), which gives the range of the vehicles + on the road, excluding the ego vehicle, by n1 <= N <= n2. + ego_pos_range: a tuple or list (x1, x2); the ego's x-position + will be sampled uniformly in [x1, x2]. + ego_v_upper_lim: the ego's velocity limit. the ego's speed + will be sampled uniformly in [0, ego_v_upper_lim] + ego_lane: the lane in which ego will be initialized + ego_perturb_lim: a tuple (da, dtheta), where da is the absolute maximum + of the ego's initial perturbations along the y-axis from the lane + centre; dtheta is the absolute maximum of the ego's heading angle + perturbation from the horizontal line (the angle parallel to the + horizontal lane). The perturbation along the y-axis is + sampled from + + "uniform(-ego_perturb_lim[0], ego_perturb_lim[0])" + + within the lane boundary. Similarly, the perturbation of the + heading angle is sampled from + + "uniform(-ego_perturb_lim[1], ego_perturb_lim[1])." + + da is restricted by the width of the road, and dtheta the non- + holonomic constraint; + ego_heading_towards_lane_centre: If True, then the ego's heading angle is + always initialized towards the lane centre. + others_h_pos_range: the range of the other vehicles that are on the + horizontal route and are not corresponding to the vehicle + generated by the code for a special scenario below. + others_v_pos_range: the range of the other vehicles that are on the + vertical route and initially not stopped in the stop region. + n_others_stopped_in_stop_region: the number of the other vehicles + that stopped in the stop region, on the other lanes than that + of the ego. The maximum is 3 (as there are 4-lanes including + ego's). When this is true, the waited_count of the stopped cars + (except the ego) in the stop region will be set randomly. This + option is useful when generating an initial scenario for Wait + maneuver. + veh_ahead_scenario: if True, the generated scenario has a vehicle + ahead of the ego within self.veh_ahead_max. This option is useful + in generating an initial scenario for e.g., Follow and Pass. + stopped_car_scenario: if True, the generated scenario contains a + stopped car located after the intersection but in the same lane as + ego's TODO: this option is not fully tested and need some debugging. + allow_vehicles_in_ego_lane: if False, there will be no vehicle in the + same lane to the ego's. This option is useful when you generate an + initial scenario like those in Default and Finish maneuvers. + v_max_multiplier: a constant between 0 and 1, used in resetting the speeds + of the vehicles if necessary to make sure that at least an input to + the ego exists to avoid collisions or stop-sign violations. The less + v_max_multiplier, more conservative scenario is generated (but when + v_max_multipler = 1, it could generate a scenario where a collision + is inevitable). 0.9 is a value set by the developer through trial-and- + error and exhaustive testing. + randomize_special_scenarios: If True, randomizes scenarios such as vehicle_ahead_scenario, + stopped_car_scenario and n_others_stopped_in_stop_region + :returns + False if the initial state is Terminal, True if not. + """ + + n_others_range = \ + kwargs.setdefault('n_others_range', (0, MAX_NUM_VEHICLES)) \ + # Set to 1 when testing follow specific behavior + ego_pos_range = \ + kwargs.setdefault('ego_pos_range', (rd.hlanes.start_pos, rd.hlanes.stop_region[0])) + ego_v_upper_lim = \ + kwargs.setdefault('ego_v_upper_lim', rd.speed_limit) + ego_lane = \ + kwargs.setdefault('ego_lane', None) + others_h_pos_range = \ + kwargs.setdefault('others_h_pos_range', rd.hlanes.pos_range) + others_v_pos_range = \ + kwargs.setdefault('others_v_pos_range', rd.vlanes.pos_range) + n_others_stopped_in_stop_region = \ + kwargs.setdefault('n_others_stopped_in_stop_region', 0) + veh_ahead_scenario = \ + kwargs.setdefault('veh_ahead_scenario', False) + stopped_car_scenario = \ + kwargs.setdefault('stopped_car_scenario', False) + allow_vehicles_in_ego_lane = \ + kwargs.setdefault('allow_vehicles_in_ego_lane', True) + v_max_multiplier = \ + kwargs.setdefault('v_max_multiplier', 0.9) + ego_perturb_lim = \ + kwargs.setdefault('ego_perturb_lim', (0, 0)) + ego_heading_towards_lane_centre = \ + kwargs.setdefault('ego_heading_towards_lane_centre', True) + randomize_special_scenarios = \ + kwargs.setdefault('randomize_special_scenarios', True) + + if n_others_range[0] < 0: + raise ValueError("the number of other vehicles has to be non-negative.") + + if n_others_range[1] < n_others_range[0]: + raise ValueError("the range of the number of other vehicles is wrong.") + + n_others = np.random.randint(n_others_range[0], n_others_range[1] + 1) + + if randomize_special_scenarios and n_others >= 1: + # stopped_car_scenario = bool(np.random.randint(0, 1)) TODO: this scenario may not work + n_others_stopped_in_stop_region = np.random.randint(0, min(3, n_others-stopped_car_scenario)) + veh_ahead_scenario = bool(np.random.randint(0, 1)) + + if n_others_stopped_in_stop_region > min(n_others - stopped_car_scenario, 3): + raise ValueError("n_others_stopped_in_stop_region has to be less than min(3, n_others_range[0] - stopped_car_scenario).") + + if veh_ahead_scenario > n_others: + raise ValueError("the minimum number of the other vehicles (n_others_range[0]) has to be at least larger than or equal to 1 for veh_ahead_scenario.") + + if not isinstance(veh_ahead_scenario, bool): + raise ValueError("veh_ahead_scenario has to be of boolean type.") + + if not isinstance(stopped_car_scenario, bool): + raise ValueError("stopped_car_scenario has to be of boolean type.") + + if not isinstance(allow_vehicles_in_ego_lane, bool): + raise ValueError("allow_vehicles_in_ego_lane has to be of boolean type.") + + if not (0 <= v_max_multiplier <= 1): + raise ValueError("v_max_multiplier has to be within the range [0, 1].") + + if ego_v_upper_lim < 0: + raise ValueError("ego_v_upper_lim has to be non-negative.") + + if ego_lane not in {0, 1} and ego_lane is not None: + raise ValueError("ego_lane has to be 0 or 1.") + + for perturb_lim in ego_perturb_lim: + if perturb_lim < 0: + raise ValueError("the perturbation term in ego_perturb_lim has to be non-negative.") + + if ego_perturb_lim[0] > rd.hlanes.width: + raise ValueError("the maximum y-perturbation (e.g., ego_perturb_lim[0]) is out-of-range.") + + if ego_perturb_lim[1] >= np.pi / 2: + raise ValueError("the maximum theta-perturbation (i.e., ego_perturb_lim[1]) is out-of-range.") + + if not isinstance(ego_heading_towards_lane_centre, bool): + raise ValueError("ego_heading_not_outwards has to be of boolean type.") + + self.n_other_vehs = n_others + + # a list of vehicles including ego vehicle i = 0 and the others + # (1 < i <= n_other_vehs <= MAX_NUM_VEHICLES). + # The ego vehicle i = 0 has to be on the horizontal lane. + self.vehs.clear() # Remove the existing vehicles if any. + self.vehs.append(Vehicle('h', v_upper_lim=ego_v_upper_lim, lane=ego_lane)) + + ego_lane = self.ego.APs['lane'] + ego_lane_centre = rd.hlanes.centres[int(ego_lane)] + + ego_pos_min = min(ego_pos_range) + ego_pos_max = max(ego_pos_range) + + others_h_pos_min = min(others_h_pos_range) + others_h_pos_max = max(others_h_pos_range) + + others_v_pos_min = min(others_v_pos_range) + others_v_pos_max = max(others_v_pos_range) + + self.ego.x = np.random.uniform(ego_pos_min, ego_pos_max) + + # sample the ego's y-pos within the lane boundary + # (ego's center will be in the current lane by the + # inspection above) + while True: + self.ego.y = ego_lane_centre + np.random.uniform( + max(-ego_perturb_lim[0], min(rd.hlanes.sidewalks)), + min( ego_perturb_lim[0], max(rd.hlanes.sidewalks))) + sign = np.sign(self.ego.y - rd.hlanes.centres[self.ego.APs['lane']]) + if sign >= 0 and ego_heading_towards_lane_centre: + self.ego.theta = np.random.uniform(-ego_perturb_lim[1], 0) + elif sign < 0 and ego_heading_towards_lane_centre: + self.ego.theta = np.random.uniform(0, ego_perturb_lim[1]) + else: # if not ego_heading_towards_lane_centre: + self.ego.theta = np.random.uniform(-ego_perturb_lim[1], ego_perturb_lim[1]) + + if not self.is_ego_off_road(): + break + + self.ego.init_local_discrete_var() + + # reset v_ref and target_lane to their default values + self.v_ref = rd.speed_limit + self.target_lane = self.ego.APs['lane'] + + self.init_APs(False) + + # s is the distance that the vehicle (in this case, the ego) + # has to inevitably drive for complete stop. + s = calculate_s(self.ego.v) + s = SimpleIntersectionEnv.__check_init_veh(self.ego, s, v_max_multiplier) + s_seq = [s] + + curr_i = 1 + veh_ahead = None + if veh_ahead_scenario: + while True: + veh_ahead = Vehicle('h', self.ego.APs['lane'], rd.speed_limit) + V2V_dist = np.random.uniform(self.veh_ahead_min, self.veh_ahead_max) + veh_ahead.x = self.ego.x + 2 * VEHICLE_SIZE_HALF[0] + V2V_dist + veh_ahead.init_local_discrete_var() + + s = calculate_s(veh_ahead.v) + s = SimpleIntersectionEnv.__check_init_veh(veh_ahead, s, v_max_multiplier) + + self.vehs.append(veh_ahead) + self.init_APs() + s_seq.append(s) + + if veh_ahead.APs['in_intersection']: + if veh_ahead.APs['intersection_is_clear']: + self.init_APs(False) + break + else: + self.vehs.pop() + self.init_APs() + s_seq.pop() + continue + else: + break + + while V2V_dist + s_seq[curr_i] < s_seq[curr_i - 1] + self.veh_ahead_min: + s_seq[curr_i - 1] = SimpleIntersectionEnv.__regulate_veh_speed(self.ego, V2V_dist + s_seq[curr_i] - self.veh_ahead_min, v_max_multiplier) + + curr_i += 1 + + if stopped_car_scenario: + stopped_veh = Vehicle('h', self.ego.APs['lane'], rd.speed_limit) + if not veh_ahead_scenario: + min_x_for_stopped_veh = self.ego.x + 2 * VEHICLE_SIZE_HALF[0] + self.veh_ahead_min + else: + min_x_for_stopped_veh = veh_ahead.x + 2 * VEHICLE_SIZE_HALF[0] + self.veh_ahead_min + + min_x_for_stopped_veh = min(min_x_for_stopped_veh, rd.intersection_width_w_offset / 2) + + stopped_veh.x = np.random.uniform(min_x_for_stopped_veh, rd.hlanes.max_pos) + stopped_veh.v = 0 + stopped_veh.init_local_discrete_var() + + self.vehs.append(stopped_veh) + self.init_APs(False) + s_seq.append(0) + + for i in range(0, curr_i): + _, V2V_dist = self.get_V2V_distance(curr_i - i - 1) + while V2V_dist + s_seq[curr_i - i] < s_seq[curr_i - i - 1] + self.veh_ahead_min: + s_seq[curr_i - i - 1] = SimpleIntersectionEnv.__regulate_veh_speed(self.vehs[curr_i - i - 1], V2V_dist + s_seq[curr_i - i] - self.veh_ahead_min, v_max_multiplier) + + self.init_APs(False) + curr_i += 1 + + # randomly pose the (n_others_stopped_in_stop_region)-number of vehicles, + # with zero speeds, in stop regions but not on the same lane as the ego's. + if n_others_stopped_in_stop_region: + index_flag = [0] * n_others_stopped_in_stop_region + + # 0s <= max_waited_count * DT <= 1s; + # this is for the random choice of waited_count of the vehicles + # which initially have stopped in the stop regions. + max_waited_count = np.random.randint(0, 11) + for i in range(0, n_others_stopped_in_stop_region): + + # Randomly pick an index j = 0, 1, 2. Remember that 3 is the + # maximum number of vehicles initially forced to be posed + # in the stop region with zero speeds, i.e., + # n_others_stopped_in_stop_region = 0, 1, 2, or 3 + # (see the inspection above). + while True: + j = np.random.randint(0, n_others_stopped_in_stop_region) + # if found an empty intersection, break the loop. + if not index_flag[j]: + break + + # Now, the stop region corresponding to index_flag[j]-th lane + # will be occupied. + index_flag[j] = True + + if j == 0: # 'h'orizontal lane + self.vehs.append(Vehicle('h', not self.ego.APs['lane'], 0)) + self.vehs[curr_i + i].x = np.random.uniform(rd.hlanes.stop_region[1], rd.hlanes.stop_region[0]) + elif j == 1: # 'v'ertical left lane + self.vehs.append(Vehicle('v', 0, 0)) + self.vehs[curr_i + i].y = np.random.uniform(rd.hlanes.stop_region[1], rd.hlanes.stop_region[0]) + elif j == 2: # 'v'ertical right lane + self.vehs.append(Vehicle('v', 1, 0)) + self.vehs[curr_i + i].y = np.random.uniform(rd.hlanes.stop_region[1], rd.hlanes.stop_region[0]) + else: + raise RuntimeError("Out of the index.") + + # update the maximum waited_count wrt the vehicles + # generated at the previous step. + if i > 0: + max_waited_count = max(max_waited_count, self.vehs[curr_i + i - 1].waited_count) + + self.vehs[curr_i + i].init_local_discrete_var() + # randomly put waited_count from 0 to 21 + max_waited_count + self.vehs[curr_i + i].waited_count = np.random.randint(0, max_waited_count + 21) + s_seq.append(0) # s is zero as the vehicle has zero velocity. + + # Now, it successfully put the vehicles + # on the stop regions. + curr_i += n_others_stopped_in_stop_region + self.init_APs(False) + + for i in range(curr_i, n_others + 1): + success_flag = False + while not success_flag: + self.vehs.append( + Vehicle('h' if np.random.randint(0, 2) is 0 else 'v', + np.random.randint(0, 2), rd.speed_limit)) + + if self.vehs[i].which_dir == 'h': + self.vehs[i].x = np.random.uniform(others_h_pos_min, others_h_pos_max) + elif self.vehs[i].which_dir == 'v': + self.vehs[i].y = np.random.uniform(others_v_pos_min, others_v_pos_max) + else: + raise ValueError("The Vehicle class constructor generates a vehicle which is neither 'h'- or 'v'-type.") + + self.vehs[i].init_local_discrete_var() + self.init_APs(False) + + if ((self.vehs[i].APs['lane'] == self.ego.APs['lane']) and (allow_vehicles_in_ego_lane is False)) or \ + (self.vehs[i].APs['in_intersection'] and not self.vehs[i].APs['intersection_is_clear']): + self.vehs.pop() + self.init_APs(False) + continue + + if self.vehs[i].APs['in_intersection']: + for veh in self.vehs: + # making every highest priority False as it is possible that one of them in the stop region is True. + veh.APs['highest_priority'] = False + self.vehs[i].APs['highest_priority'] = True + + s = calculate_s(self.vehs[i].v) + s = self.__check_init_veh(self.vehs[i], s, v_max_multiplier) + s_seq.append(s) + self.init_APs(False) + + for j in range(0, i + 1): + k, V2V_dist = self.get_V2V_distance(j) + if k is not None: + if V2V_dist < 0 or \ + (V2V_dist + s_seq[k] < s_seq[j] + self.veh_ahead_min): + self.vehs.pop() + s_seq.pop() + self.init_APs(False) + break + if j == i: + success_flag = True + break + + # Finally checks the constraints that every vehicle has to satisfy, and if not satisfied, modify the speeds. + success_flag = False + while not success_flag: + success_flag = True + for i, veh in enumerate(self.vehs): + k, V2V_dist = self.get_V2V_distance(i) + if k is None: + continue + elif V2V_dist + s_seq[k] < s_seq[i] + self.veh_ahead_min: + s_seq[i] = SimpleIntersectionEnv.__regulate_veh_speed(veh, V2V_dist + s_seq[k] - self.veh_ahead_min, v_max_multiplier) + success_flag = False + + self.init_APs(False) + + # Perform the permutations among the vehs in self.vehs (give random indices for the vehs generated above) + other_vehs_indices = np.random.permutation(n_others) + 1 + self.veh_ahead_index = other_vehs_indices[0] if veh_ahead_scenario else None + self.stopped_veh_index = other_vehs_indices[veh_ahead_scenario] if stopped_car_scenario else None + + if n_others_stopped_in_stop_region: + start_index = veh_ahead_scenario + stopped_car_scenario + self.stopped_veh_in_stop_region_indices = other_vehs_indices[start_index:start_index + n_others_stopped_in_stop_region] + + other_vehs = [] + for i in other_vehs_indices: + other_vehs.append(self.vehs[i]) + + self.vehs[1:] = other_vehs + + # create the vehicle network for graphical output + self.vehicle_network = VehicleNetworkCross('car_agent.png', self) + + # Reset the variables related to model- and collision-checking and termination. + self._reset_model_checker(self.ego.APs) + self._check_collisions() + self._check_ego_theta_out_of_range() + + return not self.termination_condition + + @staticmethod + def __regulate_veh_speed(veh, dist, v_max_multiplier): + """This private method set and regulate the speed of the + vehicle in a way that it never requires to travel the given + distance for complete stop. + + Args: + veh: the vehicle reference. + dist: the distance over which the vehicle has to not + drive for complete stop. + v_max_multiplier: the same as that in generate_scenario. + + Returns: + the distance traveling when the vehicle is under + the maximum de-acceleration to stop completely. + """ + + v_max = calculate_v_max(dist) + veh.v = v_max_multiplier * np.random.uniform(0, v_max) + + s = calculate_s(veh.v) + s = SimpleIntersectionEnv.__check_init_veh(veh, s, v_max_multiplier) + + return s + + @staticmethod + def __check_init_veh(veh, s, v_max_multiplier): + """Check a given initialized vehicle (self.vehs[i]) and modify its + speed (v) if the vehicle is physically not able to stop at the stop + region. This is internally called by the above method + generate_scenario. + + Args: + veh: the vehicle reference + s: the distance traveling when the vehicle is under the maximum + de-acceleration to stop completely. + + Returns: + the same s to the input param s, but when the speed is modified. + """ + veh.init_local_discrete_var() + dist_before_stop_region = None + + if veh.which_dir is 'h': + if veh.APs['in_stop_region']: + dist_before_stop_region = rd.hlanes.stop_region[1] - veh.x + + elif (not veh.APs['has_entered_stop_region']) and \ + (rd.hlanes.stop_region[0] - veh.x <= 2.0 * s): + dist_before_stop_region = rd.hlanes.stop_region[0] - veh.x + + elif veh.APs['in_intersection']: + v_max = calculate_v_max(veh.x - rd.hlanes.stop_region[0]) + veh.v = np.random.uniform(0, v_max) + s = calculate_s(veh.v) + + elif veh.which_dir is 'v': + if veh.APs['in_stop_region']: + dist_before_stop_region = rd.vlanes.stop_region[1] - veh.y + + if (not veh.APs['has_entered_stop_region']) and \ + (rd.vlanes.stop_region[0] - veh.y <= 2.0 * s): + dist_before_stop_region = rd.vlanes.stop_region[0] - veh.y + + elif veh.APs['in_intersection']: + v_max = calculate_v_max(veh.v - rd.vlanes.stop_region[0]) + veh.v = np.random.uniform(0, v_max) + s = calculate_s(veh.v) + + else: + raise AssertionError("which_dir in Vehicle class has to be either 'h' or 'v'.") + + if dist_before_stop_region is not None: + v_max = calculate_v_max(dist_before_stop_region) if dist_before_stop_region > 0 else 0 + if v_max < veh.v: + veh.v = v_max_multiplier * np.random.uniform(0, v_max) + s = calculate_s(veh.v) + + veh.init_local_discrete_var() + + return s + + def init_APs(self, update_local_APs=True): + """Initialize the global (and local if update_local_APs is true) atomic + propositions (APs) of each vehicle using the current state. This method + is basically called by "generate_scenario" method. Compared with + update_APs, the way of setting 'highest_priority' is different. + + Args: + update_local_APs: True if the local APs are also necessary to + be initialized; False if not, and only the global APs are + required to be initialzied. + """ + + if update_local_APs is True: + for veh in self.vehs: + veh.update_local_APs() + + self.update_APs(False, False) + + index = None + for i, veh in enumerate(self.vehs): + if veh.APs['in_intersection']: + if index is not None: + # if there are multiple cars in the intersection, + # then choose only one of them to give the highest + # priority, which has already done before in the loop. + veh.APs['highest_priority'] = 0 + else: + index = i + veh.APs['highest_priority'] = 1 + else: + veh.APs['highest_priority'] = 0 + + if index is not None: + return + + waited_count = -1 + for i, veh in enumerate(self.vehs): + if waited_count < veh.waited_count: + waited_count = veh.waited_count + index = i + + if index is not None: + self.vehs[index].APs['highest_priority'] = True + + def update_APs(self, update_local_APs=True, update_highest_priority=True): + """Update the global (and local if update_local_APs is true) atomic + propositions (APs) of each vehicle using the current state. This method + is basically called by "step" method below after it updates the + vehicle's continuous state. By a global AP, it means that the state + information of the other cars has to be used to update the AP (whereas + a local AP means that the information of the other cars are not + necessary). For comparison and more details, see also "updateLocalAPs" + method in vehicles module. + + Args: + update_local_APs: True if the local APs are also necessary to + be update; False if not, and only the global APs are required + to be updated. + """ + + if update_local_APs is True: + for veh in self.vehs: + veh.update_local_APs() + + for i, veh in enumerate(self.vehs): + veh.APs['intersection_is_clear'] = True + for j in range(0, len(self.vehs)): + if j is not i: + veh.APs[ + 'intersection_is_clear'] &= not self.vehs[j].APs['in_intersection'] + + if i == 0: + veh.APs['target_lane'] = self.target_lane + else: + veh.APs['target_lane'] = self.vehs[i].APs['lane'] + + j, V2V_dist = self.get_V2V_distance(i) + + if j is None: + veh.APs['veh_ahead'] = False + else: + veh.APs['veh_ahead'] = True if \ + 0 < V2V_dist <= self.veh_ahead_max \ + else False + + if not veh.APs['veh_ahead']: + veh.APs['veh_ahead_stopped_now'] = False + veh.APs['veh_ahead_too_close'] = False + else: + veh.APs['veh_ahead_stopped_now'] = self.vehs[j].APs['stopped_now'] + veh.APs['veh_ahead_too_close'] = True if 0 < V2V_dist <= self.veh_ahead_min else False + + if update_highest_priority: + waited_count = -1 + index = None + for i, veh in enumerate(self.vehs): + if veh.APs['highest_priority']: + if veh.APs['in_stop_region'] or veh.APs['in_intersection']: + return + else: + # Flag off the AP when the car gets out of the intersection. + veh.APs['highest_priority'] = False + + elif waited_count < veh.waited_count: + waited_count = veh.waited_count + index = i + + if (waited_count != -1) and (index is not None): + self.vehs[index].APs['highest_priority'] = True + + # Checking that there exists only one True highest_priority. + exists_highest_priority = False + for veh in self.vehs: + if veh.APs['highest_priority']: + if exists_highest_priority: + raise ValueError("The AP highest_priority is true for only one veh for each time.") + else: + exists_highest_priority = True + + def get_V2V_distance(self, veh_index=0): + """Calculate the distance between the target and the nearest adjacent + car in the same lane. The distance is given as a bumper-to-bumper one, + so being it not positive means that the two cars collide. + + Args: + veh_index: the index of the vehicle whose V2V distance is + returned, ranging from 0 to len(self.vehs) + (with 0 for the index of the ego). + + Returns: + a tuple (i, V2Vdist), where V2Vdist is the V2V distance + from the indexed vehicle to the closest vehicle, with its index i, + on the same route; i is None and V2Vdist == np.infty + when there is no vehicle ahead. + """ + if veh_index not in range(0, len(self.vehs)): + raise ValueError("veh_index in SimpleIntersectionEnv.get_V2V_distance out of index") + + tar_veh = self.vehs[veh_index] + + V2V_dist = np.infty + index = None + for i, veh in enumerate(self.vehs): + if i == veh_index: + continue + elif (veh.which_dir is tar_veh.which_dir) and \ + (veh.APs['lane'] is tar_veh.APs['lane']): + if (tar_veh.which_dir is 'h') and \ + (0.0 <= veh.x - tar_veh.x < V2V_dist): + V2V_dist = veh.x - tar_veh.x + index = i + elif (tar_veh.which_dir is 'v') and \ + (0.0 <= veh.y - tar_veh.y < V2V_dist): + V2V_dist = veh.y - tar_veh.y + index = i + + return index, V2V_dist - 2.0 * VEHICLE_SIZE_HALF[0] + + def aggressive_driving_policy(self, veh_index, maneuver_opt=None): + """Implementation of the aggressive driving policy. Calculate the + (veh_index)-th vehicle's low-level action (a, dot_phi) using aggressive + driving policy. If using aggressive driving policy for all vehicles, + there is [has to be] no collision. + + Args: + veh_index: the index of the vehicle to calculate the action + (a, dot_phi) via aggressive driving policy. + maneuver_opt: an option that specifies a maneuver to be executed; it can + be 'stop', 'wait', etc. + + Returns: + current low-level action (a, dot_phi) generated by the + aggressive driving policy for the current state. + """ + assert 0 <= veh_index <= len(self.vehs) - 1 + + tar_veh = self.vehs[veh_index] + + i, V2V_dist = self.get_V2V_distance(veh_index) + s = calculate_s(tar_veh.v) + + if i is not None and (V2V_dist + calculate_s(self.vehs[i].v) < s + self.V2V_ref): + a = -MAX_ACCELERATION # emergency stop + + elif i is not None and (V2V_dist <= self.V2V_ref + 6) and \ + ((not tar_veh.APs['has_entered_stop_region'] and + (tar_veh.which_dir is 'h' and rd.hlanes.stop_region_centre - tar_veh.x > 2 * s or + tar_veh.which_dir is 'v' and rd.vlanes.stop_region_centre - tar_veh.y > 2 * s)) or + (tar_veh.APs['has_entered_stop_region'] and not tar_veh.APs['in_stop_region'])): + a = 31.6228 * (V2V_dist - self.V2V_ref) - 7.9527 * ( + tar_veh.v - self.vehs[i].v) + self.vehs[i].acc + + elif tar_veh.APs['in_stop_region'] and \ + tar_veh.APs['highest_priority'] and \ + tar_veh.APs['intersection_is_clear'] and \ + maneuver_opt != 'stop': + a = -100.0 * (tar_veh.v - rd.speed_limit) + + elif tar_veh.APs['in_stop_region'] and \ + not (tar_veh.APs['highest_priority'] and + tar_veh.APs['intersection_is_clear']): + a = -2 * 7.9527 * tar_veh.v - 0.5 * np.clip(20*tar_veh.v, -1, 1) + + elif (not tar_veh.APs['has_entered_stop_region']) and \ + ((tar_veh.which_dir is 'h') and (0 <= rd.hlanes.stop_region[1] - tar_veh.x <= 3 * s)) or \ + ((tar_veh.which_dir is 'v') and (0 <= rd.vlanes.stop_region[1] - tar_veh.y <= 3 * s)): + if tar_veh.which_dir is 'h': + a = -31.6228 * ( + rd.hlanes.stop_region_centre - tar_veh.x) - 7.9527 * tar_veh.v + else: + a = -31.6228 * ( + rd.vlanes.stop_region_centre - tar_veh.y) - 7.9527 * tar_veh.v + else: + a = -10.0 * (tar_veh.v - rd.speed_limit) + + return np.clip(a, -MAX_ACCELERATION, MAX_ACCELERATION), 0 + + def _check_ego_theta_out_of_range(self): + self.__ego_theta_out_of_range = abs(self.ego.theta) > self.max_ego_theta + + def _check_collisions(self): + """returns True when collision happens, False if not. + + """ + self.__ego_collision_happened = self.check_ego_collision() or \ + self.is_ego_off_road() + self.__others_collision_happened = self.check_other_veh_collisions() + + @property + def collision_happened(self): + return self.__ego_collision_happened or self.__others_collision_happened + + def check_ego_collision(self): + """Checks if ego collides with any other vehicle in the environment. + Uses bounding boxes to check if a seperating line exists between given + vehicle and each of the other vehicles. + + Returns: True if ego collides with another vehicle, False + otherwise + """ + + current_veh_bb = self.ego.get_bounding_box() + for i, veh in enumerate(self.vehs): + if i is EGO_INDEX: + continue + other_veh_bb = veh.get_bounding_box() + if bb_utils.does_bounding_box_intersect(current_veh_bb, other_veh_bb): + #print("\nEgo collided with vehicle[", i, "]") + return True + + return False + + def check_other_veh_collisions(self): + """Checks if other vehicles other than ego collide in the environment. + Uses V2V distance for vehicles in same lane, otherwise uses bounding + boxes Checks all vehicles other than ego. + + Returns: True if a vehicle collides with another vehicle, False otherwise + """ + + for index in range(len(self.vehs)): + if index is EGO_INDEX: + continue + current_veh = self.vehs[index] + for j in range(index + 1, len(self.vehs)): + veh = self.vehs[j] + # check collision using V2V for other vehicles only in same lane and travelling in same direction + if veh.which_dir is current_veh.which_dir and veh.APs['lane'] is current_veh.APs['lane']: + if current_veh.which_dir is 'h': + v2v_dist = abs( + veh.x - current_veh.x) - 2.0 * VEHICLE_SIZE_HALF[0] + else: + v2v_dist = abs( + veh.y - current_veh.y) - 2.0 * VEHICLE_SIZE_HALF[0] + if v2v_dist < 0: + # TODO: Remove this print or log this somehow + #print("\nVehicle[", index, "] collided with vehicle[", j,"]") + return True + # otherwise, check collision using BB only if at intersection + elif current_veh.APs['in_intersection']: + current_veh_bb = current_veh.get_bounding_box() + other_veh_bb = veh.get_bounding_box() + if bb_utils.does_bounding_box_intersect( + current_veh_bb, other_veh_bb): + #print("\nVehicle [", index, "] collided with vehicle [", j,"]") + return True + + return False + + def is_ego_off_road(self): + """Checks if ego goes off-road. + + Returns: True if ego goes off-road, False otherwise + """ + + # check if ego off-road from horizontal road + h_offroad = not self.ego.is_within_road_boundaries(rd.hlanes) + + # check if ego off-road from vertical road + v_offroad = not self.ego.is_within_road_boundaries(rd.vlanes) + + return True if (h_offroad and v_offroad) else False + + def cost(self, u): + """Calculate the driving cost of the ego, i.e., + the negative reward for the ego-driving. + + Args: + u: the low-level input (a, dot_psi) to the ego vehicle. + + Returns: + cost: the weighted sum of squares of the components in + the vector "vec." Note that a cost is a negative reward. + """ + + # input clipping. + if abs(u[0]) > MAX_ACCELERATION: + u[0] = np.clip(u[0], -MAX_ACCELERATION, MAX_ACCELERATION) + + if abs(u[1]) > MAX_STEERING_ANGLE_RATE: + u[1] = np.clip(u[1], -MAX_STEERING_ANGLE_RATE, MAX_STEERING_ANGLE_RATE) + + y_err = self.ego.y - rd.hlanes.centres[self.target_lane] + # The target theta error is '0', corresponding to the direction of the horizontal lane. + # That is, theta_err = self.ego.theta - 'target_theta' = self.ego.theta - 0. + theta_err = self.ego.theta + theta_dot_err = self.ego.v * np.tan(self.ego.psi) / VEHICLE_WHEEL_BASE + + # for more details, see the Paxton's paper (2017, IROS)... + vec = (y_err, theta_err, theta_dot_err, self.ego.v - self.v_ref, max(0, self.ego.v - rd.speed_limit), u[0], + (u[0] - self.ego.acc) / DT, u[1]) + + if self.normalize_cost: + vec = self.normalize_tuple(vec) + + if len(self.cost_weights) != len(vec): + raise ValueError("the dimension mismatch between weights \ + and the vector.") + + return np.inner(self.cost_weights, np.square(vec)) + + #TODO: Move this to utilities + def normalize_tuple(self, vec, scale_factor=10): + """Normalizes each element in a tuple according to ranges defined in self.cost_normalization_ranges. + Normalizes between 0 and 1. And the scales by scale_factor + + Args: + vec: The tuple to be normalized + scale_factor: the scaling factor to multiply the normalized values by + + Returns: + The normalized tuple + """ + if len(self.cost_normalization_ranges) != len(vec): + raise ValueError("dimension mismatch between cost_normalization_ranges \ + and the vector.") + + normalized_vec = [] + for index, value in enumerate(vec): + min_value = self.cost_normalization_ranges[index][0] + max_value = self.cost_normalization_ranges[index][1] + normalized_vec.append(((value - min_value) / (max_value - min_value)) * scale_factor) + + return tuple(normalized_vec) + + def get_features_tuple(self): + """ + Get/calculate the features wrt. the current state variables + + Returns features tuple + """ + + return Features(self).get_features_tuple() + + def step(self, u_ego): + """Gym compliant step function. + + Calculate the next continuous and discrete states of every vehicle + using the given action u_ego for ego-vehicle and aggressive driving + policy for the other vehicles. The variables in self.vehs will be + automatically updated. Then, call the options _step and get the reward + and terminal values. + + Args: + u_ego: the low level action [a, dot_phi] of the ego vehicle. + + Returns: + new_state: the new state of the environment + R: reward obtained + terminal: whether or not the current policy finished, that is, + its termination_condition() is satisfied; TODO - also return + true when the environment's state indicates the episode is + over. + info: information variables + """ + + # TODO: remove the line below after debugging output scaling in keras_learner.py. + u_ego = [2*u_ego[0], u_ego[1]] # Rescaling (temporary code). + + reward = - self.cost(u_ego) # a cost is defined as a negative reward. + + for i, veh in enumerate(self.vehs): + # For the current version, the ego vehicle also follows the + # aggressive driving policy. Later, it'll follow a presumably + # better but complex policy learnt by reinforcement learning. + # + if i is 0: # ego vehicle case, + veh.step(u_ego) + else: # the other vehicle cases, + veh.step(self.aggressive_driving_policy(i)) + + self.update_APs(False) + self._check_collisions() + self._check_ego_theta_out_of_range() + + self._set_mc_AP(self.ego.APs) + _, _, terminal, info = super().step(u_ego) + + if self.termination_condition: + if self.collision_happened: + if self.__ego_collision_happened: + self._terminal_reward_superposition(-self._penalty_in_ego_collision) + # TODO: discussion of how to implement log and gym-compliant info + # TODO: Make a detailed log about collision. + info['episode_termination_reason'] = "ego_collision" + + else: + info['episode_termination_reason'] = "other_vehicle_collision" + + if self.__ego_theta_out_of_range: + self._terminal_reward_superposition(-self._penalty_in_ego_theta_out_of_range) + info['episode_termination_reason'] = "heading_angle_deviation" + + terminal = True + + if self._r_terminal is None: + reward = reward + else: + reward = reward + self._r_terminal + + return self.get_features_tuple(), reward, terminal, info + + def is_terminal(self): + """Check if the environment is at a terminal state or not. + + Args: + env: environment instance + + Returns True if the environment has terminated + """ + + model_checks_violated = (self._LTL_preconditions_enable and \ + self.current_model_checking_result()) + reached_goal = self._terminate_in_goal and self.goal_achieved + self._check_collisions() + self._check_ego_theta_out_of_range() + terminated = self.termination_condition + return model_checks_violated or reached_goal or terminated + + @property + def termination_condition(self): + return super().termination_condition or self.__ego_theta_out_of_range\ + or self.collision_happened + + @property + def goal_achieved(self): + """ + A property from the base class which is True if the goal + of the road scenario is achieved, otherwise False. This property is + used in both step of EpisodicEnvBase and the implementation of + the high-level reinforcement learning and execution. + """ + + return (self.ego.x >= rd.hlanes.end_pos) and \ + not self.collision_happened and \ + not self.ego.APs['over_speed_limit'] + + def reset(self): + """Gym compliant reset function. + + Reinitialize this environment with whatever parameters it was initially + called with. + + Returns: + new_state: the environment state after reset + """ + + while not self.generate_scenario(**self.scenario_option): + pass + + return self.get_features_tuple() + + def draw(self, info=None): + """Draw the background, road network and vehicle network. Also show + information as passed on by info. + + Args: + info: the information string to be shown on the window + """ + + self.background.draw() + + # draw the road network + self.road_network.draw() + + # draw the vehicle network + self.vehicle_network.draw(self.ego_info_text) + + if info is not None: + label = Text(info, x=10, y=NUM_VPIXELS - 20, multiline=True) + label.draw() + + def render(self): + """ + Gym compliant render function. + """ + + if self.window is None: + self.window = config_Pyglet(pyglet, NUM_HPIXELS, NUM_VPIXELS) + + self.window.clear() + self.window.switch_to() + self.window.dispatch_events() + + # Text information about ego vehicle's states + # Right now, we are only training one option (Stop) + info = "Ego Attributes:" + get_APs( + self, EGO_INDEX, 'in_stop_region', + 'has_entered_stop_region', 'has_stopped_in_stop_region', + 'before_but_close_to_stop_region', 'intersection_is_clear', + 'stopped_now', 'in_intersection', 'over_speed_limit', + 'on_route', 'highest_priority', 'intersection_is_clear', + 'veh_ahead', 'lane') + \ + get_veh_attributes(self, EGO_INDEX, 'waited_count', 'v', 'acc', 'psi_dot') + + self.draw(info) + + self.window.flip() + + def set_ego_info_text(self, info): + self.ego_info_text = info + + @property + def action_space(self): + return gym.spaces.Box(low=np.array([-MAX_ACCELERATION, -MAX_STEERING_ANGLE_RATE]), + high=np.array([MAX_ACCELERATION, MAX_STEERING_ANGLE_RATE])) + + @property + def observation_space(self): + length = len(self.get_features_tuple()) + return gym.spaces.Box(low=-np.finfo(np.float32).max, high=np.finfo(np.float32).max, shape=(length,)) + + def copy(self): + # Make a copy of self.env + # Assumption: all environments ship with this method + backup_background = self.background + backup_road_network = self.road_network + backup_vehicle_network = self.vehicle_network + backup_window = self.window + self.background = None + self.road_network = None + self.vehicle_network = None + self.window = None + + new_env = deepcopy(self) + + self.background = backup_background + self.road_network = backup_road_network + self.vehicle_network = backup_vehicle_network + self.window = backup_window + + return new_env diff --git a/env/simple_intersection/utilities.py b/env/simple_intersection/utilities.py new file mode 100644 index 0000000000000000000000000000000000000000..2a232a953e577ecb1b02d08953409edd24181452 --- /dev/null +++ b/env/simple_intersection/utilities.py @@ -0,0 +1,271 @@ + +from .constants import * +from . import road_geokinemetry as rd +import numpy as np + +# Add classes for each kind of utility functions +# Available utilities: +# 1) BoundingBox: for working with bounding boxes + + +# @brief: +class BoundingBox(object): + """A class that provides utility functions related to bounding boxes. + + * Bounding box: ndarray of shape (4,2) containing the vertices of the + rectangle in order + """ + + @staticmethod + def does_bounding_box_intersect(first_bb, second_bb): + """Checks if bounding boxes intersect using separating axis test: Two + objects don't intersect if you can find a line that separates the two + objects. Works only for quadrilateral bounding boxes (in 2D). + + Args: + first_bb: np.ndarray First bounding box + second_bb: np.ndarray Second bounding box + + Returns: + true if there is an intersection + """ + + for i, vertex in enumerate(first_bb): + # for each vertex, get line joining it and next vertex + line = np.array([vertex, first_bb[(i + 1) % 4]]) + + # check side of other 2 vertices in first_bb + side_of_first_bb = BoundingBox.localize_point_wrt_line( + line, first_bb[( + i + 2) % 4]) + BoundingBox.localize_point_wrt_line( + line, first_bb[(i + 3) % 4]) + + # Find side of all points in second_bb + side_of_second_bb = [] + for j in range(second_bb.shape[0]): + side_of_second_bb.append( + BoundingBox.localize_point_wrt_line( + line, second_bb[j, :])) + + # Check if all points in second_bb are on same side of line + # and that other vertices in first_bb are on the opposite side + if BoundingBox.all_same_sign_in_list(side_of_second_bb) and ( + side_of_first_bb * sum(side_of_second_bb) < 0): + return False + + return True + + # TODO: This method was never used in any other places. Remove or keep it? + @staticmethod + def does_bounding_box_cross_line(line, bb): + """Checks if bounding box crosses a line. Line is represented by an + np.ndarray of size (2,2) representing two points in it. Works only for + quadrilateral bounding boxes (in 2D). + + Args: + line: np.ndarray Two points representing the line + bb: np.ndarray Bounding box + + Returns: + true if the bounding box crosses the line + """ + + side_of_vertices = [] + for i, vertex in enumerate(bb): + side_of_vertices.append( + BoundingBox.localize_point_wrt_line(line, vertex)) + + if BoundingBox.all_same_sign_in_list(side_of_vertices): + return False + else: + return True + + @staticmethod + def localize_bounding_box_wrt_line(line, bb): + """Returns the side in which a bounding box is w.r.t a line. Line is + represented by an np.ndarray of size (2,2) representing two points in + it. Works only for quadrilateral bounding boxes (in 2D). + + Args: + line: np.ndarray Two points representing the line + bb: np.ndarray Bounding box + + Returns: + 1 or -1 depending upon the side w.r.t the line. returns 0 if it + intersects the line + """ + + side_of_vertices = [] + for i, vertex in enumerate(bb): + side_of_vertices.append( + BoundingBox.localize_point_wrt_line(line, vertex)) + + if BoundingBox.all_same_sign_in_list(side_of_vertices): + for side in side_of_vertices: + # side_of_vertices can contain 0 if a vertex touches the line + if side != 0: + return side + else: + return 0 + + @staticmethod + def localize_point_wrt_line(line, testpoint): + """Check the side in which a point lies w.r.t a line. + + Args: + line: np.ndarray Two points representing the line + testpoint: the point to be checked + + Returns: + 1 or -1 depending upon the side w.r.t the edge; + returns 0 if it is on the line + """ + + edge = line[0, :] - line[1, :] + vertex_in_edge = line[0, :] + + # find perpendicular to line + rotated_edge = np.array([-edge[1], edge[0]]) + + # return -1 or 1 depening on the side. 0 if on the line + return np.sign(rotated_edge[0] * (testpoint[0] - vertex_in_edge[0]) + + rotated_edge[1] * (testpoint[1] - vertex_in_edge[1])) + + @staticmethod + def all_same_sign_in_list(test_list): + """Check if all elements in a list are of the same sign. Zero does not + have a sign. + + Args: + test_list: the python list to be checked + + Returns: + 1 or -1 depending upon the side w.r.t the edge + """ + + return all(k >= 0 for k in test_list) or all(k <= 0 for k in test_list) + + +# Methods (get_APs, get_veh_attributes, config_Pyglet, +# road2image, draw_all_shapes) related to Pyglet for graphical output. + + +def get_APs(env, index, *args): + """Retrieve atomic proposition data from the env. + + Args: + env: SimpleIntersectionEnv object + index: vehicle index + args: atomic proposition names (variable arguments) + + Returns: + multiline string with the required data + """ + + properties = [] + for arg in args: + properties.append('%s: %s' % (arg, env.vehs[index].APs[arg])) + + return "\n" + "\n".join(properties) + "\n" + + +# TODO: env and index info are not used for now. Remove or implement it. +def get_veh_attributes(env, index, *args): + """Retrieve vehicle attributes from env. + + Args: + env: SimpleIntersectionEnv object + index: vehicle index + args: atomic proposition names (variable arguments) + + Returns: + multiline string with the required data + """ + + attributes = [] + for arg in args: + attributes.append( + "%s: %s" % (arg, round(eval("env.vehs[index].%s" % arg), 2))) + + return "\n" + "\n".join(attributes) + "\n" + + +def config_Pyglet(pyglet, win_x, win_y): + """Configure pyglet and return the window that can be used by other pyglet + objects. + + Args: + win_x: x width of the window + win_y: y width of the window + + Returns: + Pyglet window object + """ + + pyglet.options['debug_gl'] = False + config = pyglet.gl.Config(sample_buffers=1, samples=4) + window = pyglet.window.Window(width=win_x, height=win_y, config=config) + return window + + +def road2image(pos, which_dir): + """Transform a 1D point to the 1D point in the graphics coordinate for the + same direction ('h' or 'v'). + + Args: + pos: 1D position in x or y-axis of the road coordinate system + which_dir: the direction of the coordinate. It has to be either + horizontal ('h') or vertical ('v'). + + Returns: + the corresponding 1D position in the graphics coordinate. + """ + if which_dir is 'h': + pos_out = (pos - rd.hlanes.start_pos) * H_SPACE_SCALE + elif which_dir is 'v': + pos_out = (pos - rd.vlanes.start_pos) * V_SPACE_SCALE + pos_out = NUM_VPIXELS - pos_out + else: + raise AssertionError + + return pos_out + + +def draw_all_shapes(shapes): + """Go through all the shapes and call their draw function. + + Args: + shapes: list of shapes + """ + + for shape in shapes: + shape.draw() + +# Methods (calculate_v_max, calculate_s) +# used in generate_scenario of SimpleIntersectionEnv + + +def calculate_v_max(dist): + """Calculate the maximum velocity you can reach at the given position ahead. + + Args: + dist: the distance you travel from the current position. + + Returns: + the maximum reachable velocity. + """ + return np.sqrt(2.0 * MAX_ACCELERATION * max(dist, 0)) + + +def calculate_s(v): + """Calculate the distance traveling when the vehicle is maximally + de-accelerating for a complete stop. + + Args: + v: the current speed of the vehicle. + + Returns: + the distance traveling when the vehicle is under the maximum + de-acceleration to stop completely. + """ + return pow(v, 2) / MAX_ACCELERATION / 2.0 diff --git a/env/simple_intersection/vehicle_networks.py b/env/simple_intersection/vehicle_networks.py new file mode 100644 index 0000000000000000000000000000000000000000..bf61d2006bd7f8060f579f3d60f390f4785d1036 --- /dev/null +++ b/env/simple_intersection/vehicle_networks.py @@ -0,0 +1,51 @@ + +from .constants import * +from .shapes import Shape, Image, Text +from .utilities import road2image + + +class VehicleNetworkCross(Shape): + """Vehicle network for the cross scenario. + + This scenario has just one horizontal lane and one vertical lane. + Relevant constants are used from the constants file. + """ + + def __init__(self, image_url, env): + """Constructor for VehicleNetworkCross. + + Args: + image_url: url for the image file, relative to the graphics folder + env: SimpleIntersectionEnv object which should be utilized for positions and + velocities. + """ + + self.env = env + self.vehs_sprites = [] + for i, veh in enumerate(self.env.vehs): + veh_pic = Image('car_agent.png', image_type="car", tile_scale=True) + self.vehs_sprites.append(veh_pic) + + def draw(self, ego_info_text): + """ + Draw the cars. + TODO: add the code for drawing the lines on the road, e.g.,:: + + Args: + ego_info:_text: the text to be displayed above ego + + pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ("v2f", (0, 320, 640, 320))) + + """ + for i, veh in enumerate(self.env.vehs): + x = road2image(veh.x, 'h') + y = road2image(veh.y, 'v') + self.vehs_sprites[i].sprite.set_position(x, y) + self.vehs_sprites[i].sprite.update( + rotation=np.rad2deg(self.env.vehs[i].theta)) + self.vehs_sprites[i].draw() + + if i is 0: + # Put text 'ego' on the ego vehicle. + label = Text(ego_info_text, color=(255, 255, 255, 255), x=x, y=y+10, font_size=10) + label.draw() \ No newline at end of file diff --git a/env/simple_intersection/vehicles.py b/env/simple_intersection/vehicles.py new file mode 100644 index 0000000000000000000000000000000000000000..543eae0e8f8f154bd4f67d4f852fb941daafeeae --- /dev/null +++ b/env/simple_intersection/vehicles.py @@ -0,0 +1,362 @@ + +from . import road_geokinemetry as rd +import numpy as np +from model_checker.simple_intersection import AtomicPropositions +from .utilities import BoundingBox as bb_utils +from .constants import * + + +class VehicleState(object): + """A class that defines the vehicle's (cont.) state variables and provides + a mean to calculate the next state. + + * which_dir: the direction of the vehicle. It has to be either horizontal + ('h') or vertical ('v'); + * x, y: the x and y position of the vehicle; + * theta: the heading angle of the vehicle; + * v: the velocity along the heading angle; + * psi: the steering angle; + * (acc, psi_dot): the acceleration and the rate of change of the + steering angle psi. If u = (u[0], u[1]) in step is in the reasonable + range, this is equal to the previous input u at the previous step. + * method: either 'Euler' (Euler method) or 'RK4' (Runge-Kutta 4th-order) + """ + + def __init__(self, which_dir, lane, pos_in_lane, v, psi): + """The constructor which sets the properties of the class. + + Args: + which_dir: the direction of the vehicle. It has to be + either horizontal ('h') or vertical ('v'); + lane: the lane number the lane number (0 is the right + lane, 1 means the left lane); + pos_in_lane: the 1D position in the lane; + (v, psi): the velocity and the steering angle of the + vehicle, respectively. + """ + + assert (which_dir in ['h', 'v']) + assert (lane in [0, 1]) + + self.which_dir = which_dir + if which_dir is 'h': + assert (rd.hlanes.min_pos <= pos_in_lane <= rd.hlanes.max_pos) + self.x = pos_in_lane + self.y = rd.hlanes.centres[lane] + self.theta = 0.0 + elif which_dir is 'v': + assert (rd.vlanes.min_pos <= pos_in_lane <= rd.vlanes.max_pos) + self.y = pos_in_lane + self.x = rd.vlanes.centres[lane] + self.theta = -np.sign(rd.vlanes.start_pos) * np.pi / 2.0 + else: + raise AssertionError + + self.v = v + self.psi = psi + + self.acc = 0.0 + self.psi_dot = 0.0 + + self.method = 'RK4' + + def step(self, u): + """Calculate the next state and update the other properties for the + given input u. + + Args: + u: a tuple or an array whose first element corresponds to the + acceleration and the second element corresponds to the rate + of change of the steering angle. + """ + + # input clipping. + if abs(u[0]) > MAX_ACCELERATION: + self.acc = np.clip(u[0], -MAX_ACCELERATION, MAX_ACCELERATION) + else: + self.acc = u[0] + + if abs(u[1]) > MAX_STEERING_ANGLE_RATE: + self.psi_dot = np.clip(u[1], -MAX_STEERING_ANGLE_RATE, MAX_STEERING_ANGLE_RATE) + else: + self.psi_dot = u[1] + + if self.method == 'RK4': + K1x = self.v * np.cos(self.theta) + K1y = self.v * np.sin(self.theta) + K1th = self.v * np.tan(self.psi) / VEHICLE_WHEEL_BASE + + theta_temp = self.theta + DT_over_2 * K1th + v_temp = max([0.0, self.v + DT_over_2 * self.acc]) + psi_temp = np.clip(self.psi + DT_over_2 * self.psi_dot, -MAX_STEERING_ANGLE, MAX_STEERING_ANGLE) + + K23x = np.cos(theta_temp) + K23y = np.sin(theta_temp) + K23th = v_temp * np.tan(psi_temp) / VEHICLE_WHEEL_BASE + + theta_temp = self.theta + DT_over_2 * K23th + + K23x += np.cos(theta_temp) + K23y += np.sin(theta_temp) + K23x *= v_temp + K23y *= v_temp + + v_temp = max([0.0, self.v + DT * self.acc]) + psi_temp = np.clip(self.psi + DT * self.psi_dot, -MAX_STEERING_ANGLE, MAX_STEERING_ANGLE) + + K4x = v_temp * np.cos(theta_temp) + K4y = v_temp * np.sin(theta_temp) + K4th = v_temp * np.tan(psi_temp) / VEHICLE_WHEEL_BASE + + self.x += DT_over_6 * (K1x + K4x) + DT_over_3 * K23x + self.y += DT_over_6 * (K1y + K4y) + DT_over_3 * K23y + self.theta += DT_over_6 * (K1th + K4th) + DT_2_over_3 * K23th + self.v = v_temp + self.psi = psi_temp + + elif self.method == 'Euler': + self.x += DT * self.v * np.cos(self.theta) + self.y += DT * self.v * np.sin(self.theta) + self.theta += DT * self.v * np.tan(self.psi) / VEHICLE_WHEEL_BASE + + self.v = max([0.0, self.v + DT * self.acc]) + self.psi = np.clip(self.psi + DT * self.psi_dot, -MAX_STEERING_ANGLE, MAX_STEERING_ANGLE) + else: + raise ValueError("VehicleState.method has to be either 'RK4' or 'Euler'.") + + while abs(self.theta) >= 2 * np.pi: + self.theta -= np.sign(self.theta) * 2 * np.pi + + def get_bounding_box(self): + """Calculate the bounding box of the vehicle. + + Returns: the four points of the bounding box depending on + the vehicle's pose (x,y,theta) + """ + + c = np.cos(self.theta) + s = np.sin(self.theta) + + output = [] + # counter-clockwise order of vertices + for sign_y in [-1, 1]: + for sign_x in [1, -1]: + x = sign_y * sign_x * VEHICLE_SIZE_HALF[0] + y = sign_y * VEHICLE_SIZE_HALF[1] + output.append([c * x - s * y + self.x, s * x + c * y + self.y]) + + return np.array(output) + + +class Vehicle(VehicleState): + """A vehicle class that inherits VehicleState (so, contains the + (continuous) state info.), and also have discrete state variables. (i.e., + atomic propositions (APs)). + + Properties are the same as of VehicleState + + * APs: the class AtomicPropositions that stores all the APs + of the vehicle as True or False. + * waited_count: the number of time steps the vehicle stays + in the stop region; it is -1 when the car is not in the stop region; + """ + + def __init__(self, which_dir, lane=None, v_upper_lim=rd.speed_limit): + """The constructor which sets the properties of the class, with vehicle + randomly posed with random speed. + + Args: + which_dir: the direction of the vehicle. It has to be either + horizontal ('h') or vertical ('v'); + lane: the lane number (0 is the right lane, 1 means the left + lane); if it's equal to np.nan, it chooses 0 or 1 + uniformly randomly. + v_upper_lim: the upper bound of the random speed of the vehicle + """ + self.APs = AtomicPropositions() + self.waited_count = -1 + self.random_reset(which_dir, lane, v_upper_lim) + + def reset(self, which_dir, lane, pos_in_lane, v, psi): + """Reset the properties of the class including vehicle's state + variables; this reset method updates all the atomic propositions and + the discrete state (i.e., waited_count).""" + + VehicleState.__init__(self, which_dir, lane, pos_in_lane, v, psi) + + # Initialization of the discrete states (has_entered_stop_region, + # has_stopped_in_stop_region, and waited_count). + + self.init_local_discrete_var() + + # The following APs are updated globally, not by any method + # within Vehicle class. Initially, highest_priority and + # intersection_is_clear are set to False so that the vehicle + # has to wait before intersection when both APs are not updated. + # the others are also initially set to False. + self.APs['highest_priority'] = False + self.APs['intersection_is_clear'] = False + self.APs['veh_ahead'] = False + self.APs['target_lane'] = False + self.APs['veh_ahead_stopped_now'] = False + self.APs['veh_ahead_too_close'] = False + + def random_reset(self, which_dir, lane=None, v_upper_lim=rd.speed_limit): + """Randomly reset the properties of the class including vehicle's state + variables; the speed is [and the lane number can be] chosen randomly. + + The parameters of the method are exactly same as those in the + constructor. + """ + lane = np.random.randint(0, 2) if lane is None else lane + + if which_dir is 'h': + pos_in_lane = abs(rd.hlanes.start_pos - rd.hlanes.end_pos) \ + * np.random.rand() + rd.hlanes.start_pos + elif which_dir is 'v': + pos_in_lane = abs(rd.vlanes.start_pos - rd.vlanes.end_pos) \ + * np.random.rand() + rd.vlanes.start_pos + else: + raise AssertionError("Vehicle.which_dir has to be either 'h' or 'v'.") + + # v is randomly chosen within the range [0, v_upper_lim] + v = v_upper_lim * np.random.rand() + + self.reset(which_dir, lane, pos_in_lane, v, 0) + + def init_local_discrete_var(self): + if self.which_dir == 'h': + self.APs['has_entered_stop_region'] = True if self.x >= rd.hlanes.stop_region[0] else False + self.APs['has_stopped_in_stop_region'] = True if self.x > rd.hlanes.stop_region[1] else False + else: + self.APs['has_entered_stop_region'] = True if self.y >= rd.vlanes.stop_region[0] else False + self.APs['has_stopped_in_stop_region'] = True if self.y > rd.vlanes.stop_region[1] else False + + #: the number of time steps the vehicle stays in the + # stop region; it is -1 when the car is not in the stop region; + self.waited_count = -1 + + self.update_local_APs() + + # Update waited_count after reset; + # so waited_count is initially either -1 or 0. + self.update_waited_count() + + def update_local_APs(self): + """Update local atomic propositions (related to the vehicle, road + geometry, and road environment); based upon the continuous and the + previous discrete states, all the atomic propositions within the class + are updated, except the global ones ('highest_priority', + 'intersection_is_clear', and 'veh_ahead').""" + + self.APs['stopped_now'] = True if self.v <= pow(10, -10) else False + self.APs[ + 'over_speed_limit'] = True if self.v > rd.speed_limit else False + + if self.which_dir is 'h': + self.APs['on_route'] = True if min( + rd.hlanes.sidewalks) <= self.y <= max( + rd.hlanes.sidewalks) else False + self.APs['lane'] = True if self.y > 0 else False + self.APs[ + 'in_stop_region'] = True if rd.hlanes.stop_region[0] <= self.x <= rd.hlanes.stop_region[1] else False + self.APs[ + 'before_intersection'] = True if self.x < - rd.intersection_width_w_offset / 2.0 else False + self.APs[ + 'has_entered_stop_region'] = self.APs['has_entered_stop_region'] or self.APs['in_stop_region'] + self.APs[ + 'before_but_close_to_stop_region'] = True if rd.hlanes.near_stop_region <= self.x < rd.hlanes.stop_region[0] else False + self.APs['parallel_to_lane'] = True if -0.1 <= self.theta <= 0.1 else False + + elif self.which_dir is 'v': + self.APs['on_route'] = True if min( + rd.vlanes.sidewalks) <= self.x <= max( + rd.vlanes.sidewalks) else False + self.APs['lane'] = True if self.x < 0 else False + self.APs[ + 'in_stop_region'] = True if rd.vlanes.stop_region[0] <= self.y <= rd.vlanes.stop_region[1] else False + self.APs[ + 'before_intersection'] = True if self.y < - rd.intersection_height_w_offset / 2.0 else False + self.APs[ + 'has_entered_stop_region'] = True if rd.vlanes.stop_region[0] <= self.y else False + self.APs[ + 'before_but_close_to_stop_region'] = True if rd.vlanes.near_stop_region <= self.y < rd.vlanes.stop_region[0] else False + theta_v = -np.sign(rd.vlanes.start_pos) * np.pi / 2.0 + self.APs['parallel_to_lane'] = True if theta_v - 0.1 <= self.theta <= theta_v + 0.1 else False + else: + raise AssertionError("Vehicle.which_dir has to be either 'h' or 'v'.") + + self.APs['has_stopped_in_stop_region'] = self.APs['has_stopped_in_stop_region'] or \ + (self.APs['stopped_now'] and self.APs['in_stop_region']) + + if (abs(self.x) <= rd.intersection_width / 2.0 and abs(self.y) < rd.intersection_height_w_offset / 2.0) or \ + (abs(self.y) <= rd.intersection_height / 2.0 and abs(self.x) < rd.intersection_width_w_offset / 2.0): + self.APs['in_intersection'] = True + else: + self.APs['in_intersection'] = False + + def update_waited_count(self): + """ + Increase waited_count if the vehicle is in the stop region on + the same route; otherwise set waited_count = -1. + """ + self.waited_count = -1 if not ( + self.APs['stopped_now'] and self.APs['in_stop_region']) else self.waited_count + 1 + + def step(self, u): + """Calculate the next state and update the other properties for the + given input u. NOTE: the global atomic propositions ('highest_priority' + and 'intersection_is_clear') are not updated. + + Args: + u: a tuple or an array whose first element corresponds to the + acceleration and the second element corresponds to the rate + of change of the steering angle. + """ + + super().step(u) + self.update_local_APs() + self.update_waited_count() + + def is_within_road_boundaries(self, route): + """Checks if this vehicle is within road boundaries given a route. + + Args: + route: route as defined by road_geokinemetry object + + Returns: + True if vehicle is within road boundaries, False otherwise + """ + + bb = self.get_bounding_box() + + # get right and left road boundaries depending on whether 'h' or 'v' + if route.direction is 'h': + left_boundary_line = np.array( + [[route.start_pos, route.sidewalks[0]], + [route.end_pos, route.sidewalks[0]]]) + right_boundary_line = np.array( + [[route.start_pos, route.sidewalks[1]], + [route.end_pos, route.sidewalks[1]]]) + elif route.direction is 'v': + left_boundary_line = np.array( + [[route.sidewalks[0], route.start_pos], + [route.sidewalks[0], route.end_pos]]) + right_boundary_line = np.array( + [[route.sidewalks[1], route.start_pos], + [route.sidewalks[1], route.end_pos]]) + else: + raise ValueError("Route.direction has to be either 'h' or 'v'.") + + # Find side of bounding box w.r.t left boundary + side_wrt_left_boundary = bb_utils.localize_bounding_box_wrt_line( + left_boundary_line, bb) + + # Find side of bounding box w.r.t right boundary + side_wrt_right_boundary = bb_utils.localize_bounding_box_wrt_line( + right_boundary_line, bb) + + # if bb is on same side w.r.t both boundaries, it means it is + # outside the boundaries + offroad = False if side_wrt_left_boundary * side_wrt_right_boundary >= 0 else True + + return offroad diff --git a/high_level_policy_main.py b/high_level_policy_main.py new file mode 100644 index 0000000000000000000000000000000000000000..a9b4108add49ea04d9c05dd76a6a995f273d5130 --- /dev/null +++ b/high_level_policy_main.py @@ -0,0 +1,185 @@ +from env.simple_intersection import SimpleIntersectionEnv +from env.simple_intersection.constants import * +from options.options_loader import OptionsGraph +from backends.kerasrl_learner import DQNLearner +import os +import argparse + + +# TODO: make a separate file for this function. +def high_level_policy_training(nb_steps=25000, load_weights=False, training=True, testing=True, nb_episodes_for_test=10, + max_nb_steps=100, visualize=False, tensorboard=False, + save_path = "highlevel_weights.h5f"): + """ + Do RL of the high-level policy and test it. + Args: + nb_steps: the number of steps to perform RL + load_weights: True if the pre-learned NN weights are loaded (for initializations of NNs) + training: True to enable training + testing: True to enable testing + nb_episodes_for_test: the number of episodes for testing + """ + # initialize the numpy random number generator + np.random.seed() + + if not (isinstance(load_weights, bool) and isinstance(training, bool) and isinstance(testing, bool)): + raise ValueError("Type error: the variable has to be boolean.") + + if not load_weights and not training: + raise ValueError("Both load_weights and training are False: no learning and no loading weights.") + + if not isinstance(nb_steps, int) or nb_steps <= 0: + raise ValueError("nb_steps has to be a positive number.") + + global options + + agent = DQNLearner(input_shape=(50,), nb_actions=options.get_number_of_nodes(), + target_model_update=1e-3, + delta_clip=100, + low_level_policies=options.maneuvers) + + if load_weights: + agent.load_model(save_path) + + if training: + if visualize: + options.visualize_low_level_steps = True + agent.train(options, nb_steps=nb_steps, nb_max_episode_steps=max_nb_steps, tensorboard=tensorboard) + agent.save_model(save_path) + + if testing: + options.set_controller_policy(agent.predict) + agent.test_model(options, nb_episodes=nb_episodes_for_test) + + return agent + + +def high_level_policy_testing(nb_episodes_for_test=100, trained_agent_file="highlevel_weights.h5f", + pretrained=False, visualize=True): + global options + + agent = DQNLearner(input_shape=(50,), nb_actions=options.get_number_of_nodes(), + low_level_policies=options.maneuvers) + + if pretrained: + trained_agent_file = "backends/trained_policies/highlevel/" + trained_agent_file + + agent.load_model(trained_agent_file) + options.set_controller_policy(agent.predict) + + agent.test_model(options, nb_episodes=nb_episodes_for_test, visualize=visualize) + +def evaluate_high_level_policy(nb_episodes_for_test=100, nb_trials=10, + trained_agent_file="highlevel_weights.h5f", pretrained=False, visualize=False): + global options + + agent = DQNLearner(input_shape=(50,), nb_actions=options.get_number_of_nodes(), + low_level_policies=options.maneuvers) + + if pretrained: + trained_agent_file = "backends/trained_policies/highlevel/" + trained_agent_file + + agent.load_model(trained_agent_file) + options.set_controller_policy(agent.predict) + + success_list = [] + termination_reason_list = {} + print ("\nConducting {} trials of {} episodes each".format(nb_trials,nb_episodes_for_test)) + for trial in range(nb_trials): + current_success, current_termination_reason = agent.test_model(options, nb_episodes=nb_episodes_for_test, visualize=visualize) + print("\nTrial {}: success: {}".format(trial+1, current_success)) + success_list.append(current_success) + for reason, count in current_termination_reason.items(): + if reason in termination_reason_list: + termination_reason_list[reason].append(count) + else: + termination_reason_list[reason] = [count] + + success_list = np.array(success_list) + print ("\nSuccess: Avg: {}, Std: {}".format(np.mean(success_list), np.std(success_list))) + print ("Termination reason(s):") + for reason, count_list in termination_reason_list.items(): + count_list = np.array(count_list) + print("{}: Avg: {}, Std: {}".format(reason, + np.mean(count_list), + np.std(count_list))) + +def find_good_high_level_policy(nb_steps=25000, load_weights=False, nb_episodes_for_test=100, + visualize=False, tensorboard=False, save_path="./highlevel_weights.h5f"): + max_num_successes = 0 + current_success = 0 + while current_success < 0.95 * nb_episodes_for_test: + agent = high_level_policy_training(nb_steps=nb_steps, load_weights=load_weights, visualize=visualize, + tensorboard=tensorboard, testing=False) + options.set_controller_policy(agent.predict) + + current_success, termination_reason_counter = agent.test_model(options, nb_episodes=nb_episodes_for_test, visualize=visualize) + + if current_success > max_num_successes: + os.rename(save_path, "highlevel_weights_{}.h5f".format(current_success)) + max_num_successes = current_success + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--train", + help="Train a high level policy with default settings. Always saved in root folder. Always tests after training", + action="store_true") + parser.add_argument( + "--test", + help="Test a saved high level policy. Uses backends/trained_policies/highlevel/highlevel_weights.h5f by default", + action="store_true") + parser.add_argument( + "--evaluate", + help="Evaluate a saved high level policy over n trials. " + "Uses backends/trained_policies/highlevel/highlevel_weights.h5f by default", + action="store_true") + parser.add_argument( + "--saved_policy_in_root", + help="Use saved policies in root of project rather than backends/trained_policies/highlevel/", + action="store_true") + parser.add_argument( + "--load_weights", + help="Load a saved policy from root folder first before training", + action="store_true") + parser.add_argument( + "--tensorboard", + help="Use tensorboard while training", + action="store_true") + parser.add_argument( + "--visualize", + help="Visualize the training. Testing is always visualized. Evaluation is not visualized by default", + action="store_true") + parser.add_argument( + "--nb_steps", + help="Number of steps to train for. Default is 25000", default=25000, type=int) + parser.add_argument( + "--nb_episodes_for_test", + help="Number of episodes to test/evaluate. Default is 20", default=20, type=int) + parser.add_argument( + "--nb_trials", + help="Number of trials to evaluate. Default is 10", default=10, type=int) + parser.add_argument( + "--save_file", + help="filename to save/load the trained policy. Location is as specified by --saved_policy_in_root", + default="highlevel_weights.h5f") + + args = parser.parse_args() + + # load options graph + options = OptionsGraph("config.json", SimpleIntersectionEnv, randomize_special_scenarios=True) + options.load_trained_low_level_policies() + + if args.train: + high_level_policy_training(nb_steps=args.nb_steps, load_weights=args.load_weights, save_path=args.save_file, + tensorboard=args.tensorboard, nb_episodes_for_test=args.nb_episodes_for_test, + visualize=args.visualize) + + if args.test: + high_level_policy_testing(visualize=True, nb_episodes_for_test=args.nb_episodes_for_test, + pretrained=not args.saved_policy_in_root, trained_agent_file=args.save_file) + + if args.evaluate: + evaluate_high_level_policy(visualize=args.visualize, nb_episodes_for_test=args.nb_episodes_for_test, + pretrained=not args.saved_policy_in_root, trained_agent_file=args.save_file, + nb_trials=args.nb_trials) \ No newline at end of file diff --git a/low_level_policy_main.py b/low_level_policy_main.py new file mode 100644 index 0000000000000000000000000000000000000000..291ea825953c3c24f870339b4e95c462b2c008a9 --- /dev/null +++ b/low_level_policy_main.py @@ -0,0 +1,155 @@ +from env.simple_intersection import SimpleIntersectionEnv +from env.simple_intersection.constants import * +from options.options_loader import OptionsGraph +from backends.kerasrl_learner import DDPGLearner + +import argparse + +# TODO: make a separate file for this function. +def low_level_policy_training(maneuver, nb_steps, RL_method='DDPG', + load_weights=False, training=True, testing=True, + visualize=False, nb_episodes_for_test=10, tensorboard=False): + """ + Do RL of the low-level policy of the given maneuver and test it. + Args: + maneuver: the name of the maneuver defined in config.json (e.g., 'default'). + nb_steps: the number of steps to perform RL. + RL_method: either DDPG or PPO2. + load_weights: True if the pre-learned NN weights are loaded (for initializations of NNs). + training: True to enable training. + testing: True to enable testing. + visualize: True to see the graphical outputs during training. + nb_episodes_for_test: the number of episodes for testing. + """ + # initialize the numpy random number generator + np.random.seed() + + if not (isinstance(load_weights, bool) and isinstance(training, bool) and isinstance(testing, bool)): + raise ValueError("Type error: the variable has to be boolean.") + + if not load_weights and not training: + raise ValueError("Both load_weights and training are False: no learning and no loading weights.") + + if not isinstance(maneuver, str): + raise ValueError("maneuver param has to be a string.") + + if not isinstance(nb_steps, int) or nb_steps <= 0: + raise ValueError("nb_steps has to be a positive number.") + + if RL_method not in ['DDPG', 'PPO2']: + raise ValueError("Unsupported RL method.") + + # load options graph + global options + options.set_current_node(maneuver) + options.current_node.reset() + + # TODO: add PPO2 case. + # Use this code when you train a specific maneuver for the first time. + agent = DDPGLearner(input_shape=(options.current_node.get_reduced_feature_length(),), + nb_actions=2, gamma=0.99, + nb_steps_warmup_critic=200, + nb_steps_warmup_actor=200, + lr=1e-3) + + if load_weights: + agent.load_model(maneuver + "_weights.h5f") + + if training: + agent.train(options.current_node, nb_steps=nb_steps, visualize=visualize, verbose=1, + log_interval=nb_steps/4, tensorboard=tensorboard) + agent.save_model(maneuver + "_weights.h5f") # Save the NN weights for reloading them in the future. + + if testing: + # TODO: the graphical window is not closed before completing the test. + options.current_node.learning_mode = 'testing' + agent.test_model(options.current_node, nb_episodes=nb_episodes_for_test) + + +def low_level_policy_testing(maneuver, pretrained=False, nb_episodes_for_test=20): + + # initialize the numpy random number generator + np.random.seed() + + # load options graph + global options + options.set_current_node(maneuver) + options.current_node.reset() + + agent = DDPGLearner(input_shape=(options.current_node.get_reduced_feature_length(),), + nb_actions=2, gamma=0.99, + nb_steps_warmup_critic=200, + nb_steps_warmup_actor=200, + lr=1e-3) + + if pretrained: + agent.load_model("backends/trained_policies/" + maneuver + "/" + maneuver + "_weights.h5f") + else: + agent.load_model(maneuver + "_weights.h5f") + + options.current_node.learning_mode = 'testing' + agent.test_model(options.current_node, nb_episodes=nb_episodes_for_test) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--train", + help="Train a high level policy with default settings. Always saved in root folder. Always tests after training", + action="store_true") + parser.add_argument( + "--option", + help="the option to train. Eg. stop, keeplane, wait, changelane, follow. If not defined, trains all options") + parser.add_argument( + "--test", + help="Test a saved high level policy. Uses backends/trained_policies/highlevel/highlevel_weights.h5f by default", + action="store_true") + parser.add_argument( + "--saved_policy_in_root", + help="Use saved policies in root of project rather than backends/trained_policies/highlevel/", + action="store_true") + parser.add_argument( + "--load_weights", + help="Load a saved policy first before training", + action="store_true") + parser.add_argument( + "--tensorboard", + help="Use tensorboard while training", + action="store_true") + parser.add_argument( + "--visualize", + help="Visualize the training. Testing is always visualized.", + action="store_true") + parser.add_argument( + "--nb_steps", + help="Number of steps to train for. Default is 100000", default=100000, type=int) + parser.add_argument( + "--nb_episodes_for_test", + help="Number of episodes to test. Default is 20", default=20, type=int) + + args = parser.parse_args() + + options = OptionsGraph("config.json", SimpleIntersectionEnv) + + # The experiments of the low-level training can be repeated roughly by executing the code + # (with np_steps=200000 for the better result(s)) + if args.train: + if args.option: + print ("Training {} maneuver...".format(args.option)) + low_level_policy_training(args.option, load_weights=args.load_weights, nb_steps=args.nb_steps, + nb_episodes_for_test=args.nb_episodes_for_test, visualize=args.visualize, + tensorboard=args.tensorboard) + else: + for option_key in options.maneuvers.keys(): + low_level_policy_training(option_key, load_weights=args.load_weights, nb_steps=args.nb_steps, + nb_episodes_for_test=args.nb_episodes_for_test, visualize=args.visualize, + tensorboard=args.tensorboard) + + if args.test: + if args.option: + low_level_policy_testing(args.option, pretrained=not args.saved_policy_in_root, + nb_episodes_for_test=args.nb_episodes_for_test) + else: + for option_key in options.maneuvers.keys(): + low_level_policy_testing(args.option, pretrained=not args.saved_policy_in_root, + nb_episodes_for_test=args.nb_episodes_for_test) \ No newline at end of file diff --git a/mcts.py b/mcts.py new file mode 100644 index 0000000000000000000000000000000000000000..95ef93fdb14e9188339f6b2b306dc5891a86ddd0 --- /dev/null +++ b/mcts.py @@ -0,0 +1,241 @@ +from env.simple_intersection import SimpleIntersectionEnv +from env.simple_intersection.constants import * +from options.options_loader import OptionsGraph +from backends import DDPGLearner, DQNLearner, MCTSLearner +import pickle +import tqdm +import numpy as np +import tqdm + +import sys + +class Logger(object): + def __init__(self): + self.terminal = sys.stdout + self.log = open("logfile.log", "a") + + def write(self, message): + self.terminal.write(message) + self.log.write(message) + self.log.flush() + + def flush(self): + #this flush method is needed for python 3 compatibility. + #this handles the flush command by doing nothing. + #you might want to specify some extra behavior here. + pass + +sys.stdout = Logger() + +# TODO: make a separate file for this function. +def mcts_training(nb_traversals, save_every=20, visualize=False): + """ + Do RL of the low-level policy of the given maneuver and test it. + Args: + nb_traversals: number of MCTS traversals + save_every: save at every these many traversals + visualize: visualization / rendering + """ + + # initialize the numpy random number generator + np.random.seed() + + # load options graph + options = OptionsGraph("mcts_config.json", SimpleIntersectionEnv) + options.load_trained_low_level_policies() + + agent = DQNLearner(input_shape=(50,), nb_actions=options.get_number_of_nodes(), + low_level_policies=options.maneuvers) + + agent.load_model("backends/trained_policies/highlevel/highlevel_weights.h5f") + options.set_controller_args(predictor = agent.get_softq_value_using_option_alias) + options.controller.max_depth = 20 + #options.controller.load_model('backends/trained_policies/mcts/mcts.pickle') + + total_epochs = nb_traversals//save_every + trav_num = 1 + print('Total number of epochs = %d' % total_epochs) + for num_epoch in range(total_epochs): + last_rewards = [] + beg_trav_num = trav_num + for num_traversal in tqdm.tqdm(range(save_every)): + options.controller.curr_node_num = 0 + init_obs = options.reset() + v, all_ep_R = options.controller.traverse(init_obs, visualize=visualize) + # print('Traversal %d: V = %f' % (num_traversal, v)) + # print('Overall Reward: %f\n' % all_ep_R) + last_rewards += [all_ep_R] + trav_num += 1 + options.controller.save_model('mcts_%d.pickle' % (num_epoch)) + success = lambda x: x > 50 + success_rate = np.sum(list(map(success, last_rewards)))/(len(last_rewards)*1.0) + print('success rate: %f' % success_rate) + print('Average Reward (%d-%d): %f\n' % (beg_trav_num, trav_num-1, np.mean(last_rewards))) + +def mcts_evaluation(nb_traversals, num_trials=5, visualize=False): + """ + Do RL of the low-level policy of the given maneuver and test it. + Args: + nb_traversals: number of MCTS traversals + save_every: save at every these many traversals + visualize: visualization / rendering + """ + + # initialize the numpy random number generator + np.random.seed() + + # load options graph + options = OptionsGraph("mcts_config.json", SimpleIntersectionEnv) + options.load_trained_low_level_policies() + + agent = DQNLearner(input_shape=(50,), nb_actions=options.get_number_of_nodes(), + low_level_policies=options.maneuvers) + + agent.load_model("backends/trained_policies/highlevel/highlevel_weights.h5f") + options.set_controller_args(predictor=agent.get_softq_value_using_option_alias) + options.controller.max_depth = 20 + + success_list = [] + print('Total number of trials = %d' % num_trials) + for trial in range(num_trials): + num_successes = 0 + options.controller.load_model('backends/trained_policies/mcts/mcts.pickle') + for num_traversal in tqdm.tqdm(range(nb_traversals)): + options.controller.curr_node_num = 0 + init_obs = options.reset() + v, all_ep_R = options.controller.traverse(init_obs, visualize=visualize) + if all_ep_R > 50: + num_successes += 1 + print("\nTrial {}: success: {}".format(trial + 1, num_successes)) + success_list.append(num_successes) + + print("\nSuccess: Avg: {}, Std: {}".format(np.mean(success_list), np.std(success_list))) + + +def online_mcts(nb_episodes = 10): + # MCTS visualization is off + + # initialize the numpy random number generator + np.random.seed() + + # load options graph + options = OptionsGraph("mcts_config.json", SimpleIntersectionEnv) + options.load_trained_low_level_policies() + + agent = DQNLearner(input_shape=(50,), nb_actions=options.get_number_of_nodes(), + low_level_policies=options.maneuvers) + + agent.load_model("backends/trained_policies/highlevel/highlevel_weights_772.h5f") + options.set_controller_args(predictor = agent.get_softq_value_using_option_alias) + + # Loop + num_successes = 0 + for num_ep in range(nb_episodes): + init_obs = options.reset() + episode_reward = 0 + first_time = True + while not options.env.is_terminal(): + if first_time: + first_time = False + else: + print('Stepping through ...') + features, R, terminal, info = options.controller.step_current_node(visualize_low_level_steps=True) + episode_reward += R + print('Intermediate Reward: %f (ego x = %f)' % (R, options.env.vehs[0].x)) + print('') + if options.controller.can_transition(): + options.controller.do_transition() + print('') + print('EPISODE %d: Reward = %f' % (num_ep, episode_reward)) + print('') + print('') + if episode_reward > 50: num_successes += 1 + + print ("Policy succeeded {} times!".format(num_successes)) + + +def evaluate_online_mcts(nb_episodes=20, nb_trials=5): + # MCTS visualization is off + + # initialize the numpy random number generator + np.random.seed() + + # load options graph + options = OptionsGraph("mcts_config.json", SimpleIntersectionEnv) + options.load_trained_low_level_policies() + + agent = DQNLearner(input_shape=(50,), nb_actions=options.get_number_of_nodes(), + low_level_policies=options.maneuvers) + + agent.load_model("backends/trained_policies/highlevel/highlevel_weights_772.h5f") + options.set_controller_args(predictor=agent.get_softq_value_using_option_alias) + + print ("\nConducting {} trials of {} episodes each".format(nb_trials,nb_episodes)) + success_list = [] + termination_reason_list = {} + for trial in range(nb_trials): + # Loop + num_successes = 0 + termination_reason_counter = {} + for num_ep in range(nb_episodes): + init_obs = options.reset() + episode_reward = 0 + first_time = True + while not options.env.is_terminal(): + if first_time: + first_time = False + else: + print('Stepping through ...') + features, R, terminal, info = options.controller.step_current_node(visualize_low_level_steps=True) + episode_reward += R + print('Intermediate Reward: %f (ego x = %f)' % (R, options.env.vehs[0].x)) + print('') + if terminal: + if 'episode_termination_reason' in info: + termination_reason = info['episode_termination_reason'] + if termination_reason in termination_reason_counter: + termination_reason_counter[termination_reason] += 1 + else: + termination_reason_counter[termination_reason] = 1 + if options.controller.can_transition(): + options.controller.do_transition() + print('') + print('EPISODE %d: Reward = %f' % (num_ep, episode_reward)) + print('') + print('') + if episode_reward > 50: num_successes += 1 + + print("\nTrial {}: success: {}".format(trial+1, num_successes)) + success_list.append(num_successes) + for reason, count in termination_reason_counter.items(): + if reason in termination_reason_list: + termination_reason_list[reason].append(count) + else: + termination_reason_list[reason] = [count] + + success_list = np.array(success_list) + print ("\nSuccess: Avg: {}, Std: {}".format(np.mean(success_list), np.std(success_list))) + print ("Termination reason(s):") + for reason, count_list in termination_reason_list.items(): + count_list = np.array(count_list) + print("{}: Avg: {}, Std: {}".format(reason, + np.mean(count_list), + np.std(count_list))) + +def mcts_visualize(file_name): + with open(file_name, 'rb') as handle: + to_restore = pickle.load(handle) + # TR = to_restore['TR'] + # M = to_restore['M'] + # for key, val in TR.items(): + # print('%s: %f, count = %d' % (key, val/M[key], M[key])) + print(len(to_restore['nodes'])) + +if __name__ == "__main__": + + mcts_training(nb_traversals=10000, save_every=1000, visualize=False) + # mcts_evaluation(nb_traversals=100, num_trials=10, visualize=False) + # for num in range(100): mcts_visualize('timeout_inf_save100/mcts_%d.pickle' % num) + # mcts_visualize('mcts.pickle') + #online_mcts(10) + # evaluate_online_mcts(nb_episodes=20,nb_trials=5) diff --git a/mcts_config.json b/mcts_config.json new file mode 100644 index 0000000000000000000000000000000000000000..859f0fc231d75d58ca693de38902fa54271d39c4 --- /dev/null +++ b/mcts_config.json @@ -0,0 +1,15 @@ +{ + "nodes": { + "wait": "MCTSWait", + "follow": "MCTSFollow", + "stop": "MCTSStop", + "changelane": "MCTSChangeLane", + "keeplane": "MCTSKeepLane" + }, + + "edges": { + "keeplane": "keeplane" + }, + "start_node": "keeplane", + "method": "mcts" +} \ No newline at end of file diff --git a/model_checker/LTL_property_base.py b/model_checker/LTL_property_base.py new file mode 100644 index 0000000000000000000000000000000000000000..85c9d91e888c1e5a6f765986bd35063ee5d6223b --- /dev/null +++ b/model_checker/LTL_property_base.py @@ -0,0 +1,78 @@ +from model_checker.scanner import Scanner +from model_checker.parser import Parser, Errors + + +class LTLPropertyBase(object): + """This is a base class that contains information of an LTL property. + + It encapsulates the model-checking part (see check / check_incremental), + and contains additional information. The subclass needs to describe + specific APdict to be used. + """ + + #: The atomic propositions dict you must set in the subclass. + APdict = None + + def __init__(self, LTL_str, penalty, enabled=True): + """Constructor for LTLPropertyBase. + Assumes property does not change, but property may be applied to multiple traces. + + Args: + LTL_str: the human readable string representation of the LTL property + penalty: the penalty given when the LTL property is violated + """ + + #: This property's checker virtual machine + self.parser = Parser() + + self.str = LTL_str + self.penalty = penalty + self.enabled = enabled + + #: the result of the model checking (TRUE, UNDECIDED, or FALSE) -- + # see 'check' method below. + self.result = Parser.UNDECIDED + + #: initialise the Errors class to give meaningful messages when calling parser.SetProperty + Errors.Init(self.str, "", False, self.parser.getParsingPos, + self.parser.errorMessages) + + self.parser.APdict = self.APdict + self.parser.SetProperty(Scanner(self.str)) + self.result = Parser.UNDECIDED + + def reset_property(self): + """Resets existing property so that it can be applied to a new sequence of states. + Assumes init_property or check were previously called. + """ + self.parser.ResetProperty() + self.result = Parser.UNDECIDED + + def check(self, trace): + """Checks the LTL property w.r.t. the given trace. + + Args: + trace: a sequence of states + + Returns: + result w.r.t. entire trace, in {TRUE, FALSE, UNDECIDED} + """ + + self.result = self.parser.Check(trace) + + return self.result + + def check_incremental(self, state): + """Checks an initialised property w.r.t. the next state in a trace. + Assumes init_property or check were previously called. + + Args: + state: next state (an integer) + + Returns: + incremental result, in {TRUE, FALSE, UNDECIDED} + """ + + self.result = self.parser.CheckIncremental(state) + + return self.result diff --git a/model_checker/__init__.py b/model_checker/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3824ca285ff7976c87e67a9495a05a088cc6b0c0 --- /dev/null +++ b/model_checker/__init__.py @@ -0,0 +1,4 @@ +from .LTL_property_base import LTLPropertyBase +from .parser import Parser, Errors +from .scanner import Scanner +from .atomic_propositions_base import AtomicPropositionsBase diff --git a/model_checker/atomic_propositions_base.py b/model_checker/atomic_propositions_base.py new file mode 100644 index 0000000000000000000000000000000000000000..8c0b191165ab8692a00b5c601622eee96b8b23a8 --- /dev/null +++ b/model_checker/atomic_propositions_base.py @@ -0,0 +1,59 @@ + +class Bits(object): + """A bit-control class that allows us bit-wise manipulation as shown in the + example:: + + bits = Bits() + bits[0] = False + bits[2] = bits[0] + """ + + def __init__(self, value=0): + self._d = value + + def __getitem__(self, index): + return (self._d >> index) & 1 + + def __setitem__(self, index, value): + value = (value & 1) << index + mask = 1 << index + self._d = (self._d & ~mask) | value + + def __getslice__(self, start, end): + mask = 2**(end - start) - 1 + return (self._d >> start) & mask + + def __setslice__(self, start, end, value): + mask = 2**(end - start) - 1 + value = (value & mask) << start + mask = mask << start + self._d = (self._d & ~mask) | value + return (self._d >> start) & mask + + def __int__(self): + return self._d + + +class AtomicPropositionsBase(Bits): + """An AP-control base class for AP-wise manipulation. + the dictionary APdict and its length APdict_len has + to be given in the subclass + """ + + APdict = None + + def __init__(self): + Bits.__init__(self) + self.APdict_len = 0 if self.APdict is None else len(self.APdict) + + def __setitem__(self, index, value): + if index in self.APdict: + index = self.APdict[index] + assert 0 <= index <= self.APdict_len + Bits.__setitem__(self, index, value) + + def __getitem__(self, index): + if index in self.APdict: + index = self.APdict[index] + assert 0 <= index <= self.APdict_len + return Bits.__getitem__(self, index) diff --git a/model_checker/parser.py b/model_checker/parser.py new file mode 100644 index 0000000000000000000000000000000000000000..c714ea03a2a5ee69ebc73af286c913969b2e72c6 --- /dev/null +++ b/model_checker/parser.py @@ -0,0 +1,513 @@ +#------------------------------------------------------------------------- +#Parser.py -- ATG file parser +#Compiler Generator Coco/R, +#Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz +#extended by M. Loeberbauer & A. Woess, Univ. of Linz +#ported from Java to Python by Ronald Longo +#Parser.frame modified for use as incremental model checker by Sean Sedwards +# +#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 2, 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, write to the Free Software Foundation, Inc., +#59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +#As an exception, it is allowed to write an extension of Coco/R that is +#used as a plugin in non-free software. +# +#If not otherwise stated, any source code generated by Coco/R (other than +#Coco/R itself) does not fall under the GNU General Public License. +#-------------------------------------------------------------------------*/ + +import sys + +# Sean changed Scanner to model_checker.scanner +from model_checker.scanner import Token +from model_checker.scanner import Scanner +from model_checker.scanner import Position + +class ErrorRec( object ): + def __init__( self, l, c, s ): + self.line = l + self.col = c + self.num = 0 + self.str = s + + +class Errors( object ): + # errMsgFormat = "file %(file)s : (%(line)d, %(col)d) %(text)s\n" + # Sean removed "file" from message format + errMsgFormat = "%(file)s : (%(line)d, %(col)d) %(text)s\n" + eof = False + count = 0 # number of errors detected + fileName = '' + listName = '' + mergeErrors = False + mergedList = None # PrintWriter + errors = [ ] + minErrDist = 2 + errDist = minErrDist + # A function with prototype: f( errorNum=None ) where errorNum is a + # predefined error number. f returns a tuple, ( line, column, message ) + # such that line and column refer to the location in the + # source file most recently parsed. message is the error + # message corresponging to errorNum. + + @staticmethod + def Init( fn, dir, merge, getParsingPos, errorMessages ): + Errors.theErrors = [ ] + Errors.getParsingPos = getParsingPos + Errors.errorMessages = errorMessages + Errors.fileName = fn + listName = dir + 'listing.txt' + Errors.mergeErrors = merge + if Errors.mergeErrors: + try: + Errors.mergedList = open( listName, 'w' ) + except IOError: + raise RuntimeError( '-- Compiler Error: could not open ' + listName ) + + @staticmethod + def storeError( line, col, s ): + if Errors.mergeErrors: + Errors.errors.append( ErrorRec( line, col, s ) ) + else: + Errors.printMsg( Errors.fileName, line, col, s ) + + @staticmethod + def SynErr( errNum, errPos=None ): + line,col = errPos if errPos else Errors.getParsingPos( ) + msg = Errors.errorMessages[ errNum ] + Errors.storeError( line, col, msg ) + Errors.count += 1 + # Sean added exit + sys.exit( 1 ) + + @staticmethod + def SemErr( errMsg, errPos=None ): + line,col = errPos if errPos else Errors.getParsingPos( ) + Errors.storeError( line, col, errMsg ) + Errors.count += 1 + # Sean added exit + sys.exit( 1 ) + + @staticmethod + def Warn( errMsg, errPos=None ): + line,col = errPos if errPos else Errors.getParsingPos( ) + Errors.storeError( line, col, errMsg ) + + @staticmethod + def Exception( errMsg ): + print (errMsg) + sys.exit( 1 ) + + @staticmethod + def printMsg( fileName, line, column, msg ): + vals = { 'file':fileName, 'line':line, 'col':column, 'text':msg } + sys.stdout.write( Errors.errMsgFormat % vals ) + + @staticmethod + def display( s, e ): + Errors.mergedList.write('**** ') + for c in range( 1, e.col ): + if s[c-1] == '\t': + Errors.mergedList.write( '\t' ) + else: + Errors.mergedList.write( ' ' ) + Errors.mergedList.write( '^ ' + e.str + '\n') + + @staticmethod + def Summarize( sourceBuffer ): + if Errors.mergeErrors: + # Initialize the line iterator + srcLineIter = iter(sourceBuffer) + srcLineStr = srcLineIter.next( ) + srcLineNum = 1 + + try: + # Initialize the error iterator + errIter = iter(Errors.errors) + errRec = errIter.next( ) + + # Advance to the source line of the next error + while srcLineNum < errRec.line: + Errors.mergedList.write( '%4d %s\n' % (srcLineNum, srcLineStr) ) + + srcLineStr = srcLineIter.next( ) + srcLineNum += 1 + + # Write out all errors for the current source line + while errRec.line == srcLineNum: + Errors.display( srcLineStr, errRec ) + + errRec = errIter.next( ) + except: + pass + + # No more errors to report + try: + # Advance to end of source file + while True: + Errors.mergedList.write( '%4d %s\n' % (srcLineNum, srcLineStr) ) + + srcLineStr = srcLineIter.next( ) + srcLineNum += 1 + except: + pass + + Errors.mergedList.write( '\n' ) + Errors.mergedList.write( '%d errors detected\n' % Errors.count ) + Errors.mergedList.close( ) + + sys.stdout.write( '%d errors detected\n' % Errors.count ) + if (Errors.count > 0) and Errors.mergeErrors: + sys.stdout.write( 'see ' + Errors.listName + '\n' ) + + +class Parser( object ): + _EOF = 0 + _proposition = 1 + maxT = 14 + + T = True + x = False + minErrDist = 2 + + UNDEFINED = -1 + FALSE = 0 + UNDECIDED = 1 + TRUE = 2 + + + def Check_old(self, propscanner, trace) : + """Deprecated method to check an entire trace with a new property Scanner. + Includes SetProperty, which includes ResetProperty. + """ + self.SetProperty(propscanner) + for state in trace : + result = self.CheckIncremental(state) + if result != Parser.UNDECIDED : break + return result + + def Check(self, trace) : + """Checks an entire trace w.r.t. an existing property Scanner. + Includes ResetProperty, but not SetProperty. + """ + self.ResetProperty() + for state in trace : + result = self.CheckIncremental(state) + if result != Parser.UNDECIDED : break + return result + + def SetProperty(self, propscanner) : + """Sets the property Scanner that tokenizes the property. + """ + self.scanner = propscanner + self.ResetProperty() + + def ResetProperty(self) : + """Re-iniitializes an existing property Scanner. + """ + self.step = 0 + self.maxfactor = -1 + self.start = self.scanner.t = self.scanner.tokens + + def CheckIncremental(self, state) : + """Checks a new state w.r.t. an existing property Scanner. + Constructs a trace from new states using a new or previous trace list. + If a previous trace list is used, states after index self.step are not valid. + """ + if len(self.trace) <= self.step : + self.trace.append(state) + else : + self.trace[self.step] = state + result = Parser.UNDECIDED + while self.step > self.maxfactor and result == Parser.UNDECIDED : + self.scanner.t = self.start + self.la = self.start + self.Get() + result = self.Property(0) + self.Expect(0) + # print ("step [{}] checked state [{}]".format(self.step, self.maxfactor)) + self.step += 1 + return result + + + + def __init__( self ): + self.scanner = None + self.token = None # last recognized token + self.la = None # lookahead token + self.genScanner = False + self.tokenString = '' # used in declarations of literal tokens + self.noString = '-none-' # used in declarations of literal tokens + self.errDist = Parser.minErrDist + self.trace = [] + + def getParsingPos( self ): + return self.la.line, self.la.col + + def SynErr( self, errNum ): + if self.errDist >= Parser.minErrDist: + Errors.SynErr( errNum ) + + self.errDist = 0 + + def SemErr( self, msg ): + if self.errDist >= Parser.minErrDist: + Errors.SemErr( msg ) + + self.errDist = 0 + + def Warning( self, msg ): + if self.errDist >= Parser.minErrDist: + Errors.Warn( msg ) + + self.errDist = 0 + + def Successful( self ): + return Errors.count == 0; + + def LexString( self ): + return self.token.val + + def LookAheadString( self ): + return self.la.val + + def Get( self ): + while True: + self.token = self.la + # Sean added print + # print (self.la) + self.la = self.scanner.Scan( ) + if self.la.kind <= Parser.maxT: + self.errDist += 1 + break + + self.la = self.token + + def Expect( self, n ): + if self.la.kind == n: + self.Get( ) + else: + self.SynErr( n ) + + def StartOf( self, s ): + return self.set[s][self.la.kind] + + def ExpectWeak( self, n, follow ): + if self.la.kind == n: + self.Get( ) + else: + self.SynErr( n ) + while not self.StartOf(follow): + self.Get( ) + + def WeakSeparator( self, n, syFol, repFol ): + s = [ False for i in range( Parser.maxT+1 ) ] + if self.la.kind == n: + self.Get( ) + return True + elif self.StartOf(repFol): + return False + else: + for i in range( Parser.maxT ): + s[i] = self.set[syFol][i] or self.set[repFol][i] or self.set[0][i] + self.SynErr( n ) + while not s[self.la.kind]: + self.Get( ) + return self.StartOf( syFol ) + + def PyCheck( self ): + """Unused dummy method.""" + result = self.Property(0) + return result + + def Property( self, index ): + """Main property entry point.""" + start = self.la + if self.step == 0 : + start.result = Parser.UNDECIDED + start.index = 0 + if index > start.index : + start.index = index + start.result = Parser.UNDECIDED + if self.StartOf(1): + result = self.Implication(start.index if start.until else index) + if self.step == 0 : start.result = result + if (self.la.kind == 2): + if result == Parser.UNDECIDED : self.SemErr("first argument of U is UNDECIDED") + self.Get( ) + start.until = True # label previous Implication as part of Until + r2 = self.Implication(start.index) + if start.result == Parser.UNDECIDED : # Until not yet FALSE of TRUE + if r2 == Parser.TRUE : + result = start.result = Parser.TRUE + elif result == Parser.FALSE : + start.result = result + else : + result = Parser.UNDECIDED + start.index += 1 + else : # Until is already decided, so result is unchanged + result = start.result + elif self.la.kind == 3: + self.Get( ) + result = self.Implication(start.index) + if start.result == Parser.UNDECIDED : # Finally not yet FALSE or TRUE + if result == Parser.TRUE : # sub-formula is decided TRUE + start.result = result # Finally will remain TRUE + elif result == Parser.FALSE : # sub-formula is decided FALSE, + result = Parser.UNDECIDED # but Finally is not decided, + start.index += 1 # so check next sub-formula + else : # sub-formula is UNDECIDED, + result = Parser.UNDECIDED # so Finally is not decided + start.index = start.index # send the same index to sub-formula + else : # Finally is already decided, so result is unchanged + result = start.result + elif self.la.kind == 4: + self.Get( ) + result = self.Implication(start.index) + if start.result == Parser.UNDECIDED : # Globally not yet FALSE or TRUE + if result == Parser.FALSE : # sub-formula is decided FALSE + start.result = Parser.FALSE # Globally will remain FALSE + elif result == Parser.TRUE : # sub-formula is decided TRUE, + result = Parser.UNDECIDED # but Globally is not decided + start.index += 1 # check the next sub-formula + else : # result is UNDECIDED, so sub-formula is not yet resolved + result = Parser.UNDECIDED # and Globally is also not resolved + start.index = start.index # send the same index to sub-formula + else : # Globally is already decided, so result is unchanged + result = start.result + elif self.la.kind == 5: + self.Get( ) + result = self.Implication(start.index) + if start.index == index+1 : + if result == Parser.UNDECIDED : + result = Parser.UNDECIDED + start.index = start.index + else : + start.result = result + start.index += 1 + elif start.index == index : + start.index += 1 + result = Parser.UNDECIDED + elif index > start.index : + self.SemErr("X has lost synchronization: index = {}, start.index = {}".format(index,start.index)) + else: + self.SynErr(15) + return result + + def Implication( self, index ): + result = self.Disjunction(index) + if (self.la.kind == 6): + self.Get( ) + r2 = self.Disjunction(index) + if result == Parser.FALSE or r2 == Parser.TRUE : + result = Parser.TRUE + elif result == Parser.TRUE and r2 == Parser.FALSE : + result = Parser.FALSE + elif result == Parser.UNDECIDED or r2 == Parser.UNDECIDED : + result = Parser.UNDECIDED + else : + self.SemErr("unrecognized argument") + return result + + def Disjunction( self, index ): + result = self.Conjunction(index) + while self.la.kind == 7: + self.Get( ) + r2 = self.Conjunction(index) + if result == Parser.TRUE or r2 == Parser.TRUE : result = Parser.TRUE + elif result == Parser.UNDECIDED or r2 == Parser.UNDECIDED : result = Parser.UNDECIDED + else : result = Parser.FALSE + + return result + + def Conjunction( self, index ): + result = self.Factor(index) + while self.la.kind == 8: + self.Get( ) + r2 = self.Factor(index) + if result == Parser.FALSE or r2 == Parser.FALSE : result = Parser.FALSE + elif result == Parser.UNDECIDED or r2 == Parser.UNDECIDED : result = Parser.UNDECIDED + else : result = Parser.TRUE + + return result + + def Factor( self, index ): + if index > self.maxfactor : + self.maxfactor = index + neg = False + result = Parser.UNDEFINED + if (self.la.kind == 9): + self.Get( ) + neg = True + if self.la.kind == 1: + if self.la.val not in self.APdict : + self.SemErr("unrecognized proposition") + self.Get( ) + if self.trace[index] & 1 << self.APdict[self.token.val] : + result = Parser.TRUE + else : result = Parser.FALSE + elif self.la.kind == 10: + self.Get( ) + result = Parser.TRUE + elif self.la.kind == 11: + self.Get( ) + result = Parser.FALSE + elif self.la.kind == 12: + self.Get( ) + result = self.Property(index) + self.Expect(13) + else: + self.SynErr(16) + if neg : result = Parser.TRUE - result + return result + + + + def Parse( self, scanner ): + self.scanner = scanner + self.la = Token( ) + self.la.val = u'' + self.Get( ) + self.PyCheck() + self.Expect(0) + + + set = [ + [T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x], + [x,T,x,x, x,x,x,x, x,T,T,T, T,x,x,x] + + ] + + errorMessages = { + + 0 : "EOF expected", + 1 : "proposition expected", + 2 : "\"U\" expected", + 3 : "\"F\" expected", + 4 : "\"G\" expected", + 5 : "\"X\" expected", + 6 : "\"=>\" expected", + 7 : "\"or\" expected", + 8 : "\"and\" expected", + 9 : "\"not\" expected", + 10 : "\"true\" expected", + 11 : "\"false\" expected", + 12 : "\"(\" expected", + 13 : "\")\" expected", + 14 : "??? expected", + 15 : "invalid Property", + 16 : "invalid Factor", + } + + diff --git a/model_checker/scanner.py b/model_checker/scanner.py new file mode 100644 index 0000000000000000000000000000000000000000..5116b4b199fb4035207cf29efcfdd232a6fe3af8 --- /dev/null +++ b/model_checker/scanner.py @@ -0,0 +1,313 @@ + +import sys + +class Token( object ): + def __init__( self ): + self.kind = 0 # token kind + self.pos = 0 # token position in the source text (starting at 0) + self.col = 0 # token column (starting at 0) + self.line = 0 # token line (starting at 1) + self.val = u'' # token value + self.next = None # AW 2003-03-07 Tokens are kept in linked list + self.until = None + self.result = None + self.index = 0 + + def __str__( self ): + return "line {} col {} : {} {}".format(self.line,self.col,self.kind,self.val) + +class Position( object ): # position of source code stretch (e.g. semantic action, resolver expressions) + def __init__( self, buf, beg, len, col ): + assert isinstance( buf, Buffer ) + assert isinstance( beg, int ) + assert isinstance( len, int ) + assert isinstance( col, int ) + + self.buf = buf + self.beg = beg # start relative to the beginning of the file + self.len = len # length of stretch + self.col = col # column number of start position + + def getSubstring( self ): + return self.buf.readPosition( self ) + +class Buffer( object ): + EOF = u'\u0100' # 256 + + def __init__( self, s ): + self.buf = s + self.bufLen = len(s) + self.pos = 0 + self.lines = s.splitlines( True ) + + def Read( self ): + if self.pos < self.bufLen: + # result = unichr(ord(self.buf[self.pos]) & 0xff) # mask out sign bits + # Sean replaced unichr() with chr() for Python 3 compatibility + result = chr(ord(self.buf[self.pos]) & 0xff) # mask out sign bits + self.pos += 1 + return result + else: + return Buffer.EOF + + def ReadChars( self, numBytes=1 ): + result = self.buf[ self.pos : self.pos + numBytes ] + self.pos += numBytes + return result + + def Peek( self ): + if self.pos < self.bufLen: + # return unichr(ord(self.buf[self.pos]) & 0xff) # mask out sign bits + # Sean replaced unichr() with chr() for Python 3 compatibility + return chr(ord(self.buf[self.pos]) & 0xff) # mask out sign bits + else: + return Scanner.buffer.EOF + + def getString( self, beg, end ): + s = '' + oldPos = self.getPos( ) + self.setPos( beg ) + while beg < end: + s += self.Read( ) + beg += 1 + self.setPos( oldPos ) + return s + + def getPos( self ): + return self.pos + + def setPos( self, value ): + if value < 0: + self.pos = 0 + elif value >= self.bufLen: + self.pos = self.bufLen + else: + self.pos = value + + def readPosition( self, pos ): + assert isinstance( pos, Position ) + self.setPos( pos.beg ) + return self.ReadChars( pos.len ) + + def __iter__( self ): + return iter(self.lines) + +class Scanner(object): + EOL = u'\n' + eofSym = 0 + + charSetSize = 256 + maxT = 14 + noSym = 14 + start = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -1] + + + def __str__(self): + return self.buffer.buf + + def __init__( self, s ): + # self.buffer = Buffer( unicode(s) ) # the buffer instance + # Sean removed unicode for Python 3.5 compatibility + self.buffer = Buffer( s ) # the buffer instance + + self.ch = u'\0' # current input character + self.pos = -1 # column number of current character + self.line = 1 # line number of current character + self.lineStart = 0 # start position of current line + self.oldEols = 0 # EOLs that appeared in a comment; + self.NextCh( ) + self.ignore = set( ) # set of characters to be ignored by the scanner + self.ignore.add( ord(' ') ) # blanks are always white space + self.ignore.add(9) + self.ignore.add(10) + self.ignore.add(13) + + # fill token list + self.tokens = Token( ) # the complete input token stream + node = self.tokens + + node.next = self.NextToken( ) + node = node.next + while node.kind != Scanner.eofSym: + if node.kind == self.noSym : + print("{} : ({}, {}) unrecognized symbol".format(self.buffer.buf, node.line, node.col)) + sys.exit() + node.next = self.NextToken( ) + node = node.next + + node.next = node + node.val = u'EOF' + self.t = self.tokens # current token + self.pt = self.tokens # current peek token + + def NextCh( self ): + if self.oldEols > 0: + self.ch = Scanner.EOL + self.oldEols -= 1 + else: + self.ch = self.buffer.Read( ) + self.pos += 1 + # replace isolated '\r' by '\n' in order to make + # eol handling uniform across Windows, Unix and Mac + if (self.ch == u'\r') and (self.buffer.Peek() != u'\n'): + self.ch = Scanner.EOL + if self.ch == Scanner.EOL: + self.line += 1 + self.lineStart = self.pos + 1 + + + + + def Comment0( self ): + level = 1 + line0 = self.line + lineStart0 = self.lineStart + self.NextCh() + if self.ch == '*': + self.NextCh() + while True: + if self.ch == '*': + self.NextCh() + if self.ch == '/': + level -= 1 + if level == 0: + self.oldEols = self.line - line0 + self.NextCh() + return True + self.NextCh() + elif self.ch == Buffer.EOF: + return False + else: + self.NextCh() + else: + if self.ch == Scanner.EOL: + self.line -= 1 + self.lineStart = lineStart0 + self.pos = self.pos - 2 + self.buffer.setPos(self.pos+1) + self.NextCh() + return False + + + def CheckLiteral( self ): + lit = self.t.val + if lit == "U": + self.t.kind = 2 + elif lit == "F": + self.t.kind = 3 + elif lit == "G": + self.t.kind = 4 + elif lit == "X": + self.t.kind = 5 + elif lit == "or": + self.t.kind = 7 + elif lit == "and": + self.t.kind = 8 + elif lit == "not": + self.t.kind = 9 + elif lit == "true": + self.t.kind = 10 + elif lit == "false": + self.t.kind = 11 + + + def NextToken( self ): + while ord(self.ch) in self.ignore: + self.NextCh( ) + if (self.ch == '/' and self.Comment0()): + return self.NextToken() + + self.t = Token( ) + self.t.pos = self.pos + self.t.col = self.pos - self.lineStart + 1 + self.t.line = self.line + state = self.start[ord(self.ch)] + buf = u'' + buf += self.ch + self.NextCh() + + done = False + while not done: + if state == -1: + self.t.kind = Scanner.eofSym # NextCh already done + done = True + elif state == 0: + self.t.kind = Scanner.noSym # NextCh already done + done = True + elif state == 1: + if (self.ch >= 'A' and self.ch <= 'Z' + or self.ch >= 'a' and self.ch <= 'z'): + buf += self.ch + self.NextCh() + state = 1 + elif self.ch == '_': + buf += self.ch + self.NextCh() + state = 2 + else: + self.t.kind = 1 + self.t.val = buf + self.CheckLiteral() + return self.t + elif state == 2: + if (self.ch >= 'A' and self.ch <= 'Z' + or self.ch >= 'a' and self.ch <= 'z'): + buf += self.ch + self.NextCh() + state = 1 + else: + self.t.kind = Scanner.noSym + done = True + elif state == 3: + if self.ch == '>': + buf += self.ch + self.NextCh() + state = 4 + else: + self.t.kind = Scanner.noSym + done = True + elif state == 4: + self.t.kind = 6 + done = True + elif state == 5: + self.t.kind = 12 + done = True + elif state == 6: + self.t.kind = 13 + done = True + + self.t.val = buf + return self.t + + def Scan( self ): + self.t = self.t.next + self.pt = self.t.next + return self.t + + def Peek( self ): + self.pt = self.pt.next + while self.pt.kind > self.maxT: + self.pt = self.pt.next + + return self.pt + + def ResetPeek( self ): + self.pt = self.t + diff --git a/model_checker/simple_intersection/AP_dict.py b/model_checker/simple_intersection/AP_dict.py new file mode 100644 index 0000000000000000000000000000000000000000..0b1ae851d24f00d82e76133e6053189a34540d9d --- /dev/null +++ b/model_checker/simple_intersection/AP_dict.py @@ -0,0 +1,45 @@ + +#: AP_dict_simple_intersection contains all of the atomic propositions on the road +# and the vehicle. +# +# * in_stop_region: True if the veh. is in stop region +# * has_entered_stop_region: True if the veh. has entered or passed the stop +# region +# * before_but_close_to_stop_region: True if the veh. is before but close +# to the stop region +# * stopped_now: True if the veh. is now stopped +# * has_stopped_in_stop_region: True if the veh. has ever stopped in the +# stop region before or now +# * in_intersection: True if the veh. is in the intersection +# * over_speed_limit: True if the veh. is over the speed limit +# * on_route: True if the veh. is on the same route to the initial +# * highest_priority: True if the veh. has the highest priority in +# the intersection +# * intersection_is_clear: True if there is no (other) veh. in the +# intersection +# * veh_ahead: True if there is a veh. ahead close to it +# * lane: True if veh. is on the right lane (or side), False if on +# the left lane (or side) +# * target_lane: True if veh.'s target lane is on the right lane, False if on +# the left; this is equal to lane except the ego vehicle. +# * veh_ahead_stopped_now: True if "veh_ahead and (the veh ahead has stopped now)" + +AP_dict_simple_intersection = { + 'in_stop_region': 0, + 'has_entered_stop_region': 1, + 'before_but_close_to_stop_region': 2, + 'stopped_now': 3, + 'has_stopped_in_stop_region': 4, + 'in_intersection': 5, + 'over_speed_limit': 6, + 'on_route': 7, + 'highest_priority': 8, + 'intersection_is_clear': 9, + 'veh_ahead': 10, + 'lane': 11, + 'parallel_to_lane': 12, + 'before_intersection': 13, + 'target_lane': 14, + 'veh_ahead_stopped_now': 15, + 'veh_ahead_too_close': 16 +} diff --git a/model_checker/simple_intersection/LTL_test.py b/model_checker/simple_intersection/LTL_test.py new file mode 100644 index 0000000000000000000000000000000000000000..4afe03ccd0e43352b4735e3c8b39592981c9f7f3 --- /dev/null +++ b/model_checker/simple_intersection/LTL_test.py @@ -0,0 +1,30 @@ +from . import LTLProperty +from env.simple_intersection import APdict + + +# TODO: Refactor LTL_test to model_checker part. + +def test_model_check(trace): + for i in range(0, len(trace)): + LTL.check_incremental(trace[i]) + print("incremental result:" + str(LTL.result)) + + LTL.check(trace) + print("batch result:" + str(LTL.result) + "\n") + + +LTL = LTLProperty("G (has_entered_stop_region => (in_stop_region U has_stopped_in_stop_region) )", -100) + +trace = [0, 0, 0, 0, 0, 0, 0, + 0 | int(pow(2, AP_dict['has_entered_stop_region'])) | int(pow(2, AP_dict['in_stop_region'])) + ] +print(trace) +test_model_check(trace) + + +trace = [0, 0, 0, 0, 0, 0, 0, + 0 | int(pow(2, AP_dict['has_entered_stop_region'])) | int(pow(2, AP_dict['in_stop_region'])), + 0 | int(pow(2, AP_dict['has_entered_stop_region'])) + ] +print(trace) +test_model_check(trace) diff --git a/model_checker/simple_intersection/__init__.py b/model_checker/simple_intersection/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..f5d252f8036ddf6e54e66c6507e8d11d54cc2db2 --- /dev/null +++ b/model_checker/simple_intersection/__init__.py @@ -0,0 +1 @@ +from .classes import LTLProperty, AtomicPropositions \ No newline at end of file diff --git a/model_checker/simple_intersection/classes.py b/model_checker/simple_intersection/classes.py new file mode 100644 index 0000000000000000000000000000000000000000..2de7b62f8d7e6edee40db6a4afefe48bfdc7a04a --- /dev/null +++ b/model_checker/simple_intersection/classes.py @@ -0,0 +1,30 @@ +from model_checker import LTLPropertyBase, AtomicPropositionsBase +from .AP_dict import AP_dict_simple_intersection + +# TODO: classes.py is not a good name. Spliti the two classes into separate files and rename them. +class AtomicPropositions(AtomicPropositionsBase): + """ An AP-control class for AP-wise manipulation as shown in the + example: + + APs = AtomicPropositions() + APs[0] = False # this is same as + # APs[AP_dict['stop_region']] = False + APs['in_stop_region'] = False # both expressions are the same + + Requires: + Index in [...] is an integer should be in the range + {0,1,2, ..., AP_dict_len}. + + """ + APdict = AP_dict_simple_intersection + + +class LTLProperty(LTLPropertyBase): + """ is a class that contains information of an LTL property in + simple_intersection road scenario. + + It encapsulates the model-checking part and contains additional + information. + """ + APdict = AP_dict_simple_intersection + diff --git a/options/__init__.py b/options/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/options/options_loader.py b/options/options_loader.py new file mode 100644 index 0000000000000000000000000000000000000000..6a40affcb28b28cd3a04e4094e8bbdcb8b2642e7 --- /dev/null +++ b/options/options_loader.py @@ -0,0 +1,165 @@ +import json +from .simple_intersection.maneuvers import * +from .simple_intersection.mcts_maneuvers import * +from backends import RLController, DDPGLearner, MCTSLearner, OnlineMCTSController, ManualPolicy + + +class OptionsGraph: + """ + Represent the options graph as a graph like structure. The configuration + is specified in a json file and consists of the following specific values: + + * nodes: dictionary of policy node aliases -> maneuver classes + * edges: dictionary such that it has key value pairs which represent + edges between policy node aliases + * starting_node: ego's starting node + """ + #: visualization flag + visualize_low_level_steps = False + + def __init__(self, json_path, env_class, *env_args, **env_kwargs): + """ + Constructor for the options graph. + + Args: + json_path: path to the json file which stores the configuration + for this options graph + env_class: the gym compliant environment class + env_args: arguments to pass when initializing the env + env_kwargs: named arguments to pass when initializing the env + """ + + self.config = json.load(open(json_path)) + + #: Gym compliant environment instance. This instance also has a + # back-reference to this options instance. + self.env = env_class(*env_args, **env_kwargs) + #: nodes of the graph + self.nodes = self.config["nodes"] + #: edges of the graph + self.edges = self.config["edges"] + #: adjacency list from the graph + self.adj = {key: [] for key, value in self.nodes.items()} + for i, j in self.edges.items(): + self.adj[i].append(j) + + #: Hold the different maneuver objects + # Each maneuver object also has a back-reference to this options + # instance. TODO: allow for passing arguments to maneuver + # objects at init, for example, noise + # TODO: Change name maneuver as it is SimpleIntersectionEnv specific. + self.maneuvers = {key: globals()[value](self.env) for key, value in self.nodes.items()} + self.maneuvers_alias = list(self.maneuvers.keys()) # so that maneuver can be referenced using an int + + #: starting node + # TODO: reimplement if needed for multi-agent training? + self.start_node_alias = self.config["start_node"] + + #: high level policy over low level policies + # possible classes : rl + if self.config["method"] == "rl": + self.controller = RLController(self.env, self.maneuvers, self.start_node_alias) + elif self.config["method"] == "manual": + self.controller = ManualPolicy(self.env, self.maneuvers, self.adj, self.start_node_alias) + elif self.config["method"] == "mcts": + self.controller = MCTSLearner(self.env, self.maneuvers, self.start_node_alias) + elif self.config["method"] == "online_mcts": + self.controller = OnlineMCTSController(self.env, self.maneuvers, self.start_node_alias) + else: + raise Exception(self.__class__.__name__ + \ + "Controller to be used not specified") + + def step(self, option): + """Complete an episode using specified option. This assumes that + the manager's env is at a place where the option's initiation + condition is met. + + Args: + option: index of high level option to be executed + """ + + #check if the incoming option is an integer or an option alias(string) + try: + option = int(option) + option_alias = self.maneuvers_alias[option] + except ValueError: + option_alias = option + + self.controller.set_current_node(option_alias) + + # execute whole maneuver + return self.controller.step_current_node(visualize_low_level_steps=self.visualize_low_level_steps) + + def reset(self): + """Reset the environment. This function may be needed to reset the + environment for eg. after an MCTS rollout and update. Also reset the + controller to root node. + + Returns whatever the environment's reset returns. + """ + + self.controller.set_current_node(self.start_node_alias) + return self.env.reset() + + def set_controller_policy(self, policy): + """Sets the trained controller policy as a function which takes in feature vector and returns + an option index(int). By default, trained_policy is None + + Args: + policy: a function which takes in feature vector and returns an option index(int) + """ + self.controller.set_trained_policy(policy) + + def set_controller_args(self, **kwargs): + """Sets custom arguments depending on the chosen controller + + Args: + **kwargs: dictionary of args and values + """ + self.controller.set_controller_args(**kwargs) + + + def execute_controller_policy(self): + """Performs low level steps and transitions to other nodes using controller transition policy. + + Returns state after one step, step reward, episode_termination_flag, info + """ + if self.controller.can_transition(): + self.controller.do_transition() + + return self.controller.low_level_step_current_node() + + def set_current_node(self, node_alias): + """Sets the current node for controller. Used for training/testing a particular node + + Args: + node_alias: alias of the node as per config file + """ + self.controller.set_current_node(node_alias) + + @property + def current_node(self): + return self.controller.current_node + + # TODO: specify values using config file, else use these defaults + # TODO: error handling + def load_trained_low_level_policies(self): + for key, maneuver in self.maneuvers.items(): + agent = DDPGLearner(input_shape=(maneuver.get_reduced_feature_length(),), + nb_actions=2, gamma=0.99, + nb_steps_warmup_critic=200, + nb_steps_warmup_actor=200, + lr=1e-3) + agent.load_model("backends/trained_policies/" + key + "/" + key + "_weights.h5f") + maneuver.set_low_level_trained_policy(agent.predict) + + if self.config["method"] == "mcts": + maneuver.timeout = np.inf + + def get_number_of_nodes(self): + return len(self.maneuvers) + + def render(self, mode='human'): + self.env.render() + + diff --git a/options/simple_intersection/__init__.py b/options/simple_intersection/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/options/simple_intersection/maneuver_base.py b/options/simple_intersection/maneuver_base.py new file mode 100644 index 0000000000000000000000000000000000000000..93d7a6face976106c2dafc79487f14023d4278eb --- /dev/null +++ b/options/simple_intersection/maneuver_base.py @@ -0,0 +1,344 @@ +import numpy as np +import gym +import env.simple_intersection.road_geokinemetry as rd +from env.simple_intersection.constants import DT, MAX_ACCELERATION, MAX_STEERING_ANGLE_RATE, MAX_STEERING_ANGLE +from env import EpisodicEnvBase + + +class ManeuverBase(EpisodicEnvBase): + """The abstract class from which each maneuver is defined and inherited. + + In all of the maneuvers, we assume that the ego-vehicle is supposed + to drive on the 'h'orizontal route. + """ + + trained_policy = None + + #: learning mode of the low-level policy. + # It can be 'training' or for validation after learning, 'testing'. + # In reset, the scenario is generated depending on learning_mode. + learning_mode = 'training' + + #: timeout (i.e., time horizon for termination) + # By default, the time-out horizon is 1 as in Paxton et. al (2017). + timeout = 1 + + #: the option specific weight vector for cost of driving, which is + # substituted to self.env.cost_weights in every step call + # (with some modification on the action weights if + # _extra_action_weights_flag = True); note that a cost is defined + # as a negative reward, so a cost will be summed up to the reward + # with subtraction. + _cost_weights = ( 20.0*1e-3, 1.0*1e-3, 0.25*1e-3, 1.0*1e-3, + 100.0*1e-3, 0.1*1e-3, 0.25*1e-3, 0.1*1e-3) + + _extra_r_terminal = None + _extra_r_on_timeout = None + + #: the flag being False when _cost_weights is used without + # modification; If True, then the action parts of _cost_weights + # are increased for some edge cases (see the step method). + _extra_action_weights_flag = True + + #: the extra weights on the actions added to _cost_weights + # for some edge cases when _extra_action_weights_flag = True. + _extra_action_weights = (100, 20) + + #: gives a reward equal to _extra_r_on_timeout when maneuver times out + _give_reward_on_timeout = True + + #: enable the property for low-level policy training only, if any. + # this flag is useful in low-level policy learning + # (see maneuvers.py. In ManeuverBase, this plays no role). + _enable_low_level_training_properties = False + + #: the additional reward given to the high-level learner for choosing + # the maneuver (each maneuver is an action in the high-level); + # plays no role in low-level training. + high_level_extra_reward = 0 + + def __init__(self, env): + """Constructor for the maneuver. + + Args: + env: the SimpleIntersectionEnv reference + """ + + super().__init__() + + #: the associated environment + # TODO: make a flag parameter for the deep-copy option of env. + self.env = env + self._reset_model_checker(env.ego.APs) + + #: target_lane for each maneuver is the current lane + # by default and is substituted to self.env.target_lane + # in every step call + self._target_lane = self.env.ego.APs['lane'] + + #: the reference velocity for each maneuver is + # the speed limit of the road by default and is substituted + # to self.env.v_ref in every step call + self._v_ref = rd.speed_limit + + # (re-)initialize the parameters including _target_lane, _v_ref, + # _cost_weights, if necessary in the subclass. + self._init_param() + + #: time_out_horizon is the maximal time at which a maneuver + # must terminate, divided by DT. + self.__time_out_horizon = np.round(self.timeout / DT) + self.__time_out_count = 0 + + def step(self, u_ego): + """The main function, increases timeout count and calculates the reward + based on model- and collision-checking. + + Returns: a tuple (reduced_features_tuple, R, terminal, info), where + reduced_features_tuple: the features tuple after _features_dim_reduction; + R: the reward for the transition; + terminal: True if the next state is the terminal state, False if not; + info: log info. + """ + + # Substitute the maneuver-specific variables to those in self.env + self.env.v_ref = self._v_ref + self.env.target_lane = self._target_lane + + if self._extra_action_weights_flag: + ego = self.env.ego + weights = list(self._cost_weights) + if ego.v <= 0 and u_ego[0] < 0: + weights[4] += self._extra_action_weights[0] * abs(u_ego[0]) / MAX_ACCELERATION + + if abs(ego.psi) >= MAX_STEERING_ANGLE and \ + np.sign(ego.psi) == np.sign(u_ego[1]): + weights[6] += self._extra_action_weights[1] * abs(u_ego[1]) / MAX_STEERING_ANGLE_RATE + + self.env.cost_weights = tuple(weights) + + else: + self.env.cost_weights = self._cost_weights + + info = dict() + + features, env_r, env_terminal, env_info = self.env.step(u_ego) + + info.update(env_info) + # _mc_AP has to be set before super().step. + self._set_mc_AP(self.env.ego.APs) + + self.__time_out_count += 1 + + # the super class reward = self._r_terminal + # which is added to the final reward (see below). + _, _, super_terminal, super_info = super().step(u_ego) + + info.update(super_info) + terminal = env_terminal or super_terminal + + if env_terminal: + if self.env.r_terminal is not None: + # Remove the terminal reward from env_r as it is re-evaluated + # through _terminal_reward_superposition below. + env_r -= self.env.r_terminal + self._terminal_reward_superposition(self.env.r_terminal) + self._update_param() + + extra_termination_cond = self.extra_termination_condition + if self.timeout_happened or extra_termination_cond: + if extra_termination_cond: + # in this case, no additional reward by Default + # (i.e., self._extra_r_terminal = None by default). + self._terminal_reward_superposition(self._extra_r_terminal) + info['maneuver_termination_reason'] = 'extra_termination_condition' + if self.timeout_happened: + if self._give_reward_on_timeout: + # in this case, no additional reward by Default + # (i.e., self._extra_r_on_timeout = None by default). + self._terminal_reward_superposition(self._extra_r_on_timeout) + info['maneuver_termination_reason'] = 'timeout' + terminal = True + + reward = env_r + + if self._r_terminal is not None: + reward += self._r_terminal + + return self._features_dim_reduction(features), reward, terminal, info + + def get_reduced_feature_length(self): + """ + get the length of the feature tuple after applying _features_dim_reduction. + :return: + """ + return len(self.get_reduced_features_tuple()) + + def get_reduced_features_tuple(self): + return self._features_dim_reduction(self.env.get_features_tuple()) + + @property + def observation_space(self): + length = self.get_reduced_feature_length() + return gym.spaces.Box(low=-np.finfo(np.float32).max, high=np.finfo(np.float32).max, shape=(length,)) + + @property + def action_space(self): + return gym.spaces.Box(low=np.array([-MAX_ACCELERATION, -MAX_STEERING_ANGLE_RATE]), high=np.array([MAX_ACCELERATION, MAX_STEERING_ANGLE_RATE])) + + def reset(self): + """Gym compliant reset function. + + Reset the environment as specified by the + generate_learning_scenario() in this class and the maneuver, + and then return the initial features tuple. + + Returns: + features tuple after _features_dim_reduction + + Reinitialize the maneuver and the environment with whatever parameters + it was initially called with. This will be implemented in each subclass maneuver. + (to reset the maneuver part within the implementation of this method + in the subclass, use reset_maneuver below after resetting the environment). + Use this function only for the low-level policy learning of each maneuver. + """ + if self.learning_mode == 'training': + self.generate_learning_scenario() + elif self.learning_mode == 'testing': + self.generate_validation_scenario() + else: + raise ValueError("learning_mode has to be either training or testing") + + self.reset_maneuver() + + # TODO: make this warning as a log, not a direct print. + if not self.initiation_condition: + print('\nWarning: the maneuver ' + self.__class__.__name__ + + ' is ready but the initiation condition is not satisfied.') + + return self._features_dim_reduction(self.env.get_features_tuple()) + + def reset_maneuver(self): + self.__init__(self.env) + + def render(self, mode='human'): + self.env.render() # Do nothing but calling self.env.render() + + def set_low_level_trained_policy(self, trained_policy): + """Sets the trained policy as a function which takes in feature vector and returns + an action (a, dot_psi). By default, trained_policy is None + """ + self.trained_policy = trained_policy + + @property + def termination_condition(self): + return self.extra_termination_condition or self.timeout_happened or \ + super().termination_condition or self.env.termination_condition + + # A series of virtual functions that might need to be rewritten + # (if necessary) in each subclass for each specific maneuver. + + @property + def extra_termination_condition(self): + return False + + @staticmethod + def _features_dim_reduction(features_tuple): + """ + Reduce the dimension of the features in step and reset. + + Param: features_tuple: a tuple obtained by e.g., self.env.get_features_tuple() + Return: the reduced features tuple (by default, it returns features_tuple itself. + """ + return features_tuple + + # TODO: Determine whether this method depends on the external features_tuple or for simplicity, define and use a features_tuple within the class. + def low_level_policy(self, reduced_features_tuple): + """the low level policy as a map from a feature vector to an action + (a, dot_psi). By default, it'll call low_level_manual_policy below + if it's implemented in the subclass. + """ + if self.trained_policy is None: + return self._low_level_manual_policy() + else: + return self.trained_policy(reduced_features_tuple) + + def _low_level_manual_policy(self): + """the manually-defined low level policy as a map from a feature vector to an action + (a, dot_psi). _low_level_policy will call this manual policy unless modified in the subclass. + Implement this in the subclass whenever necessary. + """ + raise NotImplemented(self.__class__.__name__ + "._low_Level_manual_policy is not implemented.") + + def generate_learning_scenario(self): + raise NotImplemented(self.__class__.__name__ + ".generate_learning_scenario is not implemented.") + + def generate_validation_scenario(self): + # If not implemented, use learning scenario. + self.generate_learning_scenario() + + def generate_scenario(self, enable_LTL_preconditions=True, timeout=np.infty, **kwargs): + """generates the scenario for low-level policy learning and validation. This method + will be used in generate_learning_scenario and generate_validation_scenario in + the subclasses. + + Param: + enable_LTL_preconditions: whether to enable LTL preconditions in the maneuver or not + timeout: the timeout for the scenario (which is infinity by default) + **kwargs: the arguments of generate_scenario of the environment. + """ + + kwargs.setdefault('n_others_range', (0, 0)) + kwargs.setdefault('ego_pos_range', (rd.hlanes.start_pos, rd.hlanes.end_pos)) + + while not self.env.generate_scenario(**kwargs): + pass + + if enable_LTL_preconditions: + self.env.enable_LTL_preconditions() + else: + self.env.disable_LTL_preconditions() + + self.timeout = timeout + + @property + def initiation_condition(self): + """this method specifies the initiation condition (or in a technical + term, initiation set) of the maneuver. + + Returns True if the condition is satisfied, and False otherwise. + """ + + return not (self.env.termination_condition or self.violation_happened) and \ + self.extra_initiation_condition + + @property + def extra_initiation_condition(self): + return True + + @property + def timeout_happened(self): + return self.__time_out_count >= self.__time_out_horizon + + @property + def goal_achieved(self): + """Check whether the ego vehicle achieves the goal of the maneuver or + not. + + By default, there is no goal, so the ego vehicle never achieves + it (i.e., goal_achieved is always False). + """ + + return False + + def _init_param(self): + """Initialize parameters in the constructor and 'ready' methods before + applying the maneuver.""" + + return # do nothing unless specified in the subclass + + def _update_param(self): + """Update the parameters in the gym-compliant 'step' method above + """ + + return # do nothing unless specified in the subclass diff --git a/options/simple_intersection/maneuvers.py b/options/simple_intersection/maneuvers.py new file mode 100644 index 0000000000000000000000000000000000000000..bb6a7649a80313b0900291da7f23a1dc6f35fb39 --- /dev/null +++ b/options/simple_intersection/maneuvers.py @@ -0,0 +1,254 @@ +from .maneuver_base import ManeuverBase +from env.simple_intersection.constants import * +import env.simple_intersection.road_geokinemetry as rd +from env.simple_intersection.features import extract_ego_features, extract_other_veh_features +from model_checker.simple_intersection import LTLProperty + +import numpy as np +# TODO: separate out into different files?? is it really needed? + + +class KeepLane(ManeuverBase): + + def _init_param(self): + self._v_ref = rd.speed_limit + self._target_lane = self.env.ego.APs['lane'] + + def _init_LTL_preconditions(self): + self._LTL_preconditions.append(LTLProperty("G ( not veh_ahead )", 0)) + self._LTL_preconditions.append(LTLProperty("G ( not stopped_now )", 200, + self._enable_low_level_training_properties)) + self._LTL_preconditions.append( + LTLProperty("G ( (lane and target_lane) or (not lane and not target_lane) )", 200, + self._enable_low_level_training_properties)) + + def generate_learning_scenario(self): + self.generate_scenario(enable_LTL_preconditions=False, + ego_pos_range=(rd.hlanes.start_pos, rd.hlanes.end_pos), + ego_perturb_lim=(rd.hlanes.width / 4, np.pi / 6), + ego_heading_towards_lane_centre=True) + # the goal reward and termination is led by the SimpleIntersectionEnv + self.env._terminate_in_goal = True + self.env._reward_in_goal = 200 + self._enable_low_level_training_properties = True + + @staticmethod + def _features_dim_reduction(features_tuple): + return extract_ego_features(features_tuple, + 'pos_near_stop_region', + 'v', 'v_ref', 'e_y', + 'psi', 'theta', 'acc', 'psi_dot') + + +class Stop(ManeuverBase): + + _terminate_in_goal = True + _reward_in_goal = None + + def _init_param(self): + self._set_v_ref() + self._target_lane = self.env.ego.APs['lane'] + + def _init_LTL_preconditions(self): + self._LTL_preconditions.append(LTLProperty("G ( not has_stopped_in_stop_region )", + self._penalty(self._reward_in_goal))) + + self._LTL_preconditions.append( + LTLProperty("G ( (before_but_close_to_stop_region or in_stop_region) U has_stopped_in_stop_region )", 0)) + + self._LTL_preconditions.append( + LTLProperty("G ( not stopped_now U in_stop_region )", 200, + self._enable_low_level_training_properties)) + + self._LTL_preconditions.append( + LTLProperty("G ( (lane and target_lane) or (not lane and not target_lane) )", 200, + self._enable_low_level_training_properties)) + + def _update_param(self): + self._set_v_ref() + + def _set_v_ref(self): + self._v_ref = rd.speed_limit + x = self.env.ego.x + if x <= rd.hlanes.near_stop_region: + self._v_ref = rd.speed_limit + elif x <= rd.hlanes.stop_region_centre: + self._v_ref = - (rd.speed_limit / abs(rd.hlanes.near_stop_region)) * (x - rd.hlanes.stop_region_centre) + else: + self._v_ref = 0 + + def generate_learning_scenario(self): + self.generate_scenario(ego_pos_range=(rd.hlanes.near_stop_region, - rd.intersection_width_w_offset / 2), + ego_perturb_lim=(rd.hlanes.width / 4, np.pi / 6), + ego_heading_towards_lane_centre=True) + self._reward_in_goal = 200 + self._enable_low_level_training_properties = True + + def _low_level_manual_policy(self): + return self.env.aggressive_driving_policy(EGO_INDEX) + + @staticmethod + def _features_dim_reduction(features_tuple): + return extract_ego_features(features_tuple, + 'pos_near_stop_region', + 'v', 'v_ref', 'e_y', + 'psi', 'theta', 'acc', 'psi_dot', + 'not_in_stop_region') + + +class Wait(ManeuverBase): + + _terminate_in_goal = True + _reward_in_goal = None + + def _init_LTL_preconditions(self): + self._LTL_preconditions.append( + LTLProperty("G ( (in_stop_region and stopped_now) U highest_priority)", 0)) + + self._LTL_preconditions.append( + LTLProperty("G ( not (in_intersection and highest_priority) )", + self._penalty(self._reward_in_goal))) + + def _init_param(self): + ego = self.env.ego + self._v_ref = rd.speed_limit if self.env.ego.APs['highest_priority'] else 0 + self._target_lane = ego.APs['lane'] + + self._n_others_with_higher_priority = 0 + for veh in self.env.vehs[1:]: + if veh.waited_count > ego.waited_count: + self._n_others_with_higher_priority += 1 + + def _update_param(self): + if self.env.ego.APs['highest_priority']: + self._v_ref = rd.speed_limit + + def generate_learning_scenario(self): + n_others = np.random.randint(0, 3) + self.generate_scenario(enable_LTL_preconditions=True, timeout=62, + n_others_range=(n_others, n_others), + ego_pos_range=rd.hlanes.stop_region, + n_others_stopped_in_stop_region=n_others, + ego_v_upper_lim=0, ego_perturb_lim=(rd.hlanes.width / 4, np.pi / 6), + ego_heading_towards_lane_centre=True) + + max_waited_count = 0 + for veh in self.env.vehs[1:]: + max_waited_count = max(max_waited_count, veh.waited_count) + + self._extra_action_weights_flag = False + self.env.ego.waited_count = np.random.randint(0, max_waited_count + 21) + self.env.init_APs(False) + + self._reward_in_goal = 200 + + @staticmethod + def _features_dim_reduction(features_tuple): + return extract_ego_features(features_tuple, + 'v', 'v_ref', 'psi', 'theta', + 'acc', 'psi_dot', 'pos_stop_region', + 'intersection_is_clear', 'highest_priority') + + +class ChangeLane(ManeuverBase): + + min_y_distance = rd.hlanes.width / 4 + + _terminate_in_goal = True + _reward_in_goal = None + + _violation_penalty_in_low_level_training = None + + high_level_extra_reward = -20 + + def _init_param(self): + self._v_ref = rd.speed_limit + self._target_lane = not self.env.ego.APs['lane'] + self._terminate_in_goal = True + + def _init_LTL_preconditions(self): + self._LTL_preconditions.append( + LTLProperty("G ( on_route and not over_speed_limit )", + self._violation_penalty_in_low_level_training, + self._enable_low_level_training_properties)) + self._LTL_preconditions.append(LTLProperty("G ( not stopped_now )", + self._violation_penalty_in_low_level_training, + self._enable_low_level_training_properties)) + @property + def goal_achieved(self): + ego = self.env.ego + APs = self.env.ego.APs + on_other_lane = APs['lane'] == self._target_lane + achieved_y_displacement = np.sign(ego.y) * \ + (ego.y - rd.hlanes.centres[APs['target_lane']]) >= - self.min_y_distance + return on_other_lane and APs['on_route'] and \ + achieved_y_displacement and APs['parallel_to_lane'] + + def _low_level_manual_policy(self): + return self.env.aggressive_driving_policy(EGO_INDEX) + + def generate_learning_scenario(self): + self.generate_scenario(enable_LTL_preconditions=False, timeout=15, + ego_pos_range=(rd.hlanes.start_pos, rd.hlanes.end_pos), + ego_lane=np.random.choice([0, 1]), + ego_perturb_lim=(rd.hlanes.width/5, np.pi/6)) + # print('our range was %s, %s, ego at %s' % (before_intersection, after_intersection, self.env.ego.x)) + self._reward_in_goal = 200 + self._violation_penalty_in_low_level_training = 200 + self._enable_low_level_training_properties = True + + # TODO: It is not a good idea to specify features by numbers, as the list + # of features is ever changing. We should specify them by strings. + @staticmethod + def _features_dim_reduction(features_tuple): + return extract_ego_features(features_tuple, + 'v', 'v_ref', 'e_y', 'psi', + 'v tan(psi/L)', 'theta', 'lane', + 'acc', 'psi_dot') + + +class Follow(ManeuverBase): + + _target_veh_i = None + _penalty_for_out_of_follow_range = None + + def _init_LTL_preconditions(self): + self._LTL_preconditions.append( + LTLProperty("G ( veh_ahead )", self._penalty_for_out_of_follow_range)) + + self._LTL_preconditions.append( + LTLProperty("G ( (lane and target_lane) or (not lane and not target_lane) )", + self._penalty_for_out_of_follow_range)) + + self._LTL_preconditions.append( + LTLProperty("G ( not stopped_now U veh_ahead_stopped_now)", 200, + self._enable_low_level_training_properties)) + + self._LTL_preconditions.append( + LTLProperty("G ( not veh_ahead_too_close )", 200, + self._enable_low_level_training_properties)) + + def generate_learning_scenario(self): + self.generate_scenario(enable_LTL_preconditions=False, + n_others_range=(1, 1), + ego_perturb_lim=(rd.hlanes.width/2, np.pi/4), + veh_ahead_scenario=True) + self.env._terminate_in_goal = False + self._penalty_for_out_of_follow_range = 200 + self._enable_low_level_training_properties = True + + def _update_param(self): + self._target_veh_i, _ = self.env.get_V2V_distance() + + def _low_level_manual_policy(self): + return self.env.aggressive_driving_policy(EGO_INDEX) + + def _features_dim_reduction(self, features_tuple): + ego_features = extract_ego_features(features_tuple, + 'v', 'v_ref', 'e_y', 'psi', 'v tan(psi/L)', 'theta', 'lane', 'e_y,lane', + 'acc', 'psi_dot') + if self._target_veh_i is not None: + return ego_features + extract_other_veh_features(features_tuple, + self._target_veh_i, 'rel_x', 'rel_y', 'v', 'acc') + else: + return ego_features + (0.0, 0.0, 0.0, 0.0) diff --git a/options/simple_intersection/mcts_maneuvers.py b/options/simple_intersection/mcts_maneuvers.py new file mode 100644 index 0000000000000000000000000000000000000000..c4e7c42dbb2f52767bbbc96f5d0a343bf972e805 --- /dev/null +++ b/options/simple_intersection/mcts_maneuvers.py @@ -0,0 +1,290 @@ +from .maneuver_base import ManeuverBase +from env.simple_intersection.constants import * +import env.simple_intersection.road_geokinemetry as rd +from env.simple_intersection.features import extract_ego_features, extract_other_veh_features +from model_checker.simple_intersection import LTLProperty + +import numpy as np +# TODO: separate out into different files?? is it really needed? + + +class MCTSKeepLane(ManeuverBase): + + def _init_param(self): + self._v_ref = rd.speed_limit + self._target_lane = self.env.ego.APs['lane'] + self._extra_action_weights_flag = True + + @property + def extra_initiation_condition(self): + return not self.env.ego.APs['veh_ahead'] + + def generate_learning_scenario(self): + self.generate_scenario(enable_LTL_preconditions=False, + ego_pos_range=(rd.intersection_width_w_offset/2, rd.hlanes.end_pos), + ego_perturb_lim=(rd.hlanes.width / 4, np.pi / 12), + ego_heading_towards_lane_centre=True) + self.env._terminate_in_goal = True + self.env._reward_in_goal = 200 + + def generate_validation_scenario(self): + self.generate_scenario(enable_LTL_preconditions=False, timeout=10, + ego_perturb_lim=(0, 0), + ego_heading_towards_lane_centre=True) + self.env._terminate_in_goal = True + self.env._reward_in_goal = 200 + + @staticmethod + def _features_dim_reduction(features_tuple): + return features_tuple[0:5] + features_tuple[6:7] + features_tuple[9:11] + + +class MCTSStop(ManeuverBase): + + _terminate_in_goal = True + _reward_in_goal = None + + def _init_param(self): + self._set_v_ref() + self._target_lane = self.env.ego.APs['lane'] + self._extra_action_weights_flag = True + + def _update_param(self): + self._set_v_ref() + + def _set_v_ref(self): + self._v_ref = rd.speed_limit + x = self.env.ego.x + if x <= rd.hlanes.near_stop_region: + self._v_ref = rd.speed_limit + elif x <= rd.hlanes.stop_region_centre: + self._v_ref = - (rd.speed_limit / abs(rd.hlanes.near_stop_region)) * (x - rd.hlanes.stop_region_centre) + else: + self._v_ref = 0 + + @property + def goal_achieved(self): + APs = self.env.ego.APs + return APs['stopped_now'] and APs['in_stop_region'] + + @property + def extra_initiation_condition(self): + APs = self.env.ego.APs + return not APs['has_stopped_in_stop_region'] and \ + (APs['before_but_close_to_stop_region'] or + APs['in_stop_region']) + + def generate_learning_scenario(self): + self.generate_scenario(ego_pos_range=(rd.hlanes.start_pos, - rd.intersection_width_w_offset / 2), + ego_perturb_lim=(rd.hlanes.width / 4, np.pi / 6), + ego_heading_towards_lane_centre=True) + + self._reward_in_goal = 200 + + def _low_level_manual_policy(self): + return self.env.aggressive_driving_policy(EGO_INDEX) + + @staticmethod + def _features_dim_reduction(features_tuple): + return features_tuple[0:5] + features_tuple[6:7] + features_tuple[9:11] + features_tuple[12:13] + + +class MCTSWait(ManeuverBase): + + _penalty_in_violation = 200 + + _terminate_in_goal = True + _reward_in_goal = None + + def _init_param(self): + ego = self.env.ego + self._v_ref = 0.0 + self._target_lane = ego.APs['lane'] + + #self._LTL_preconditions.append( + # LTLProperty("G ( has_stopped_in_stop_region => (in_stop_region or in_intersection))", + # self._penalty_in_violation)) + + self._n_others_with_higher_priority = 0 + for veh in self.env.vehs[1:]: + if veh.waited_count > ego.waited_count: + self._n_others_with_higher_priority += 1 + + def _update_param(self): + if self.env.ego.APs['highest_priority']: + self._v_ref = rd.speed_limit + + def generate_learning_scenario(self): + n_others = np.random.randint(0, 3) + self.generate_scenario(enable_LTL_preconditions=True, timeout=62, + n_others_range=(n_others, n_others), + ego_pos_range=rd.hlanes.stop_region, + n_others_stopped_in_stop_region=n_others, + ego_v_upper_lim=0, ego_perturb_lim=(rd.hlanes.width / 4, np.pi / 6), + ego_heading_towards_lane_centre=True) + + max_waited_count = 0 + for veh in self.env.vehs[1:]: + max_waited_count = max(max_waited_count, veh.waited_count) + + self.env.ego.waited_count = np.random.randint(0, max_waited_count + 21) + self.env.init_APs(False) + + self._reward_in_goal = 200 + + def _low_level_manual_policy(self): + return self.env.aggressive_driving_policy(EGO_INDEX) + + @property + def goal_achieved(self): + APs = self.env.ego.APs + return APs['in_intersection'] and APs['highest_priority'] + + @property + def extra_initiation_condition(self): + APs = self.env.ego.APs + return (APs['stopped_now'] and APs['in_stop_region']) + + @property + def extra_termination_condition(self): + APs = self.env.ego.APs + cond = (APs['in_intersection'] and not APs['highest_priority']) \ + or APs['over_speed_limit'] + if cond: + self._extra_r_terminal = -200 + else: + self._extra_r_terminal = None + return cond + + @staticmethod + def _features_dim_reduction(features_tuple): + return tuple(features_tuple[i] for i in \ + [1, 2, 4, 6, 9, 10, 11, 18, 19]) + + +class MCTSChangeLane(ManeuverBase): + + max_goal_distance = 21 + min_y_distance = rd.hlanes.width * 0.8 + + _terminate_in_goal = True + _reward_in_goal = None + + def _init_param(self): + self._init_x = self.env.ego.x + self._init_y = self.env.ego.y + self._v_ref = rd.speed_limit + self._target_lane = not self.env.ego.APs['lane'] + + self._terminate_in_goal = True + + @property + def goal_achieved(self): + APs = self.env.ego.APs + on_other_lane = APs['lane'] == self._target_lane + within_goal_distance = abs(self.env.ego.x - self._init_x) <= self.max_goal_distance + achieved_y_displacement = abs(self.env.ego.y - self._init_y) >= self.min_y_distance + return on_other_lane and APs['on_route'] and achieved_y_displacement and \ + APs['parallel_to_lane'] and within_goal_distance + + @property + def extra_initiation_condition(self): + return not self.env.ego.APs['in_intersection'] and not self.env.ego.APs['in_stop_region'] + + @property + def extra_termination_condition(self): + APs = self.env.ego.APs + cond1 = not APs['on_route'] or APs['over_speed_limit'] + cond2 = APs['in_stop_region'] or APs['in_intersection'] + if cond1 or cond2: + self._extra_r_terminal = -200 + else: + self._extra_r_terminal = None + return cond1 or cond2 + + def _low_level_manual_policy(self): + return self.env.aggressive_driving_policy(EGO_INDEX) + + def generate_learning_scenario(self): + before_intersection = (rd.hlanes.start_pos, rd.hlanes.stop_region[0]-self.max_goal_distance) + after_intersection = (rd.intersection_width_w_offset / 2, rd.hlanes.end_pos-self.max_goal_distance) + random_placement_index = np.random.choice([0, 1]) + random_h_pos = before_intersection if random_placement_index == 0 else after_intersection + self.generate_scenario(enable_LTL_preconditions=False, timeout=15, + ego_pos_range=random_h_pos, + ego_lane=np.random.choice([0, 1]), + ego_perturb_lim=(rd.hlanes.width/5, np.pi/6)) + # print('our range was %s, %s, ego at %s' % (before_intersection, after_intersection, self.env.ego.x)) + self._reward_in_goal = 200 + + # TODO: It is not a good idea to specify features by numbers, as the list + # of features is ever changing. We should specify them by strings. + @staticmethod + def _features_dim_reduction(features_tuple): + return tuple(features_tuple[i] for i in \ + [1, 2, 3, 4, 5, 6, 7, 9, 10]) + + +class MCTSFollow(ManeuverBase): + + __veh_ahead_buffer = 0.5 + + _penalty_for_out_of_follow_range = None + + def _init_param(self): + self._update_param() + self._terminate_in_goal = True + + if self._target_veh_i is None: + pass # print("\nWarning: initially, no vehicle is ahead of the ego in Follow maneuver.") + + def _update_param(self): + self._target_veh_i, self._V2V_dist = self.env.get_V2V_distance() + + def generate_learning_scenario(self): + self.generate_scenario(enable_LTL_preconditions=False, + n_others_range=(1, 1), + ego_perturb_lim=(rd.hlanes.width/2, np.pi/4), + veh_ahead_scenario=True) + _penalty_for_out_of_follow_range = 100 + + def generate_validation_scenario(self): + self.generate_scenario(enable_LTL_preconditions=False, + n_others_range=(1, 1), + ego_perturb_lim=(0, 0), + veh_ahead_scenario=True) + _penalty_for_out_of_follow_range = 100 + + def _low_level_manual_policy(self): + return self.env.aggressive_driving_policy(EGO_INDEX) + + @property + def extra_initiation_condition(self): + return self.env.ego.APs['veh_ahead'] + + @property + def extra_termination_condition(self): + condition1 = self._target_veh_i is None + + condition2 = self.env.ego.APs['lane'] != self._target_lane + + condition3 = self._V2V_dist > self.env.veh_ahead_max + self.__veh_ahead_buffer or \ + self._V2V_dist < self.env.veh_ahead_min - self.__veh_ahead_buffer + + if condition1 or condition2 or condition3: + if self._penalty_for_out_of_follow_range is not None: + self._extra_r_terminal = -self._penalty_for_out_of_follow_range + else: + self._extra_r_terminal = None + return True + else: + self._extra_r_terminal = None + return False + + def _features_dim_reduction(self, features_tuple): + # TODO: Remove magic number 19 and 5 using features.py + if self._target_veh_i is not None: + start_of_veh_feature = 20+((self._target_veh_i-1)*5) + return features_tuple[1:11] + features_tuple[start_of_veh_feature:start_of_veh_feature+4] + else: + return features_tuple[1:11] + (0.0, 0.0, 0.0, 0.0) \ No newline at end of file diff --git a/ppo2_training.py b/ppo2_training.py new file mode 100644 index 0000000000000000000000000000000000000000..fd8fa113fac541b097c8d3fb77ceba5d5cc51a24 --- /dev/null +++ b/ppo2_training.py @@ -0,0 +1,34 @@ +from env.simple_intersection import SimpleIntersectionEnv +from env.simple_intersection.constants import * +from options.options_loader import OptionsGraph +from backends.baselines_learner import PPO2Agent + +if __name__ == "__main__": + + # initialize the numpy random number generator + np.random.seed() + + # load options graph + options = OptionsGraph("config.json", SimpleIntersectionEnv) + options.set_current_node("changeright") + options.current_node.reset() + + # Use this code when you train a specific maneuver for the first time. + agent = PPO2Agent(input_shape=(options.current_node.get_reduced_feature_length(),), + nb_actions=2, env=options.current_node, tensorboard=True) + + # Use this code to resume the training from the last step. + # agent.load_weights("right_weights.h5f") + + # Train the NN models and save them. + agent.fit(nb_max_episode_steps=200, nb_steps=50000) + agent.save_weights("right_weights.h5f") # Save the NN weights for reloading them in the future. + + # Uncomment this after training to use trained model. Comment this to use manually defined policy + #agent.load_weights("right_weights.h5f") + + print ("Testing model...") + + # Test trained maneuver + # TODO: the graphical window is not closed before completing the test. + agent.test_model(options.current_node, nb_episodes=50) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..1db152477c89a8e85e8f9c7e9e0e927e2995479e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +numpy==1.14.3 +pyglet==1.3.2 +Sphinx==1.7.8 +yapf==0.23.0 +docformatter==1.0 +recommonmark==0.4.0 +keras-rl==0.4.2 +h5py==2.8.0 +gym==0.10.5 +stable_baselines==2.1.1 diff --git a/scripts/dependencies_config.sh b/scripts/dependencies_config.sh new file mode 100644 index 0000000000000000000000000000000000000000..1369747f0fcf2a418318ef58aba9c34c4189fde9 --- /dev/null +++ b/scripts/dependencies_config.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +DEPENDENCY_DIRECTORY="../dependencies" +PIP_PACKAGE_FOLDER="$DEPENDENCY_DIRECTORY/pip_packages" +PIP_SETUP_FOLDER="$DEPENDENCY_DIRECTORY/pip" +PIP_FILE_NAME="pip-18.1" +REQUIREMENTS_FILE="../requirements.txt" +PIP_LINK="https://files.pythonhosted.org/packages/45/ae/8a0ad77defb7cc903f09e551d88b443304a9bd6e6f124e75c0fbbf6de8f7/pip-18.1.tar.gz" \ No newline at end of file diff --git a/scripts/download_dependencies.sh b/scripts/download_dependencies.sh new file mode 100644 index 0000000000000000000000000000000000000000..a66466cc8afc026d38a915330fc8b6cc6770d44b --- /dev/null +++ b/scripts/download_dependencies.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +source dependencies_config.sh + +# Create folders +mkdir $DEPENDENCY_DIRECTORY +mkdir $PIP_SETUP_FOLDER +mkdir $PIP_PACKAGE_FOLDER + +# Download pip +wget -P $PIP_SETUP_FOLDER $PIP_LINK + +# Download pip packeges using requirements file +pip download -r $REQUIREMENTS_FILE -d $PIP_PACKAGE_FOLDER \ No newline at end of file diff --git a/scripts/generate_doc.sh b/scripts/generate_doc.sh new file mode 100644 index 0000000000000000000000000000000000000000..b2f0351c9f7b7a5bbadbf0a10535aa4a6d3492ae --- /dev/null +++ b/scripts/generate_doc.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# assuming sphinx is installed +function build_doc() { + curr_dir=$(pwd) + cd "$SCRIPT_DIR"/../documentation/sphinx + rm -rf .build + mkdir .build + sphinx-apidoc -o ./.doc ../../. + sphinx-build -b html . ./.build + rm -rf .doc + ln -s sphinx/.build/index.html ../index.html + cd "$curr_dir" + echo "Documentation files placed in the .build directory in sphinx folder." + +} + +function clean_doc() { + curr_dir=$(pwd) + cd "$SCRIPT_DIR"/../documentation/sphinx + rm -rf .build + rm ../index.html + cd "$curr_dir" + echo "Cleaned .build folder." +} + +# if arg0 is clean then kill session +if [[ "$#" -eq 1 ]]; then + if [[ "$1" == "clean" ]]; then + clean_doc + exit 0 + elif [[ "$1" == "build" ]]; then + build_doc + elif [[ "$1" == "launch" ]]; then + case "$(uname -s)" in + Darwin) + open "$SCRIPT_DIR/../documentation/index.html" + ;; + Linux) + xdg-open "$SCRIPT_DIR/../documentation/index.html" + ;; + *) + echo 'Cannot determine your OS. Open the .build/index.html file in the root folder.' + ;; + esac + else + echo "Usage: generate_doc.sh {build|clean|launch}" + fi +else + echo "Usage: generate_doc.sh {build|clean|launch}" +fi \ No newline at end of file diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100644 index 0000000000000000000000000000000000000000..d03e0b73a294f30fc5e9930da6b532327749700a --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +sh ./install_dependencies.sh +sh ./generate_doc.sh clean +sh ./generate_doc.sh build + diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh new file mode 100644 index 0000000000000000000000000000000000000000..7ebb289dc1096d14a4c5079ddf4a6efb1773ba87 --- /dev/null +++ b/scripts/install_dependencies.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +source dependencies_config.sh + +# Install pip +if ! [ -x "$(command -v pip3)" ]; then + echo "Installing pip3..." + if [ -d "$DEPENDENCY_DIRECTORY" ]; then + tar -xvzf "$PIP_SETUP_FOLDER/$PIP_FILE_NAME.tar.gz" + python3 "./$PIP_FILE_NAME/setup.py" install + rm -rf "./$PIP_FILE_NAME" + else + sudo apt-get update + sudo apt-get install python3-pip + fi +fi + +# Install packages in requirements.txt +if [ -d "$DEPENDENCY_DIRECTORY" ]; then + pip3 install --no-index --find-links=$PIP_PACKAGE_FOLDER -r $REQUIREMENTS_FILE --user +else + pip3 install -r $REQUIREMENTS_FILE --user +fi +