├── .eslintignore ├── .eslintrc.js ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── README.md ├── config ├── i18n │ └── en.json └── tutorials.json ├── css └── style.css ├── docs ├── Simulators.md ├── Tutorials.md └── i18n.md ├── img ├── arrow.svg ├── bayes.png ├── city.hero.png ├── city.png ├── hero_bg.png ├── sensitivity.png ├── sim.png ├── taxi.png └── taxisim.png ├── index.html ├── js ├── affix.js ├── chartx.js ├── gp.js ├── lib │ ├── Chart.js │ ├── mithril.min.js │ └── threejs │ │ ├── collada.js │ │ ├── controls.js │ │ └── three.min.js ├── np.js ├── playground.js └── simulators │ └── taxi.js └── models └── taxi ├── Park.dae ├── RoadEnd.dae ├── RoadIntersection.dae ├── RoadStraight.dae ├── Taxi.dae └── materials ├── Park.png ├── RoadEnd.png ├── RoadIntersection.png ├── RoadStraight.png ├── Taxi.1.png └── Taxi.png /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true 4 | }, 5 | "extends": "eslint:recommended", 6 | "parserOptions": { 7 | "ecmaVersion": 6 8 | }, 9 | "rules": { 10 | "indent": [ 11 | "error", 12 | "tab" 13 | ], 14 | "linebreak-style": [ 15 | "error", 16 | "unix" 17 | ], 18 | "quotes": [ 19 | "error", 20 | "single" 21 | ], 22 | "semi": [ 23 | "error", 24 | "always" 25 | ] 26 | }, 27 | "globals": { 28 | "m": false, 29 | "Affix": false, 30 | "Emulator": false, 31 | "Chart": false, 32 | "Float64Array": false, 33 | "Playground": false, 34 | "np": false, 35 | "THREE": false 36 | } 37 | }; -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # DS_Store 2 | .DS_Store 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (https://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | 42 | # TypeScript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | 63 | # parcel-bundler cache (https://parceljs.org/) 64 | .cache 65 | 66 | # next.js build output 67 | .next 68 | 69 | # nuxt.js build output 70 | .nuxt 71 | 72 | # vuepress build output 73 | .vuepress/dist 74 | 75 | # Serverless directories 76 | .serverless -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/amzn/emukit-playground/issues), or [recently closed](https://github.com/amzn/emukit-playground/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure your changes work as intended across multiple browsers and that your code is [linted](#linting). 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/amzn/emukit-playground/labels/help%20wanted) issues is a great place to start. 45 | 46 | ## Setting up a development environment 47 | Once you have the repository cloned from git, you must host a server to test the Playground. The easiest way to host the Playground is by using [http-server](https://www.npmjs.com/package/http-server) (assuming you have [node.js](https://nodejs.org/) and [npm](https://npmjs.com) installed): 48 | 49 | ```bash 50 | git clone https://github.com/amzn/emukit-playground 51 | cd EmukitPlayground 52 | npm install -g http-server 53 | http-server 54 | ``` 55 | 56 | ## Linting 57 | To ensure code style consistency, we use eslint. To install eslint, ensure you have [node.js](https://nodejs.org/) and [npm](https://npmjs.com) installed, then run 58 | 59 | ```bash 60 | npm install -g eslint 61 | ``` 62 | 63 | to globally install eslint. After making changes, navigate to the root of the repository and run 64 | 65 | ```bash 66 | eslint js 67 | ``` 68 | 69 | Some errors can be automatically fixed (such as changing from space indentation to tab indentation) byusing the `--fix` option. 70 | 71 | Once you have ensured there are no errors, you can submit a pull request with your changes. 72 | 73 | 74 | ## Code of Conduct 75 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 76 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 77 | opensource-codeofconduct@amazon.com with any additional questions or comments. 78 | 79 | 80 | ## Security issue notifications 81 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 82 | 83 | 84 | ## Licensing 85 | 86 | See the [LICENSE](https://github.com/amzn/emukit-playground/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 87 | 88 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 89 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Emukit Playground 2 | Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
Learn about key emulation concepts with the Emukit Playground.
4 |Launch Playground | Documentation | Contribution guidelines
5 | 6 | ## What is Emukit Playground? 7 | Emukit Playground is an interactive learning tool teaching users about emulation-based decision making. The playground allows users to train a working emulator in their browser based on visually driven simulations. 8 | 9 | This project was released alongside [Emukit](https://github.com/amzn/Emukit), a Python toolkit of various methods in uncertainty quantification and statistical emulation: experimental design, Bayesian optimisation, Bayesian quadrature. 10 | 11 | ## Contributing 12 | We're always open to contributions! Please read our [contribution guidelines](CONTRIBUTING.md) for more information. We are particularly interested in contributions regarding translations and tutorials. 13 | 14 | ## License 15 | This project is licensed under Apache 2.0. Please refer to [LICENSE](LICENSE) and [NOTICE](NOTICE) for further license information. 16 | -------------------------------------------------------------------------------- /config/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "core": { 3 | "title": "Emukit Playground", 4 | "heroTitle": "Welcome to the Emukit Playground", 5 | "tutorials": "Tutorials", 6 | "sandbox": "Sandbox", 7 | "btnHome": "Return to home", 8 | "btnFork": "Fork on GitHub", 9 | "btnLaunch": "Launch", 10 | "btnBack": "Back", 11 | "btnNext": "Next", 12 | "btnNextTutorial": "Next tutorial", 13 | "btnTour": "Take a tour", 14 | "btnStartLearning": "Start learning", 15 | "minutes": "minutes", 16 | "simulate": "Simulate", 17 | "visualise": "Visualise", 18 | "emulate": "Emulate", 19 | "emulator": "Emulator", 20 | "emulators": "Emulators", 21 | "simulationInputs": "Simulation Inputs", 22 | "simulationOutputs": "Simulation Outputs", 23 | "simulationStatus": "Simulation status", 24 | "simulationPaused": "Paused", 25 | "simulationRunning": "Running", 26 | "simulationFinished": "Finished", 27 | "simulationProgress": "Progress", 28 | "simulationSpeed": "Simulation speed", 29 | "simulationReady": "Ready", 30 | "tutorialEndCardTitle": "You've completed the $0 tutorial!", 31 | "variance": "Variance", 32 | "varianceDescription": "The variance is the prior belief on how much output of the simulator can change with respect to the input", 33 | "length": "Length scale", 34 | "lengthDescription": "The length scale is how close two points in the input domain have to be to be influencing each other", 35 | "noise": "Noise", 36 | "noiseDescription": "The noise is the variation in the collected data, meaning how much the outputs can change if we run the simulator several times in the same location", 37 | "removeData": "Remove data points", 38 | "removeEmulator": "Remove emulator", 39 | "resetEmulators": "Reset all emulators", 40 | "add": "Add", 41 | "nextTutorial": "When you are ready, you may continue to the next tutorial." 42 | }, 43 | "tutorial": { 44 | "introduction": { 45 | "title": "Introduction to Simulation", 46 | "description": "Learn about simulation and discover where simulators are used.", 47 | "slide1": { 48 | "title": "Introduction to Simulation", 49 | "description": "Simulation is widely used in a number of industries as a method of modeling complex systems. In this simulator, taxis travel around a city picking up and dropping of passengers." 50 | }, 51 | "slide2": { 52 | "title": "Simulation inputs", 53 | "description": "The inputs to the simulator can be set here. Hover (or tap on) the input titles to learn more about each input." 54 | }, 55 | "slide3": { 56 | "title": "Simulation speed", 57 | "description": "The speed of a simulation can be changed at any time with this slider." 58 | }, 59 | "slide4": { 60 | "title": "Run a simulation", 61 | "description": "To start a simulation, click on the play button." 62 | }, 63 | "slide5": { 64 | "title": "Simulator", 65 | "description": "Here you can visualise the simulation to understand what the simulation is doing. Use the left mouse button to rotate and the scroll wheel to zoom." 66 | }, 67 | "slide6": { 68 | "title": "Journeys", 69 | "description": "The blue bars represent the pick-up location of a journey, and the red bars represent the drop-off location. The height of the bars represents the time since the journey was created." 70 | }, 71 | "slide7": { 72 | "title": "Simulation outputs", 73 | "description": "The outputs of the simualator are shown here." 74 | }, 75 | "end_card": { 76 | "action": "The journey frequency and number of roads have been changed. Try to find out the new optimal profit by training the emulator." 77 | } 78 | }, 79 | "bayesian_optimization": { 80 | "title": "Bayesian Optimization", 81 | "description": "Find out how emulators can be used to optimize a variable.", 82 | "slide1":{ 83 | "title": "Bayesian Optimization", 84 | "description":"We may want to answer the question, “what is the optimal number of taxis to generate the most profit?” One approach would be to repeatedly run the simulator many times, each time changing the number of taxis and observing the profit to try and find the maximum value." 85 | }, 86 | "slide2":{ 87 | "description":"Try running the simulator to see what would happen if we only have 10 taxis. Click the play button to begin the simulation." 88 | }, 89 | "slide3":{ 90 | "description":"Many passengers are waiting a very long time before being picked up by a taxi. There aren’t enough taxis to fulfill all the demand, and as a result profit opportunities are being missed." 91 | }, 92 | "slide4":{ 93 | "description":"Let’s increase the number of taxis to 90. Click the play button to begin the simulation." 94 | }, 95 | "slide5":{ 96 | "description":"Now there are too many taxis. This impacts profits as we are paying fuel and driver costs for taxis which are empty and generating no profit. Our intuition tells us that the optimal number of taxis must be somewhere in the middle." 97 | }, 98 | "slide6":{ 99 | "description":"Let’s try once again with 30 taxis. Click the play button to begin the simulation." 100 | }, 101 | "slide7":{ 102 | "description":"The profit is higher than both of our previous attempts, but should we increase or decrease the number of taxis from here?" 103 | }, 104 | "slide8":{ 105 | "description":"The number of times we would have to run a simulation to answer this question quickly adds up. In many real-world applications, these simulation runs can be very costly and time consuming." 106 | }, 107 | "slide9":{ 108 | "description":"Instead we can construct an emulator that models the relationship between the inputs and outputs of simulators. In this case, we use an emulator to model how changing the number of taxis affects our profit." 109 | }, 110 | "slide10":{ 111 | "description":"Each time we complete a run of the simulation, we add a data point (shown in orange). The emulator then generates the predicted mean of the function (shown in black) and the uncertainty in the prediction (shown in gray)." 112 | }, 113 | "slide11":{ 114 | "description":"Lets explore the function when there are 65 taxis. Since we have not observed the outputs of the simulator around this point, the optimum of the function could be contained in this region of high uncertainty." 115 | }, 116 | "slide12":{ 117 | "description":"Run the simulator with 65 taxis. Click the play button to begin the simulation." 118 | }, 119 | "slide13":{ 120 | "description":"The uncertainty in this area has reduced, and the emulator still shows us that the predicted maximum of the function is around 40 taxis. Now lets exploit this region to increase the precision of the emulator around the optimum." 121 | }, 122 | "slide14":{ 123 | "description":"Run the simulation with 40 taxis. Click the play button to begin the simulation." 124 | }, 125 | "slide15":{ 126 | "description":"Too much exploration results in a lack of precision around the optimum, while too much exploitation means we may miss the true optimum of the function. It is important to balance exploration and exploitation in order to ensure we efficiently find the true optimum value." 127 | }, 128 | "end_card": { 129 | "action": "The journey frequency and number of roads have been changed. Try to find out the new optimal profit by training the emulator." 130 | }, 131 | "emulator1": { 132 | "title": "Number of Taxis vs Profit" 133 | } 134 | }, 135 | "sensitivity_analysis": { 136 | "title": "Sensitivity Analysis", 137 | "description": "Learn about sensitivity analysis and discover how emulators can be used to find how sensitive an input is.", 138 | "slide1": { 139 | "title": "Sensitivity Analysis", 140 | "description": "A common reason we may build a simulator is so that we can answer ‘what if’ questions, such as “what would happen if we increased our prices?”" 141 | }, 142 | "slide2": { 143 | "description": "Our intuition tells us that while increasing prices may result in additional profit, increasing them by too much will lead to a fall in demand as potential passengers use other means (such as our competitors) to get to their destinations." 144 | }, 145 | "slide3": { 146 | "description": "We can construct an emulator that models the relationship between the cost per kilometer travelled against different outputs." 147 | }, 148 | "slide4": { 149 | "description": "Run the simulator to gather some data. Click the play button to start the simulation." 150 | }, 151 | "slide5": { 152 | "description": "Continue to train the emulator on a couple of further points. Click the play button to start the simulation." 153 | }, 154 | "slide6": { 155 | "description": "Run the simulator once again with a higher price. Click the play button to start the simulation." 156 | }, 157 | "slide7": { 158 | "description": "Now that we have trained the emulator with some points, we can use sensitivity analysis to see how sensitive (i.e. how much the output will change by increasing or decreasing the input) the cost per kilometers driven is for each output." 159 | }, 160 | "slide8": { 161 | "description": "The orange line denotes the derivative of the mean at the given input point. The gradient of this line tells us how sensitive this input is at the given point." 162 | }, 163 | "slide9": { 164 | "description": "We can see that when there are 5 taxis, if we were to add a 6th taxi we could expect a profit increase of around $1.5k." 165 | }, 166 | "slide10": { 167 | "description": "When we observe the cost per kilometer vs the mean pick-up time, we see that the gradient of the sensitivity is almost flat. This means that adding or removing taxis at this point will have little to no effect." 168 | }, 169 | "slide11": { 170 | "description": "This aligns with our intuition, since changing the cost of the journey shouldn’t increase the time it takes for a taxi to pick a given passenger up." 171 | }, 172 | "slide12": { 173 | "description": "We also observe the same relationship with missed customers. While we are increasing the price, passengers are still willing to pay the additional cost, hence we still have the same demand and thus don’t miss any additional customers." 174 | }, 175 | "slide13": { 176 | "description": "Lets train the emulator with some further points. Click the play button to start the simulation." 177 | }, 178 | "slide14": { 179 | "description": "Train the emulator with one more point. Click the play button to start the simulation." 180 | }, 181 | "slide15": { 182 | "description": "We can see that the relationship observed once the cost per kilometer goes above $10 changes. At this point, passengers start to decide against taking the taxis if their journey will cost too much." 183 | }, 184 | "slide16": { 185 | "description": "When there are 13 taxis, the profit starts to level out. At this point if we were to increase or decrease the cost per km, we would observe a lower overall profit." 186 | }, 187 | "slide17": { 188 | "description": "However when we consider mean pick-up time, we observe that increasing the cost per km will reduce the mean pick-up time by around 25 minutes per $1 increase." 189 | }, 190 | "slide18": { 191 | "description": "While this may initially seem counter-intuitive, when the price is higher there is lower demand meaning the remaining passengers can be picked up faster." 192 | }, 193 | "slide19": { 194 | "description": "This is confirmed when we look at the sensitivity of customers missed. We see that increasing the cost per km will increase the numbers of customers missed by around 50 passengers per $1 increase." 195 | }, 196 | "slide20": { 197 | "description": "We can see that even though we have only trained the emulator on 5 data points, we have already gather alot of information about the underlying relationships, and have the ability to perform sensitivity analysis at any point within the input domain. Performing sensitivity analysis without the help of an emulator would require many more simulation runs, resulting in a significant increase of both the cost and time required." 198 | }, 199 | "slide21": { 200 | "description": "By using emulators, we are able to determine the sensitivities of many inputs and outputs at the same time. This further decreases the requirement for additional simulation runs." 201 | }, 202 | "end_card": { 203 | "action": "Explore the sensitivity of the input at different points." 204 | }, 205 | "emulator1": { 206 | "title": "Cost per km vs Profit" 207 | }, 208 | "emulator2": { 209 | "title": "Cost per km vs Mean pick-up time" 210 | }, 211 | "emulator3": { 212 | "title": "Cost per km vs Customers missed" 213 | } 214 | } 215 | }, 216 | "simulator": { 217 | "taxi": { 218 | "profit": { 219 | "title": "Profit", 220 | "description": "The total net profit generated" 221 | }, 222 | "customersMissed": { 223 | "title": "Customers missed", 224 | "description": "The total number of customers missed" 225 | }, 226 | "meanPickUpTime": { 227 | "title": "Mean pick-up time", 228 | "description": "The average time it takes a taxi to pick up a passenger" 229 | }, 230 | "profitPerJourney": { 231 | "title": "Profit per journey", 232 | "description": "The average profit generated in a single journey" 233 | }, 234 | "journeysCompleted": { 235 | "title": "Journeys completed", 236 | "description": "The total number of journeys completed" 237 | }, 238 | "numRoads": { 239 | "title": "Number of roads", 240 | "description": "The number of roads simulated" 241 | }, 242 | "numTaxis": { 243 | "title": "Number of taxis", 244 | "description": "The number of taxis simulated" 245 | }, 246 | "journeyFrequency": { 247 | "title": "Journey frequency", 248 | "description": "The frequency of journey requests" 249 | }, 250 | "baseFare": { 251 | "title": "Base fare", 252 | "description": "The starting fare on the meter" 253 | }, 254 | "costPerTile": { 255 | "title": "Cost per km", 256 | "description": "The cost to the passengers per kilometer driven" 257 | }, 258 | "maxMultiplier": { 259 | "title": "Demand multiplier", 260 | "description": "During peak times passengers will be charged more. The multiplier determines the maximum charge. For example, a demand multiplier of 2x will charge at most 2 times the regular price of the journey." 261 | } 262 | } 263 | } 264 | } -------------------------------------------------------------------------------- /config/tutorials.json: -------------------------------------------------------------------------------- 1 | { 2 | "introduction": { 3 | "order": 1, 4 | "title": "@title", 5 | "description": "@description", 6 | "estimated_time": 3, 7 | "image": "img/sim.png", 8 | "simulator": { 9 | "name": "taxi", 10 | "outputs": [ "profit", "missed", "pickUpTime" ], 11 | "steps": 1000 12 | }, 13 | "tutorial_steps": [ 14 | { "highlight": "self" }, 15 | { "highlight": "inputs" }, 16 | { "highlight": "speedSlider" }, 17 | { "highlight": "playButton", "action": "playSimulation" }, 18 | { "highlight": "simulator", "trigger": "midSimulation" }, 19 | { "highlight": "simulator", "trigger": "midSimulation" }, 20 | { "highlight": "outputs", "trigger": "midSimulation" } 21 | ], 22 | "end_card": { 23 | "next_tutorial": "bayesian_optimization", 24 | "extra_action": "Try changing different inputs of the simulator to see the effect on the outputs." 25 | } 26 | }, 27 | "bayesian_optimization": { 28 | "order": 2, 29 | "title": "@title", 30 | "description": "@description", 31 | "estimated_time": 5, 32 | "image": "img/bayes.png", 33 | "simulator": { 34 | "name": "taxi", 35 | "inputs": [ "taxiCount" ], 36 | "outputs": [ "profit", "missed", "pickUpTime" ], 37 | "steps": 1000 38 | }, 39 | "emulators": [ 40 | { 41 | "id": "taxisvsprofit", 42 | "title": "@emulator1/title", 43 | "input": "taxiCount", 44 | "output": "profit", 45 | "xAxisLabel": "Number of Taxis", 46 | "yAxisLabel": "Profit ($)", 47 | "hyperparameters": { 48 | "variance": 5000, 49 | "length": 500, 50 | "noise": 0.005 51 | }, 52 | "showOnStep": 8, 53 | "showSensitivity": false 54 | }], 55 | "tutorial_steps": [ 56 | { 57 | "highlight": "self", 58 | "simulator_values": { 59 | "gridSize": 5, 60 | "taxiCount": 20, 61 | "journeyFrequency": 50, 62 | "baseFare": 5, 63 | "costPerTile": 5, 64 | "maxMultiplier": 2 65 | } 66 | }, 67 | { 68 | "highlight": "playButton", 69 | "action": "playSimulation", 70 | "simulator_values": { 71 | "taxiCount": 10 72 | } 73 | }, 74 | { "highlight": "simulator", "trigger": "midSimulation" }, 75 | { 76 | "highlight": "playButton", 77 | "trigger": "endSimulation", 78 | "simulator_values": { 79 | "taxiCount": 90 80 | }, 81 | "action": "playSimulation" 82 | }, 83 | { "highlight": "simulator", "trigger": "midSimulation" }, 84 | { 85 | "highlight": "playButton", 86 | "trigger": "endSimulation", 87 | "simulator_values": { 88 | "taxiCount": 30 89 | }, 90 | "action": "playSimulation" 91 | }, 92 | { "highlight": "profit", "trigger": "midSimulation" }, 93 | { "highlight": "self", "trigger": "endSimulation" }, 94 | { "highlight": "taxisvsprofit" }, 95 | { "highlight": "taxisvsprofit" }, 96 | { 97 | "highlight": "taxisvsprofit", 98 | "simulator_values": { 99 | "taxiCount": 65 100 | } 101 | }, 102 | { "highlight": "playButton", "action": "playSimulation" }, 103 | { 104 | "highlight": "taxisvsprofit", 105 | "simulator_values": { 106 | "taxiCount": 40 107 | }, 108 | "trigger": "endSimulation" 109 | }, 110 | { "highlight": "playButton", "action": "playSimulation" }, 111 | { "highlight": "taxisvsprofit", "trigger": "endSimulation" } 112 | ], 113 | "end_card": { 114 | "next_tutorial": "sensitivity_analysis", 115 | "extra_action": "@end_card/action", 116 | "simulator_values": { 117 | "journeyFrequency": 60, 118 | "costPerTile": 3, 119 | "baseFare": 8, 120 | "maxMultiplier": 1.5, 121 | "gridSize": 4 122 | } 123 | } 124 | }, 125 | "sensitivity_analysis": { 126 | "order": 3, 127 | "title": "@title", 128 | "description": "@description", 129 | "estimated_time": 8, 130 | "image": "img/sensitivity.png", 131 | "simulator": { 132 | "name": "taxi", 133 | "inputs": [ "costPerTile" ], 134 | "outputs": [ "profit", "missed", "pickUpTime" ], 135 | "steps": 1000 136 | }, 137 | "emulators": [ 138 | { 139 | "id": "costperkmvsprofit", 140 | "title": "@emulator1/title", 141 | "input": "costPerTile", 142 | "output": "profit", 143 | "xAxisLabel": "Cost per km ($)", 144 | "yAxisLabel": "Profit ($)", 145 | "hyperparameters": { 146 | "variance": 10000, 147 | "length": 16, 148 | "noise": 0.0225 149 | }, 150 | "showSensitivity": true 151 | }, 152 | { 153 | "id": "costperkmvspickuptime", 154 | "title": "@emulator2/title", 155 | "input": "costPerTile", 156 | "output": "pickUpTime", 157 | "xAxisLabel": "Cost per km ($)", 158 | "yAxisLabel": "Mean pick-up time", 159 | "hyperparameters": { 160 | "variance": 28, 161 | "length": 11, 162 | "noise": 0.0225 163 | }, 164 | "showSensitivity": true 165 | }, 166 | { 167 | "id": "costperkmvsmissed", 168 | "title": "@emulator3/title", 169 | "input": "costPerTile", 170 | "output": "missed", 171 | "xAxisLabel": "Cost per km ($)", 172 | "yAxisLabel": "Customers Missed", 173 | "hyperparameters": { 174 | "variance": 155, 175 | "length": 10, 176 | "noise": 0.05 177 | }, 178 | "showSensitivity": true 179 | } 180 | ], 181 | "tutorial_steps": [ 182 | { "highlight": "self" }, 183 | { "highlight": "self" }, 184 | { "highlight": "self" }, 185 | { 186 | "highlight": "playButton", 187 | "action": "playSimulation", 188 | "simulator_values": { 189 | "costPerTile": 1 190 | } 191 | }, 192 | { 193 | "trigger": "endSimulation", 194 | "highlight": "playButton", 195 | "action": "playSimulation", 196 | "simulator_values": { 197 | "costPerTile": 5 198 | } 199 | }, 200 | { 201 | "trigger": "endSimulation", 202 | "highlight": "playButton", 203 | "action": "playSimulation", 204 | "simulator_values": { 205 | "costPerTile": 10 206 | } 207 | }, 208 | { "highlight": "self", "trigger": "endSimulation" }, 209 | { "highlight": "costperkmvsprofit", "simulator_values": { "costPerTile": 5 } }, 210 | { "highlight": "costperkmvsprofit", "simulator_values": { "costPerTile": 5 } }, 211 | { "highlight": "costperkmvspickuptime", "simulator_values": { "costPerTile": 5 } }, 212 | { "highlight": "costperkmvspickuptime", "simulator_values": { "costPerTile": 5 } }, 213 | { "highlight": "costperkmvsmissed", "simulator_values": { "costPerTile": 5 } }, 214 | { 215 | "highlight": "playButton", 216 | "action": "playSimulation", 217 | "simulator_values": { 218 | "costPerTile": 15 219 | } 220 | }, 221 | { 222 | "trigger": "endSimulation", 223 | "highlight": "playButton", 224 | "action": "playSimulation", 225 | "simulator_values": { 226 | "costPerTile": 20 227 | } 228 | }, 229 | { "trigger": "endSimulation", "highlight": "costperkmvsprofit", "simulator_values": { "costPerTile": 13 } }, 230 | { "highlight": "costperkmvsprofit", "simulator_values": { "costPerTile": 13 } }, 231 | { "highlight": "costperkmvspickuptime", "simulator_values": { "costPerTile": 13 } }, 232 | { "highlight": "costperkmvspickuptime", "simulator_values": { "costPerTile": 13 } }, 233 | { "highlight": "costperkmvsmissed", "simulator_values": { "costPerTile": 13 } }, 234 | { "highlight": "self" }, 235 | { "highlight": "self" } 236 | ], 237 | "end_card": { 238 | "extra_action": "@end_card/action", 239 | "simulator_values": { 240 | "journeyFrequency": 60, 241 | "costPerTile": 3, 242 | "baseFare": 8, 243 | "maxMultiplier": 1.5, 244 | "gridSize": 4 245 | } 246 | } 247 | } 248 | } -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | /* Global styles */ 17 | html { 18 | font-family: 'Open Sans', sans-serif; 19 | height: 100%; 20 | cursor: default; 21 | font-weight: 100; 22 | } 23 | 24 | body { 25 | margin: 0; 26 | height: 100%; 27 | background-color: #eee; 28 | } 29 | 30 | a { 31 | text-decoration: none; 32 | } 33 | 34 | h1 { 35 | font-weight: 400; 36 | } 37 | 38 | h2 { 39 | font-weight: 400; 40 | } 41 | 42 | /* Header */ 43 | .header { 44 | width: 100%; 45 | height: 70px; 46 | padding: 20px; 47 | margin: 0; 48 | box-sizing: border-box; 49 | background-color: #20232a; 50 | color: #fff; 51 | display: flex; 52 | flex-wrap: wrap; 53 | justify-content: space-between; 54 | overflow: hidden; 55 | } 56 | 57 | h1.title { 58 | margin: 0; 59 | font-size: 24px; 60 | font-weight: 200; 61 | margin-right: 20px; 62 | margin-top: -3px; 63 | } 64 | 65 | .header .btn { 66 | margin-top: -4px; 67 | padding-top: 8px; 68 | } 69 | 70 | .header-left { 71 | display: flex; 72 | justify-content: space-between; 73 | } 74 | 75 | /* Hero */ 76 | .hero { 77 | width: 100%; 78 | box-sizing: border-box; 79 | height: 300px; 80 | display: flex; 81 | justify-content: center; 82 | align-items: center; 83 | background-color: #fff; 84 | } 85 | 86 | .hero-title { 87 | margin-top: 0; 88 | } 89 | 90 | .hero-image { 91 | background-image: url('../img/city.hero.png'); 92 | background-size: cover; 93 | margin: auto; 94 | width: 100%; 95 | height: 300px; 96 | opacity: 0.18; 97 | position: absolute; 98 | } 99 | 100 | .hero-content { 101 | text-align: center; 102 | padding: 20px; 103 | z-index: 2; 104 | } 105 | 106 | /* Buttons */ 107 | .btn { 108 | border-radius: 5px; 109 | border: none; 110 | text-align: center; 111 | padding: 10px 16px; 112 | box-shadow: 3px 3px rgba(0, 0, 0, 0.21); 113 | background-color: #ff9800; 114 | color: #fff; 115 | font-size: 14px; 116 | text-decoration: none; 117 | cursor: pointer; 118 | } 119 | 120 | .btn:hover { 121 | background-color: #ec8d00; 122 | } 123 | 124 | .btn-disabled:hover { 125 | background-color: #c2c2c2 !important; 126 | } 127 | 128 | .btn-disabled { 129 | background-color: #c2c2c2 !important; 130 | cursor: not-allowed; 131 | } 132 | 133 | .btn-autow { 134 | width: auto !important; 135 | } 136 | 137 | .btn-fw { 138 | width: 150px; 139 | } 140 | 141 | .btn-github { 142 | background-color: #d1d2d3; 143 | color: #000; 144 | } 145 | 146 | .btn-github:hover { 147 | background-color: #a8a8a8; 148 | } 149 | 150 | .btn-danger { 151 | background-color: #f44336; 152 | width: auto !important; 153 | } 154 | 155 | .btn-danger:hover { 156 | background-color: #ba000d; 157 | } 158 | 159 | /* Floating action button */ 160 | .btn-fab { 161 | width: 80px; 162 | height: 80px; 163 | background-color: #FF9800; 164 | color: #fff; 165 | border-radius: 50%; 166 | box-shadow: 5px 5px rgba(0, 0, 0, 0.5); 167 | position: relative; 168 | cursor: pointer; 169 | } 170 | 171 | .btn-fab-highlight { 172 | animation: 0.7s alternate-reverse infinite flash; 173 | } 174 | 175 | .btn-fab-hf { 176 | z-index: 10000 !important; 177 | background-color: #a86200 !important; 178 | cursor: not-allowed; 179 | } 180 | .btn-fab-hf path { 181 | fill: rgb(168, 168, 168) !important; 182 | } 183 | 184 | .btn-fab:hover { 185 | background-color: #ec8d00; 186 | } 187 | 188 | .btn-simulation-fab { 189 | margin-top: -35px; 190 | margin-left: 20px; 191 | margin-right: 20px; 192 | } 193 | 194 | /* Cards */ 195 | .card-container { 196 | display: flex; 197 | flex-wrap: wrap; 198 | } 199 | 200 | .card { 201 | position: relative; 202 | margin: 4px; 203 | border: solid 1px #d6d6d6; 204 | border-radius: 5px; 205 | overflow: hidden; 206 | background-color: #fff; 207 | display: flex; 208 | flex-flow: column; 209 | } 210 | 211 | .card-experiment { 212 | width: 290px; 213 | height: 250px; 214 | } 215 | 216 | .card-content { 217 | padding: 10px; 218 | align-self: flex; 219 | } 220 | 221 | .card-action { 222 | margin-top: 10px; 223 | display: flex; 224 | justify-content: space-between; 225 | } 226 | 227 | .card-image { 228 | flex: 1; 229 | background-size: cover; 230 | } 231 | 232 | .card-title { 233 | margin-bottom: 4px; 234 | font-size: 18px; 235 | } 236 | 237 | .card-container .card-subtitle { 238 | font-size: 15px; 239 | } 240 | 241 | .card-subtitle { 242 | font-size: 17px; 243 | } 244 | 245 | .card-info { 246 | font-size: 13px; 247 | padding: 10px 0; 248 | margin: 0; 249 | color: #888; 250 | } 251 | 252 | .card .btn { 253 | font-size: 13px; 254 | width: 80px; 255 | } 256 | 257 | .sidebar .card { 258 | margin-bottom: 20px; 259 | } 260 | 261 | .overflow { 262 | overflow: visible; 263 | } 264 | 265 | /* Utility */ 266 | .container { 267 | max-width: 1200px; 268 | margin: auto; 269 | padding: 0 20px; 270 | } 271 | 272 | .section { 273 | margin: 20px 0; 274 | } 275 | 276 | .m-left { 277 | margin-left: 20px; 278 | } 279 | 280 | .centered { 281 | margin: auto; 282 | } 283 | 284 | /* Experiment page */ 285 | .content { 286 | display: flex; 287 | position: absolute; 288 | 289 | top: 70px; left: 0; bottom: 0; right: 0; 290 | } 291 | 292 | .visualiser { 293 | flex: 1; 294 | display: flex; 295 | flex-flow: column; 296 | } 297 | 298 | .visualisation { 299 | flex: 1; 300 | border: none; 301 | min-width: 0; 302 | min-height: 0; 303 | } 304 | 305 | .hidden { 306 | visibility: hidden; 307 | } 308 | 309 | #canvas { 310 | width: 100% !important; 311 | height: 100% !important; 312 | } 313 | 314 | .controls { 315 | background-color: #20232a; 316 | height: 70px; 317 | width: 100%; 318 | display: flex; 319 | justify-content: center; 320 | color: #fff; 321 | } 322 | 323 | .sidebar { 324 | border-right: solid 1px #d6d6d6; 325 | overflow-y: scroll; 326 | max-width: 35%; 327 | min-width: 400px; 328 | padding: 20px; 329 | } 330 | 331 | .control { 332 | margin: 10px; 333 | width: 191px; 334 | } 335 | 336 | .input-container { 337 | display: flex; 338 | justify-content: center; 339 | flex-wrap: wrap; 340 | } 341 | 342 | .input { 343 | width: 170px; 344 | font-size: 15px; 345 | margin: 15px; 346 | } 347 | 348 | .output-container { 349 | display: flex; 350 | justify-content: center; 351 | flex-wrap: wrap; 352 | } 353 | 354 | .output { 355 | width: 100px; 356 | height: 100px; 357 | border-radius: 100%; 358 | border: solid 1px #979797; 359 | margin: 20px; 360 | display: flex; 361 | justify-content: center; 362 | align-items: center; 363 | flex-flow: column; 364 | text-align: center; 365 | background-color: #fff; 366 | } 367 | 368 | .output-label { 369 | max-width: 90px; 370 | } 371 | 372 | .output-value { 373 | font-size: 20px; 374 | } 375 | 376 | /* Emulator controller */ 377 | .emulator-controls-container { 378 | display: flex; 379 | justify-content: center; 380 | align-items: center; 381 | flex-wrap: wrap; 382 | } 383 | 384 | /* Hyperparams */ 385 | .hyperparams { 386 | padding: 10px; 387 | } 388 | 389 | /* Slider */ 390 | .slider { 391 | -webkit-appearance: none; 392 | appearance: none; 393 | width: 170px; 394 | height: 6px; 395 | outline: none; 396 | border-radius: 3px; 397 | background-color: #d8d8d8; 398 | } 399 | 400 | .slider-hyper { 401 | width: 100%; 402 | } 403 | 404 | .slider::-webkit-slider-thumb { 405 | -webkit-appearance: none; 406 | appearance: none; 407 | width: 12px; 408 | height: 12px; 409 | border-radius: 6px; 410 | border: none; 411 | background: #ff9800; 412 | } 413 | 414 | .slider::-moz-range-thumb { 415 | width: 12px; 416 | height: 12px; 417 | border-radius: 6px; 418 | border: none; 419 | background: #ff9800; 420 | } 421 | 422 | .slider-output { 423 | padding: 9px 13px; 424 | width: 20px; 425 | height: 20px; 426 | background-color: #ff9800; 427 | text-align: center; 428 | color: #fff; 429 | border-radius: 20px; 430 | margin-left: -10px; 431 | cursor: pointer; 432 | } 433 | 434 | .input-disabled .slider::-webkit-slider-thumb { 435 | background: #979797 !important; 436 | } 437 | 438 | .input-disabled .slider::-webkit-slider-thumb { 439 | background: #979797 !important; 440 | } 441 | 442 | .input-disabled .slider::-webkit-slider-thumb { 443 | background: #979797 !important; 444 | } 445 | 446 | .input-disabled .slider-output { 447 | background-color: #979797 !important; 448 | } 449 | 450 | /* Hover hints */ 451 | .hint { 452 | visibility: hidden; 453 | max-width:300px; 454 | background-color: #20232a; 455 | color: #fff; 456 | text-align: center; 457 | position: absolute; 458 | padding: 10px; 459 | margin-top:-5px; 460 | transform: translateY(-100%); 461 | -webkit-transform: translateY(-100%); 462 | -moz-transform: translateY(-100%); 463 | border-radius: 5px; 464 | } 465 | 466 | .hint::after { /* Arrow */ 467 | content: " "; 468 | position: absolute; 469 | margin-left: -5px; 470 | border-width: 5px; 471 | border-style: solid; 472 | border-color: black transparent transparent transparent; 473 | top: 100%; 474 | left: 15px; 475 | } 476 | 477 | .hoverable:hover .hint { 478 | visibility: visible; 479 | } 480 | 481 | /* Select box */ 482 | select { 483 | width: 180px; 484 | margin: 10px; 485 | padding: 5px 15px; 486 | font-size: 16px; 487 | border: 0px; 488 | height: 36px; 489 | -webkit-appearance: none; 490 | -moz-appearance: none; 491 | appearance: none; 492 | box-shadow: 3px 3px rgba(0, 0, 0, 0.21); 493 | border-radius: 5px; 494 | background-color: rgb(248, 248, 248); 495 | } 496 | 497 | /* CAUTION: IE hackery ahead */ 498 | select::-ms-expand { 499 | display: none; /* remove default arrow on ie10 and ie11 */ 500 | } 501 | 502 | /* target Internet Explorer 9 to undo the custom arrow */ 503 | @media screen and (min-width:0\0) { 504 | select { 505 | background:none\9; 506 | padding: 5px\9; 507 | } 508 | } 509 | 510 | 511 | /* Tutorial page */ 512 | .tutorial { 513 | background-color: rgba(0, 0, 0, .38); 514 | position: absolute; 515 | top: 0; 516 | left: 0; 517 | bottom: 0; 518 | right: 0; 519 | display: flex; 520 | align-items: center; 521 | justify-content: center; 522 | } 523 | 524 | .tutorial-card { 525 | width: 500px; 526 | z-index: 10000; 527 | max-width: 90%; 528 | } 529 | 530 | [id^=chart] { 531 | margin-top: 20px; 532 | cursor: crosshair; 533 | } 534 | 535 | /* Tab view */ 536 | .tabs { 537 | background-color: #474B52; 538 | width: 100%; 539 | height: 60px; 540 | display: none; 541 | justify-content: center; 542 | } 543 | 544 | .tab { 545 | text-align: center; 546 | width: 160px; 547 | color: #fff; 548 | padding: 18px 0; 549 | text-transform: uppercase; 550 | } 551 | 552 | .tab-active { 553 | border-bottom: solid 3px #FF9800; 554 | } 555 | 556 | .error { 557 | display: flex; 558 | flex-direction: column; 559 | justify-content: center; 560 | align-items: center; 561 | height: 100%; 562 | } 563 | 564 | .error h1 { 565 | margin-bottom: 10px; 566 | } 567 | 568 | .error p { 569 | margin-top: 0; 570 | } 571 | 572 | #emulator_controller { 573 | padding-bottom: 15px; 574 | } 575 | 576 | .mobile-container { 577 | padding: 10px; 578 | box-sizing: border-box; 579 | overflow-y: scroll; 580 | position: absolute; 581 | background-color: #eee; 582 | top: 0; 583 | bottom: 0; 584 | left: 0; 585 | right: 0; 586 | } 587 | 588 | /* Respoinsiveness */ 589 | @media only screen and (max-width: 400px) { 590 | h1.title { 591 | font-size: 18px; 592 | } 593 | } 594 | 595 | @media only screen and (max-width: 1000px) { 596 | .tabs { 597 | display: flex; 598 | } 599 | 600 | .card-container { 601 | justify-content: space-between; 602 | } 603 | 604 | .card-experiment { 605 | flex-grow: 1; 606 | } 607 | 608 | .content { 609 | top: 130px; 610 | } 611 | 612 | .sidebar { 613 | display: none; 614 | } 615 | 616 | .btn-github { 617 | display: none; 618 | } 619 | } 620 | 621 | @media only screen and (max-width: 500px) { 622 | .control-progress { 623 | display: none; 624 | } 625 | } 626 | 627 | body:not(.user-is-tabbing) button:focus, 628 | body:not(.user-is-tabbing) input:focus, 629 | body:not(.user-is-tabbing) select:focus, 630 | body:not(.user-is-tabbing) textarea:focus { 631 | outline: none; 632 | } 633 | 634 | @keyframes flash { 635 | from { 636 | background-color: #FF9800; 637 | } 638 | to { 639 | background-color: rgb(255, 187, 85); 640 | } 641 | } -------------------------------------------------------------------------------- /docs/Simulators.md: -------------------------------------------------------------------------------- 1 | # Simulators 2 | 3 | ## Adding new simulators 4 | Further simulators can be added by calling the `Playground.registerSimulation(name, simulation)` method. 5 | 6 | This method takes two parameters, `name` which specifies the name of the simulation, and `simulation` which is a function that takes the following parameters: 7 | 8 | | Parameter name | Type | Description | 9 | | -------------- | ------ | ----------- | 10 | | `container` | string | The DOM element that the visual portion of the simulator should be initiated in. | 11 | | `options` | object | The options object can contain `onOutputsUpdated` (a callback for handling when an output has been updated), `onFinish` (a callback for handling when a simulation run has finished) and `maxSteps` (the total number of steps that the simulation should run for, default: 10000). | 12 | 13 | The `simulation` function should return an object with the following values: 14 | 15 | - `init` - A function that initiates the visual aspects of the simulator. 16 | - `getInputs` - A function which returns the inputs object. (See the "Specifying Inputs" section) 17 | - `getOutputs` - A function which returns the outputs object. (See the "Specifying Outputs" section) 18 | - `setPaused` - A function which takes a boolean to set the state of the simulator to paused or unpaused. 19 | - `setValue` - A function taking parameters `key` and `value` which sets the value of an input. 20 | - `dispose` - A function to dispose of the simulation 21 | - `startSimulation` - A function to start a run of the simulation. 22 | 23 | ### Specifying Inputs 24 | The `getInputs` function returned from the simulation method should return an object of the inputs. Each input can specify a display name, description, default value, min and max values, and a boolean specifying if the input is hidden from the simulation inputs section by default. Below is an example taken from the taxis simulator: 25 | 26 | ```javascript 27 | /** 28 | * The inputs of the simulator 29 | */ 30 | var inputs = { 31 | gridSize: { 32 | displayName: '@numRoads/title', // The user friendly display name - can use i18n strings 33 | description: '@numRoads/description', // The user friendly description of this input 34 | value: 5, // The default value 35 | min: 3, // The minimum value 36 | max: 10, // The maximum value 37 | hidden: false // Determines if this input is hidden (default is false) 38 | }, 39 | ... 40 | } 41 | ``` 42 | 43 | ### Specifying Outputs 44 | The `getOutputs` function returned from the simulation method should return an object of the outputs. Each output can specify a display name, value, a `toString` function used for formatting the value, and a boolean specifying if the output is hidden from the simulation outputs section. Below is an example taken from the taxi simulator: 45 | 46 | ```javascript 47 | /** 48 | * The outputs of the simulator 49 | */ 50 | var outputs = { 51 | profit: { 52 | displayName: '@profit', // The user friendly display name - can use i18n strings 53 | value: 0, // The value of the output 54 | toString: function() { // Formatting function 55 | // Display as $### if under $1000, or $#.#k if over 56 | if (this.value < -1000) return '-$' + Math.abs((this.value/1000).toFixed(1)) + 'k' 57 | else if (this.value < 0) return '-$' + Math.abs(this.value.toFixed(2)); 58 | else if (this.value < 1000) return '$' + this.value.toFixed(2); 59 | else return '$' + (this.value/1000).toFixed(1) + 'k' 60 | } 61 | }, 62 | ... 63 | } 64 | ``` -------------------------------------------------------------------------------- /docs/Tutorials.md: -------------------------------------------------------------------------------- 1 | # Tutorials 2 | 3 | Tutorials are stored in JSON and accessible at `[Project Root]/config/tutorials.json` 4 | 5 | ## Adding new tutorials 6 | 7 | Tutorials can be added by modifying the tutorials.json file. 8 | 9 | Below is an example of the structure of a tutorial: 10 | 11 | ```json 12 | "introduction": { 13 | "order": 1, 14 | "title": "@title", 15 | "description": "@description", 16 | "estimated_time": 3, 17 | "image": "img/sim.png", 18 | "simulator": { 19 | "name": "taxi", 20 | "inputs": [ "taxiCount", "journeyFrequency", "gridSize" ], 21 | "outputs": [ "profit", "missed", "pickUpTime" ], 22 | "steps": 1000 23 | }, 24 | "tutorial_steps": [ 25 | ... 26 | { 27 | "highlight": "playButton", 28 | "trigger": "endSimulation", 29 | "action": "playSimulation", 30 | "simulator_values": { 31 | "taxiCount": 5 32 | } 33 | }, 34 | ... 35 | ], 36 | "emulators": [ 37 | { 38 | "id": "taxisvsprofit", 39 | "title": "@emulator1/title", 40 | "input": "taxiCount", 41 | "output": "profit", 42 | "xAxisLabel": "Number of Taxis", 43 | "yAxisLabel": "Profit ($)", 44 | "hyperparameters": { 45 | "variance": 10000, 46 | "length": 15, 47 | "noise": 0.0225 48 | }, 49 | "hidden": true, 50 | "showOnStep": 8, 51 | "showSensitivity": false 52 | }], 53 | "end_card": { 54 | "next_tutorial": "bayesian_optimisation", 55 | "extra_action": "Try changing different inputs of the simulator to see the effect on the outputs." 56 | } 57 | } 58 | ``` 59 | 60 | The key of the object represents the unique ID of the tutorial. Tutorials are accessible in the application at the `#!/learn/[Tutorial ID]` endpoint. 61 | 62 | Tutorial objects contain the following properties: 63 | 64 | | Parameter name | Type | Description | 65 | | -------------- | ------ | ----------- | 66 | | `order` | number | The index of the tutorial used to sort tutorials on the home page. Lower values appear first. | 67 | | `title` | string | The user facing title of the tutorial. Can use i18n strings, such as `@title` (maps to `@tutorial/[Tutorial ID]/title`) | 68 | | `description` | string | The user facing description. Can use i18n strings, such as `@description` (maps to `@tutorial/[Tutorial ID]/description`) | 69 | | `estimated_time`| number | The estimated completion time in minutes for this tutorial. Displayed on home page. | 70 | | `image` | string | The URL of the image. Displayed on home page. | 71 | | `simulator` | object | The simulator configuration. Defines the name of the simulator, the visible inputs and outputs for this tutorial (defaults to all) and the number of steps per simulation run (defaults to 1000). | 72 | | `tutorial_steps`| array | The steps featured in the tutorial. See the "Defining tutorial steps" section for details. | 73 | | `emulators` | array | (Optional) Contains emulator configuration. `hidden` specifies if the emulator is shown at the start of the tutorial. | 74 | 75 | 76 | ## Definining tutorial steps 77 | 78 | Each tutorial step is an object contained within `tutorial_steps` with the following properties: 79 | 80 | | Parameter name | Type | Description | 81 | | -------------- | ------ | ----------- | 82 | | `highlight` | string | The ID of the object to highlight to the user. Specifying `"highlight": "self"` shows the card in the middle of the screen. | 83 | | `trigger` | string | (Optional) If a trigger is specified, the card waits for an action to occur before displaying the card. Allowed options for trigger include `midSimulation` and `endSimulation`, which cause cards to appear at 90% completion and upon completion of a simulation run respectively. | 84 | | `action` | string | (Optional) If an action is specified, the next button is disabled and the user is required to perform an action (such as click the play button, specified by setting action to `playSimulation`) before the tutorial is progressed. | 85 | | `simulation_values`| object | (Optional) If specified, the input defined by the key of an entry is set to the value upon this tutorial step activating. | 86 | 87 | 88 | ## Emulators 89 | 90 | Emulators can optionally be added to a tutorial by specifying each of them in the `emulators` array as an object with the following properties: 91 | 92 | | Parameter name | Type | Description | 93 | | -------------- | ------ | ----------- | 94 | | `id` | string | The ID of the object to highlight to the user. This may also be used for highlighting in a tutorial step. | 95 | | `title` | string | (Optional) The title of this emulator. If left unset, the title is generated from the display names of the input and output fields. | 96 | | `input` | string | The ID of the input to the simulator. | 97 | | `output`| string | The ID of the output of the simulator | 98 | | `xAxisLabel` | string | (Optional) The label shown on the X axis of the emulator. | 99 | | `yAxisLabel` | string | (Optional) The label shown on the Y axis of the emulator. | 100 | | `hyperparameters` | Object | (Optional) The hyperparameters of this emulator, including `variance`, `length` (the length scale) and `noise`. | 101 | | `showOnStep` | Number | If set, the emulator is not shown until the user reaches the step given | 102 | | `showSensitivity` | Boolean | If true, the sensitivity (derivative of the mean) is displayed on the emulator at the current input value. | 103 | 104 | 105 | ## End card 106 | 107 | The end card is used to direct users to test their knowledge, and once ready move on to the next tutorial. 108 | 109 | The `end_card` object has the following properties: 110 | 111 | | Parameter name | Type | Description | 112 | | -------------- | ------ | ----------- | 113 | | `next_tutorial`| string | The ID of the next tutorial in the series, which is linked to the user upon completion of this tutorial. | 114 | | `extra_action` | string | Provides the user with a task to complete to test their knowledge based on the tutorial. | 115 | | `simulation_values`| object | (Optional) If specified, the input defined by the key of an entry is set to the value upon this tutorial step activating. | -------------------------------------------------------------------------------- /docs/i18n.md: -------------------------------------------------------------------------------- 1 | # i18n/Multilingual Support 2 | The Emukit Playground has support for additional languages to be added. The playground uses the browser's highest supported preference of language (obtained by [navigator.languages](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages), or [navigator.language](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language) for older browsers), or defaults to English if no supported languages are found. 3 | 4 | We are open to language contributions. Please refer to our [contribution guide](CONTRIBUTING.md) for more information. 5 | 6 | ## Adding a new language 7 | To add a new language, first duplicate `config/i18n/en.json` to a file in the same directory using the naming scheme `[LANGUAGE CODE].json`, where [LANGUAGE CODE] refers to a [BCP 47](http://www.ietf.org/rfc/bcp/bcp47.txt) representation of the language. Valid language codes include "en", "en-US", "fr", "fr-FR", "es-ES", etc. 8 | 9 | Once you have duplicated the file, open `js/playground.js` and add the language code to `languages` array (around line 30). 10 | 11 | Now you can start to translate strings into the new langauge. Do not edit the keys of each entry, only edit the value. 12 | 13 | Once a translation is complete, feel free to submit a PR. Please see the [contribution guide](CONTRIBUTING.md) for more information. -------------------------------------------------------------------------------- /img/arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/bayes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amzn/emukit-playground/4add7627339492d6bdfafd5a647f80a2945db73d/img/bayes.png -------------------------------------------------------------------------------- /img/city.hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amzn/emukit-playground/4add7627339492d6bdfafd5a647f80a2945db73d/img/city.hero.png -------------------------------------------------------------------------------- /img/city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amzn/emukit-playground/4add7627339492d6bdfafd5a647f80a2945db73d/img/city.png -------------------------------------------------------------------------------- /img/hero_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amzn/emukit-playground/4add7627339492d6bdfafd5a647f80a2945db73d/img/hero_bg.png -------------------------------------------------------------------------------- /img/sensitivity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amzn/emukit-playground/4add7627339492d6bdfafd5a647f80a2945db73d/img/sensitivity.png -------------------------------------------------------------------------------- /img/sim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amzn/emukit-playground/4add7627339492d6bdfafd5a647f80a2945db73d/img/sim.png -------------------------------------------------------------------------------- /img/taxi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amzn/emukit-playground/4add7627339492d6bdfafd5a647f80a2945db73d/img/taxi.png -------------------------------------------------------------------------------- /img/taxisim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amzn/emukit-playground/4add7627339492d6bdfafd5a647f80a2945db73d/img/taxisim.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |0 1 12 1 1 13 2 1 14 3 1 15 4 0 8 5 0 9 6 0 10 7 0 11 3 2 20 2 2 21 5 2 22 4 2 23 7 3 16 6 3 17 1 3 18 0 3 19 3 4 0 4 4 1 7 4 2 0 4 3 5 5 4 2 5 5 1 5 6 6 5 7
89 |0 1 12 1 1 13 2 1 14 3 1 15 4 0 8 5 0 9 6 0 10 7 0 11 3 2 20 2 2 21 5 2 22 4 2 23 7 3 16 6 3 17 1 3 18 0 3 19 3 4 0 4 4 1 7 4 2 0 4 3 5 5 4 2 5 5 1 5 6 6 5 7
89 |0 1 12 1 1 13 2 1 14 3 1 15 4 0 8 5 0 9 6 0 10 7 0 11 3 2 20 2 2 21 5 2 22 4 2 23 7 3 16 6 3 17 1 3 18 0 3 19 3 4 0 4 4 1 7 4 2 0 4 3 5 5 4 2 5 5 1 5 6 6 5 7
89 |0 1 8 1 1 9 2 1 10 3 1 11 4 1 32 5 1 33 6 1 34 7 1 35 8 1 64 9 1 65 10 1 66 11 1 67 12 1 124 13 1 125 14 1 126 15 1 127 16 1 196 17 1 197 18 1 198 19 1 199 20 1 180 21 1 181 22 1 182 23 1 183 24 1 164 25 1 165 26 1 166 27 1 167 28 1 168 29 1 169 30 1 170 31 1 171 32 1 172 33 1 173 34 1 174 35 1 175 36 1 176 37 1 177 38 1 178 39 1 179 40 0 20 41 0 21 42 0 22 43 0 23 44 0 36 45 0 37 46 0 38 47 0 39 48 0 68 49 0 69 50 0 70 51 0 71 52 0 96 53 0 97 54 0 98 55 0 99 56 0 120 57 0 121 58 0 122 59 0 123 60 0 236 61 0 237 62 0 238 63 0 239 64 0 208 65 0 209 66 0 210 67 0 211 68 0 204 69 0 205 70 0 206 71 0 207 72 0 212 73 0 213 74 0 214 75 0 215 3 2 12 76 2 13 41 2 14 40 2 15 47 2 40 46 2 41 5 2 42 4 2 43 11 2 52 10 2 53 49 2 54 48 2 55 76 2 108 2 2 109 25 2 110 24 2 111 19 2 136 18 2 137 61 2 138 60 2 139 23 2 132 22 2 133 65 2 134 64 2 135 31 2 140 30 2 141 69 2 142 68 2 143 35 2 160 34 2 161 73 2 162 72 2 163 15 2 216 14 2 217 57 2 218 56 2 219 27 2 220 26 2 221 53 2 222 52 2 223 43 3 16 42 3 17 77 3 18 0 3 19 7 3 28 6 3 29 45 3 30 44 3 31 51 3 48 50 3 49 9 3 50 8 3 51 39 3 112 38 3 113 1 3 114 77 3 115 63 3 156 62 3 157 17 3 158 16 3 159 67 3 144 66 3 145 21 3 146 20 3 147 71 3 148 70 3 149 29 3 150 28 3 151 75 3 152 74 3 153 33 3 154 32 3 155 59 3 240 58 3 241 13 3 242 12 3 243 55 3 232 54 3 233 37 3 234 36 3 235 3 4 0 78 4 1 79 4 2 0 4 3 45 4 24 6 4 25 5 4 26 46 4 27 11 4 56 2 4 57 1 4 58 8 4 59 80 4 60 48 4 61 51 4 62 81 4 63 82 4 116 40 4 117 43 4 118 83 4 119 15 4 128 56 4 129 59 4 130 12 4 131 78 4 224 82 4 225 57 4 226 14 4 227 13 4 228 58 4 229 83 4 230 79 4 231 27 4 200 52 4 201 41 4 202 24 4 203 39 4 192 42 4 193 55 4 194 36 4 195 31 5 4 60 5 5 67 5 6 32 5 7 7 5 44 44 5 45 47 5 46 4 5 47 63 5 72 16 5 73 23 5 74 64 5 75 71 5 76 28 5 77 35 5 78 72 5 79 61 5 88 18 5 89 17 5 90 62 5 91 65 5 84 22 5 85 21 5 86 66 5 87 69 5 92 30 5 93 29 5 94 70 5 95 73 5 80 34 5 81 33 5 82 74 5 83 19 5 100 10 5 101 9 5 102 20 5 103 49 5 104 68 5 105 75 5 106 50 5 107 53 5 184 26 5 185 25 5 186 80 5 187 81 5 188 38 5 189 37 5 190 54 5 191
89 |