diff --git a/README.md b/README.md
index 2aa27da..bf810b5 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,7 @@
1. [Creating an AnyLogic simulation](#creating-an-anylogic-simulation)
2. [Preparing the AnyLogic simulation for Bonsai](#preparing-the-anylogic-simulation-for-bonsai)
3. [Attaching AnyLogic telemetry by querying ADT](#attaching-anylogic-telemetry-by-querying-adt)
+ 4. [Exporting the AnyLogic Model for Bonsai](#exporting-the-anylogic-model-for-bonsai)
10. [Python Simulation](#python-simulation)
1. [Creating a Python Simulation](#creating-a-python-simulation)
2. [Preparing the Python simulation for Bonsai](#preparing-the-python-simulation-for-bonsai)
@@ -884,9 +885,33 @@ We can also verify in ADT that our simulated device's twin no longer exists.
+
+RLExperiment is a type of experiment in AnyLogic that simplifies the wrapping of an AnyLogic model so that it can be easily trained in a RL training platform such as Bonsai. Without RLExperiment, you'd have to use a separate wrapper class in order to use the model for reinforcement learning.
+Note: By the time this tutorial is created, AnyLogic RLExperiment currently does not support local training. RLExperiment is only used for wrapping and exporting the model/simulation for Bonsai or any other RL Training platform.
+
+To use RLExperiment, simply add it to the AnyLogic model.
+
+
+
+** There is already an existing RLExperiment on this model. The above screenshots just show how to add one.
+
+To use RLExperiment, the Observation, Action and Configuration fields must be filled in. The **Observation** field comprises the data being passed to the Bonsai brain in order to make a decision. The **Action** field comprises the parameters that the Bonsai brain can manipulate after making a decision. Lastly, the **Configuration** field comprises the parameters that the Bonsai can set as the model's initial condition/state.
+
+The fields' values are mapped from the **Top-level agent** which is being referenced as **root**.
+
+
#### Attaching AnyLogic Telemetry By Querying ADT ####

+
+#### Exporting the AnyLogic Model for Bonsai ####
+1. Right-click the model, select 'Export > Reinforcement Learning'.
+
+2. Take note of the destination folder where the zip file will be exported. The zip file will be used later when training in Bonsai.
+
+3. Finish the export.
+
+
### Python Simulation ###
#### Creating a Python Simulation ####
#### Preparing the Python simulation for Bonsai ####
@@ -1133,8 +1158,141 @@ if __name__ == "__main__":
### Microsoft Bonsai Teaching ###
#### Testing The Simulation ####
#### Importing The Simulation ####
+ NOTE: The following only applies for AnyLogic Simulations.
+1. Go to Bonsai Workspace and click 'Add Sim'.
+
+2. Select 'AnyLogic'.
+
+3. Upload the [exported zip](#exporting-the-anylogic-model-for-bonsai) of the AnyLogic model and provide a name for the simulator.
+
+4. Copy the package statement. This will be used later in the inkling code.
+
+
#### Creating The Brain ####
+1. Go to the Bonsai Workspace and click 'Create Brain'.
+
+2. Select 'Empty Brain' and enter details.
+
+
+3. After the brain is created, go to the 'Teach' tab and paste the following inkling code.
+
+```python
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+inkling "2.0"
+using Math
+using Goal
+# SimState has the same properties as the Observation fields in the RLExperiment
+type SimState {
+ arrivalRate: number<0 .. 2.0>,
+ recentNProducts: number,
+ costPerProduct: number,
+ utilizationResourceA: number<0 .. 1>,
+ utilizationResourceB: number<0 .. 1>,
+ ratioFullQueueA: number<0 .. 1>,
+ ratioFullQueueB: number<0 .. 1>,
+ ratioCostIdleA: number<0 .. 1>,
+ ratioCostIdleB: number<0 .. 1>,
+ ratioCostWaiting: number<0 .. 1>,
+ ratioCostProcessing: number<0 .. 1>,
+ ratioCostMoving: number<0 .. 1>,
+
+ exceededCapacityFlag: number<0, 1, >,
+ simTimeHours: number<0 .. 24>
+}
+# The ObservableState is what the brain sees from the simulator.
+# In this case, it's just the arrival rate.
+type ObservableState {
+ arrivalRate: number
+}
+
+type Action {
+ numResourceA: number<1 .. 20>,
+ numResourceB: number<1 .. 20>,
+ conveyorSpeed: number<0.01 .. 1.0>,
+}
+type SimConfig {
+ arrivalRate: number,
+ sizeBufferQueues: number
+}
+simulator Simulator(action: Action, config: SimConfig): SimState {
+
+}
+# SimAction is the values translated for the sim.
+# We do not need ranges here.
+# These are the same as the ModelAction class.
+type SimAction {
+ numResourceA: number,
+ numResourceB: number,
+ conveyorSpeed: number,
+}
+
+function Terminal(obs: SimState) {
+ if (obs.exceededCapacityFlag == 1) {
+ return true
+ }
+
+
+ # The brain gets one chance at the answer
+ return obs.simTimeHours >= 6
+}
+function Reward(obs: SimState) {
+ # Large penalty for exceeding the buffer queue's capacity.
+ # Otherwise, try to maximize the cost per product value.
+ return -obs.costPerProduct - 1000 * obs.exceededCapacityFlag
+
+}
+graph (input: ObservableState): Action {
+
+ concept optimize(input): Action {
+ curriculum {
+ source Simulator
+ reward Reward
+ terminal Terminal
+ lesson `Vary Arrival Rate` {
+ # These map to the SimConfig values
+ scenario {
+ arrivalRate: number<0.5 .. 2.0 step .05>,
+ sizeBufferQueues: 45
+ }
+ }
+ }
+ }
+ output optimize
+}
+
+```
+4. Paste the [package statement](#importing-the-simulation) in the simulator object code.
+
+
+
#### Teaching The Brain ####
+1. Go to the 'Train' tab and click the 'Train' button to begin training.
+
+2. Training should begin after all the simulator instances are running. On the bottom, a chart showing the values of different variables can be seen.
+
+3. You can add more charts using the 'Add chart' button.
+
+4. Training usually takes a long time. After a few thousand iterations, the main graph should show the **brain performance** and **mean brain performance**.
+
+5. You may stop the training if you think the performance is good enough.
+
+
#### Exporting The Brain ####
+Once the training is done, the brain can now be exported for use. The brain is usually exported as a docker image which can be run locally or in the cloud as a web app. The exported docker image, when run, can be exposed as a REST API.
+1. Click 'Export brain'
+
+2. Provide the brain's display name. There's no need to change the processor architecture.
+
+3. In the deployment instructions after export, copy the string following the 'docker pull' command.
+
#### Running A Simulation Using The Brain ####
+ NOTE: The following only applies for AnyLogic Simulations.
+
+1. Go to the Playback Experiment in AnyLogic and paste the string from the [exported brain](#exporting-the-brain) following 'https://'.
+
+2. Run the Playback Experiment.
+
+
+
#### Other Scenarios For Using The Trained Brain ####