Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • flatland/flatland
  • stefan_otte/flatland
  • jiaodaxiaozi/flatland
  • sfwatergit/flatland
  • utozx126/flatland
  • ChenKuanSun/flatland
  • ashivani/flatland
  • minhhoa/flatland
  • pranjal_dhole/flatland
  • darthgera123/flatland
  • rivesunder/flatland
  • thomaslecat/flatland
  • joel_joseph/flatland
  • kchour/flatland
  • alex_zharichenko/flatland
  • yoogottamk/flatland
  • troye_fang/flatland
  • elrichgro/flatland
  • jun_jin/flatland
  • nimishsantosh107/flatland
20 results
Show changes
Commits on Source (579)
Showing
with 404 additions and 198 deletions
...@@ -11,7 +11,7 @@ __pycache__/ ...@@ -11,7 +11,7 @@ __pycache__/
env/ env/
build/ build/
develop-eggs/ develop-eggs/
dist/ # dist/
downloads/ downloads/
eggs/ eggs/
.eggs/ .eggs/
...@@ -117,3 +117,11 @@ images/test/ ...@@ -117,3 +117,11 @@ images/test/
test_save.dat test_save.dat
.visualizations .visualizations
playground/
**/tmp
**/TEMP
*.pkl
images
\ No newline at end of file
...@@ -10,42 +10,69 @@ image: themattrix/tox ...@@ -10,42 +10,69 @@ image: themattrix/tox
## - AWS_SECRET_ACCESS_KEY ## - AWS_SECRET_ACCESS_KEY
stages: stages:
- build_wheel
- tests - tests
- integration_testing - integration_testing
- profiling - profiling
- benchmarks - benchmarks
- deploy_docs - deploy_docs
cache:
paths:
- .tox
before_script: before_script:
- echo "Setting Up...." - echo "Setting Up...."
tests: .test-setup: &test-setup
stage: tests stage: tests
services:
- redis
before_script: before_script:
- apt update - apt update
- apt install -y libgl1-mesa-glx xvfb graphviz xdg-utils libcairo2-dev libjpeg-dev libgif-dev - apt install -y libgl1-mesa-glx xvfb graphviz libgraphviz-dev xdg-utils libcairo2-dev libjpeg-dev libgif-dev python-pyglet
- wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh - wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh
- bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3 - bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3
- export PATH=/tmp/miniconda3/bin:$PATH - export PATH=/tmp/miniconda3/bin:$PATH
- pip install tox awscli - pip install tox awscli
- conda update -n root conda -y - conda update -n root conda -y
- conda install -c conda-forge tox-conda - conda install -c conda-forge tox-conda -y
test-py37:
<<: *test-setup
script:
- xvfb-run tox -v --recreate -e py37
test-py38:
<<: *test-setup
script:
- xvfb-run tox -v --recreate -e py38
test-notebooks:
<<: *test-setup
script:
- xvfb-run tox -v --recreate -e notebooks
test-examples:
<<: *test-setup
script: script:
- xvfb-run tox -v --recreate - xvfb-run tox -v --recreate -e examples
test-docs:
<<: *test-setup
script:
- xvfb-run tox -v --recreate -e docs
test-coverage:
<<: *test-setup
script:
- xvfb-run tox -v --recreate -e coverage
build_and_deploy_docs: build_and_deploy_docs:
image: "python:latest"
stage: deploy_docs stage: deploy_docs
only: only:
- master - master
dependencies: dependencies:
- tests - test-docs
before_script: before_script:
- apt update - apt update
- apt install -y libgl1-mesa-glx xvfb xdg-utils libcairo2-dev libjpeg-dev libgif-dev - apt install -y libgl1-mesa-glx xvfb xdg-utils libcairo2-dev libjpeg-dev libgif-dev graphviz libgraphviz-dev python-pyglet
- wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh - wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh
- bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3 - bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3
- export PATH=/tmp/miniconda3/bin:$PATH - export PATH=/tmp/miniconda3/bin:$PATH
...@@ -64,14 +91,18 @@ build_and_deploy_docs: ...@@ -64,14 +91,18 @@ build_and_deploy_docs:
profiling: profiling:
dependencies: dependencies:
- tests - test-py38
- test-py37
- test-notebooks
- test-examples
- test-coverage
stage: profiling stage: profiling
only: only:
variables: variables:
- $BENCHMARKS_AND_PROFILING - $BENCHMARKS_AND_PROFILING
before_script: before_script:
- apt update - apt update
- apt install -y libgl1-mesa-glx xvfb xdg-utils libcairo2-dev libjpeg-dev libgif-dev - apt install -y libgl1-mesa-glx xvfb xdg-utils libcairo2-dev libjpeg-dev libgif-dev graphviz libgraphviz-dev python-pyglet
- wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh - wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh
- bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3 - bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3
- export PATH=/tmp/miniconda3/bin:$PATH - export PATH=/tmp/miniconda3/bin:$PATH
...@@ -83,14 +114,18 @@ profiling: ...@@ -83,14 +114,18 @@ profiling:
benchmarks: benchmarks:
dependencies: dependencies:
- tests - test-py38
- test-py37
- test-notebooks
- test-examples
- test-coverage
stage: benchmarks stage: benchmarks
only: only:
variables: variables:
- $BENCHMARKS_AND_PROFILING - $BENCHMARKS_AND_PROFILING
before_script: before_script:
- apt update - apt update
- apt install -y libgl1-mesa-glx xvfb xdg-utils libcairo2-dev libjpeg-dev libgif-dev - apt install -y libgl1-mesa-glx xvfb xdg-utils libcairo2-dev libjpeg-dev libgif-dev graphviz libgraphviz-dev python-pyglet
- wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh - wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh
- bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3 - bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3
- export PATH=/tmp/miniconda3/bin:$PATH - export PATH=/tmp/miniconda3/bin:$PATH
...@@ -102,9 +137,11 @@ benchmarks: ...@@ -102,9 +137,11 @@ benchmarks:
test_conda_setup: test_conda_setup:
stage: integration_testing stage: integration_testing
services:
- redis
before_script: before_script:
- apt update - apt update
- apt install -y libgl1-mesa-glx xvfb xdg-utils libcairo2-dev libjpeg-dev libgif-dev - apt install -y libgl1-mesa-glx xvfb xdg-utils libcairo2-dev libjpeg-dev libgif-dev graphviz libgraphviz-dev python-pyglet
- wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh - wget -nv https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/Miniconda3-latest-Linux-x86_64.sh
- bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3 - bash /tmp/Miniconda3-latest-Linux-x86_64.sh -b -p /tmp/miniconda3
- export PATH=/tmp/miniconda3/bin:$PATH - export PATH=/tmp/miniconda3/bin:$PATH
...@@ -112,4 +149,18 @@ test_conda_setup: ...@@ -112,4 +149,18 @@ test_conda_setup:
script: script:
- xvfb-run bash getting_started/getting_started.sh - xvfb-run bash getting_started/getting_started.sh
build_wheel:
image: "python:3.7-slim"
stage: build_wheel
before_script:
- apt update
- apt install -y make
- pip install -r requirements_dev.txt
script:
- make dist
- export WHEEL_NAME="$( find dist -name 'flatland_rl*.whl' )"
- mv "${WHEEL_NAME}" "${WHEEL_NAME/-py2.py3-/-py3-}"
artifacts:
paths:
- dist/flatland_rl*.whl
expire_in: 2 mos
...@@ -108,21 +108,22 @@ Merge Request Guidelines ...@@ -108,21 +108,22 @@ Merge Request Guidelines
Before you submit a merge request, check that it meets these guidelines: Before you submit a merge request, check that it meets these guidelines:
1. The merge request should include tests. 1. The merge request should include tests.
2. If the merge request adds functionality, the docs should be updated. Put 2. The code must be formatted (PyCharm)
3. If the merge request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the your new functionality into a function with a docstring, and add the
feature to the list in README.rst. feature to the list in README.rst.
3. The merge request should work for Python 3.6, 3.7 and for PyPy. Check 4. The merge request should work for Python 3.6, 3.7 and for PyPy. Check
https://gitlab.aicrowd.com/flatland/flatland/pipelines https://gitlab.aicrowd.com/flatland/flatland/pipelines
and make sure that the tests pass for all supported Python versions. and make sure that the tests pass for all supported Python versions.
We force pipelines to be run successfully for merge requests to be merged. We force pipelines to be run successfully for merge requests to be merged.
4. Although we cannot enforce it technically, we ask for merge requests to be reviewed by at least one core member 5. Although we cannot enforce it technically, we ask for merge requests to be reviewed by at least one core member
in order to ensure that the Technical Guidelines below are respected and that the code is well tested: in order to ensure that the Technical Guidelines below are respected and that the code is well tested:
4.1 The remarks from the review should be resolved/implemented and communicated using the 'discussions resolved': 5.1. The remarks from the review should be resolved/implemented and communicated using the 'discussions resolved':
.. image:: images/DiscussionsResolved.png .. image:: images/DiscussionsResolved.png
4.2 When a merge request is merged, source branches should be deleted and commits squashed: 5.2. When a merge request is merged, source branches should be deleted and commits squashed:
.. image:: images/SourceBranchSquash.png .. image:: images/SourceBranchSquash.png
...@@ -216,6 +217,10 @@ RemoteClient ...@@ -216,6 +217,10 @@ RemoteClient
Technical Guidelines Technical Guidelines
-------------------- --------------------
Clean Code
~~~~~~~~~~
Please adhere to the general `Clean Code <https://www.planetgeek.ch/wp-content/uploads/2014/11/Clean-Code-V2.4.pdf>`_ principles,
for instance we write short and concise functions and use appropriate naming to ensure readability.
Naming Conventions Naming Conventions
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
...@@ -237,7 +242,7 @@ Docstrings should be formatted using numpydoc_. ...@@ -237,7 +242,7 @@ Docstrings should be formatted using numpydoc_.
Acessing resources Acessing resources
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
We use `importlib-resources`_ to read from local files. We use `importlib-resources <https://importlib-resources.readthedocs.io/en/latest/>`_ to read from local files.
Sample usages: Sample usages:
.. code-block:: python .. code-block:: python
...@@ -257,7 +262,6 @@ We use `importlib-resources`_ to read from local files. ...@@ -257,7 +262,6 @@ We use `importlib-resources`_ to read from local files.
self.set_full_state_msg(load_data) self.set_full_state_msg(load_data)
.. _importlib-resources: https://importlib-resources.readthedocs.io/en/latest/
Renders the scene into a image (screenshot) Renders the scene into a image (screenshot)
...@@ -267,7 +271,8 @@ We use `importlib-resources`_ to read from local files. ...@@ -267,7 +271,8 @@ We use `importlib-resources`_ to read from local files.
Type Hints Type Hints
~~~~~~~~~~ ~~~~~~~~~~
We use Type Hints (type_hints_pep484_) for better readability and better IDE support.
We use Type Hints (`PEP 484 <https://www.python.org/dev/peps/pep-0484/>`_) for better readability and better IDE support.
.. code-block:: python .. code-block:: python
# This is how you declare the type of a variable type in Python 3.6 # This is how you declare the type of a variable type in Python 3.6
...@@ -287,9 +292,9 @@ We use Type Hints (type_hints_pep484_) for better readability and better IDE sup ...@@ -287,9 +292,9 @@ We use Type Hints (type_hints_pep484_) for better readability and better IDE sup
else: else:
child = False child = False
Have a look at the _type_hints_cheat_sheet to get started with Type Hints. Have a look at the `Type Hints Cheat Sheet <https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html>`_ to get started with Type Hints.
Caveat: We discourage the usage of Type Aliases for structured data since its members remain unnamed (see refactor_unnamed_tuples_). Caveat: We discourage the usage of Type Aliases for structured data since its members remain unnamed (see `Issue #284 <https://gitlab.aicrowd.com/flatland/flatland/issues/284/>`_).
.. code-block:: python .. code-block:: python
# Discouraged: Type Alias with unnamed members # Discouraged: Type Alias with unnamed members
...@@ -305,15 +310,11 @@ Caveat: We discourage the usage of Type Aliases for structured data since its me ...@@ -305,15 +310,11 @@ Caveat: We discourage the usage of Type Aliases for structured data since its me
] ]
.. _type_hints_pep484: https://www.python.org/dev/peps/pep-0484/
.. _type_hints_cheat_sheet: https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html
.. _refactor_unnamed_tuples: https://gitlab.aicrowd.com/flatland/flatland/issues/284
NamedTuple NamedTuple
~~~~~~~~~~ ~~~~~~~~~~
For structured data containers for which we do not write methods that have to ensure For structured data containers for which we do not write additional methods, we use
some (class) invariant over multiple members, we use `NamedTuple` instead of plain `Dict` to ensure better readability by
`NamedTuple`s instead of plain `Dict`s to ensure better readability by
.. code-block:: python .. code-block:: python
from typing import NamedTuple from typing import NamedTuple
...@@ -327,9 +328,15 @@ some (class) invariant over multiple members, we use ...@@ -327,9 +328,15 @@ some (class) invariant over multiple members, we use
Members of NamedTuple can then be accessed through `.<member>` instead of `['<key>']`. Members of NamedTuple can then be accessed through `.<member>` instead of `['<key>']`.
If we have to ensure some (class) invariant over multiple members
(for instance, `o.A` always changes at the same time as `o.B`),
then we should uses classes instead, see the next section.
Class Attributes Class Attributes
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
We use classes for data structures if we need to write methods that ensure (class) invariants over multiple members.
We use classes for data structures if we need to write methods that ensure (class) invariants over multiple members,
for instance, `o.A` always changes at the same time as `o.B`.
We use the attrs_ class decorator and a way to declaratively define the attributes on that class: We use the attrs_ class decorator and a way to declaratively define the attributes on that class:
.. code-block:: python .. code-block:: python
...@@ -396,9 +403,10 @@ And then ...@@ -396,9 +403,10 @@ And then
Currying Currying
~~~~~~~~ ~~~~~~~~
We discourage currying to encapsulate state since we often the stateful object to have multiple methods. We discourage currying to encapsulate state since we often want the stateful object to have multiple methods
(but the curried function has only its signature and abusing params to switch behaviour is not very readable).
Thus, we should refactor our generators and use classes instead (refactor_currying_). Thus, we should refactor our generators and use classes instead (see `Issue #283 <https://gitlab.aicrowd.com/flatland/flatland/issues/283>`_).
.. code-block:: python .. code-block:: python
# Type Alias # Type Alias
...@@ -412,4 +420,4 @@ Thus, we should refactor our generators and use classes instead (refactor_curryi ...@@ -412,4 +420,4 @@ Thus, we should refactor our generators and use classes instead (refactor_curryi
max_dist=99999, max_dist=99999,
seed=1) -> RailGenerator: seed=1) -> RailGenerator:
.. _refactor_currying: https://gitlab.aicrowd.com/flatland/flatland/issues/283
...@@ -3,3 +3,12 @@ ...@@ -3,3 +3,12 @@
### Why are my trains drawn outside of the rails? ### Why are my trains drawn outside of the rails?
If you render your environment and the agents appear to be off the rail it is usually due to changes in the railway infrastructure. Make sure that you reset your renderer anytime the infrastructure changes by calling `env_renderer.reset(). If you render your environment and the agents appear to be off the rail it is usually due to changes in the railway infrastructure. Make sure that you reset your renderer anytime the infrastructure changes by calling `env_renderer.reset().
` `
### I keep getting there error when submitting from windows
When submitting from a Windows system you might run into the following error:
```
OSError: dlopen() failed to load a library: cairo / cairo-2 / cairo-gobject-2 / cairo.so.2
```
Please follow the intstruction in the starter-kit to avoid these problems. Make sure to reset your `environment.yml` correctly.
[Link to Windows submission instructions](https://github.com/AIcrowd/flatland-challenge-starter-kit/blob/master/windows_submission.md)
...@@ -53,3 +53,79 @@ The environments vary in size and number of agents as well as malfunction parame ...@@ -53,3 +53,79 @@ The environments vary in size and number of agents as well as malfunction parame
- `(x_dim, y_dim) <= (150, 150)` - `(x_dim, y_dim) <= (150, 150)`
- `n_agents <= 250` (this might be updated) - `n_agents <= 250` (this might be updated)
- `malfunction rates` this is currently being refactored - `malfunction rates` this is currently being refactored
### How can I experiment locally before submitting?
You can follow the instruction in the [starter kit](https://github.com/AIcrowd/flatland-challenge-starter-kit) and use the [provided example files](https://www.aicrowd.com/challenges/flatland-challenge/dataset_files) to run your tests locally.
If you want to generate your own test instances to test your solution you can either head over to the [torch baselines](https://gitlab.aicrowd.com/flatland/baselines/tree/master/torch_training) and get inspired by the setup there.
Or you can generate your own test cases by using the same generators as used by the submission test set.
In order to generate the appropriate levels you need to import the `malfunction_generator`, `rail_generator` and `schedule_generator` as follows:
```
from flatland.envs.malfunction_generators import malfunction_from_params
from flatland.envs.rail_env import RailEnv
from flatland.envs.rail_generators import sparse_rail_generator
from flatland.envs.schedule_generators import sparse_schedule_generator
```
Then you can simply generate levels by instantiating:
```python
stochastic_data = {'malfunction_rate': 8000, # Rate of malfunction occurence of single agent
'min_duration': 15, # Minimal duration of malfunction
'max_duration': 50 # Max duration of malfunction
}
# Custom observation builder without predictor
observation_builder = YourObservationBuilder()
width = 16 * 7 # With of map
height = 9 * 7 # Height of map
nr_trains = 50 # Number of trains that have an assigned task in the env
cities_in_map = 20 # Number of cities where agents can start or end
seed = 14 # Random seed
grid_distribution_of_cities = False # Type of city distribution, if False cities are randomly placed
max_rails_between_cities = 2 # Max number of tracks allowed between cities. This is number of entry point to a city
max_rail_in_cities = 6 # Max number of parallel tracks within a city, representing a realistic trainstation
rail_generator = sparse_rail_generator(max_num_cities=cities_in_map,
seed=seed,
grid_mode=grid_distribution_of_cities,
max_rails_between_cities=max_rails_between_cities,
max_rails_in_city=max_rail_in_cities,
)
# Different agent types (trains) with different speeds.
speed_ration_map = {1.: 0.25, # Fast passenger train
1. / 2.: 0.25, # Fast freight train
1. / 3.: 0.25, # Slow commuter train
1. / 4.: 0.25} # Slow freight train
# We can now initiate the schedule generator with the given speed profiles
schedule_generator = sparse_schedule_generator(speed_ration_map)
# Construct the enviornment with the given observation, generataors, predictors, and stochastic data
env = RailEnv(width=width,
height=height,
rail_generator=rail_generator,
schedule_generator=schedule_generator,
number_of_agents=nr_trains,
obs_builder_object=observation_builder,
malfunction_generator_and_process_data=malfunction_from_params(stochastic_data),
remove_agents_at_target=True)
```
For the testing of you submission you should test different levels in these parameter ranges:
- `width` and `height` between `20` and `150`
- `nr_train` between `50` and `200`
- `n_cities` between `2` and `35`
- `max_rails_between_cities` between `2` and `4`
- `max_rail_in_city` between `3` and `6`
- `malfunction_rate` between `500` and `4000`
- `min_duration` and `max_duration` in ranges from `20` to `80`
- speeds you can keep more or less equally distributed.
With these parameters you should get a good feeling of the test cases your algorithm will be tested against.
...@@ -30,7 +30,7 @@ Each agent is an object and contains the following information: ...@@ -30,7 +30,7 @@ Each agent is an object and contains the following information:
- The attribute `'transition_action_on_cellexit'` contains the information about the action that will be performed at the exit of the cell. Due to speeds smaller than 1. agents have to take several steps within a cell. We however only allow an action to be chosen at cell entry. - The attribute `'transition_action_on_cellexit'` contains the information about the action that will be performed at the exit of the cell. Due to speeds smaller than 1. agents have to take several steps within a cell. We however only allow an action to be chosen at cell entry.
- `malfunction_data = attrib(default=Factory(lambda: dict({'malfunction': 0, 'malfunction_rate': 0, 'next_malfunction': 0, 'nr_malfunctions': 0,'moving_before_malfunction': False})))`: Contains all information relevant for agent malfunctions: - `malfunction_data = attrib(default=Factory(lambda: dict({'malfunction': 0, 'malfunction_rate': 0, 'next_malfunction': 0, 'nr_malfunctions': 0,'moving_before_malfunction': False})))`: Contains all information relevant for agent malfunctions:
- The attribute `'malfunction` indicates if the agent is currently broken. If the value is larger than `0` the agent is broken. The integer value represents the number of `env.step()` calls the agent will still be broken. - The attribute `'malfunction` indicates if the agent is currently broken. If the value is larger than `0` the agent is broken. The integer value represents the number of `env.step()` calls the agent will still be broken.
- The attribute `'next_malfunction'` will be REMOVED as it serves no purpose anymore, malfunctions are now generated by a poisson process. - The attribute `'next_malfunction'` was REMOVED as it serves no purpose anymore, malfunctions are now generated by a poisson process.
- The attribute `'nr_malfunctions'` is a counter that keeps track of the number of malfunctions a specific agent has had. - The attribute `'nr_malfunctions'` is a counter that keeps track of the number of malfunctions a specific agent has had.
- The attribute `'moving_before_malfunction'` is an internal parameter used to restart agents that were moving automatically after the malfunction is fixed. - The attribute `'moving_before_malfunction'` is an internal parameter used to restart agents that were moving automatically after the malfunction is fixed.
- `status = attrib(default=RailAgentStatus.READY_TO_DEPART, type=RailAgentStatus)`: The status of the agent explains what the agent is currently doing. It can be in either one of these states: - `status = attrib(default=RailAgentStatus.READY_TO_DEPART, type=RailAgentStatus)`: The status of the agent explains what the agent is currently doing. It can be in either one of these states:
......
...@@ -9,7 +9,7 @@ include requirements_continuous_integration.txt ...@@ -9,7 +9,7 @@ include requirements_continuous_integration.txt
graft svg graft flatland/png
graft env_data graft env_data
......
Flatland 🚂 Flatland
======== ========
![Test Running](https://gitlab.aicrowd.com/flatland/flatland/badges/master/pipeline.svg)![Test Coverage](https://gitlab.aicrowd.com/flatland/flatland/badges/master/coverage.svg "asdff")
![Flatland](https://i.imgur.com/0rnbSLY.gif) ![Flatland](https://i.imgur.com/0rnbSLY.gif)
## About Flatland <p style="text-align:center">
<img alt="repository" src="https://gitlab.aicrowd.com/flatland/flatland/badges/master/pipeline.svg">
<img alt="coverage" src="https://gitlab.aicrowd.com/flatland/flatland/badges/master/coverage.svg">
</p>
Flatland is a opensource toolkit for developing and comparing Multi Agent Reinforcement Learning algorithms in little (or ridiculously large !) gridworlds. Flatland is a open-source toolkit for developing and comparing Multi Agent Reinforcement Learning algorithms in little (or ridiculously large!) gridworlds.
The base environment is a two-dimensional grid in which many agents can be placed, and each agent must solve one or more navigational tasks in the grid world. More details about the environment and the problem statement can be found in the [official docs](http://flatland-rl-docs.s3-website.eu-central-1.amazonaws.com/). [The official documentation](http://flatland.aicrowd.com/) contains full details about the environment and problem statement
This library was developed by [SBB](<https://www.sbb.ch/en/>), [AIcrowd](https://www.aicrowd.com/) and numerous contributors and AIcrowd research fellows from the AIcrowd community. Flatland is tested with Python 3.6, 3.7 and 3.8 on modern versions of macOS, Linux and Windows. You may encounter problems with graphical rendering if you use WSL. Your [contribution is welcome](https://flatland.aicrowd.com/misc/contributing.html) if you can help with this!
This library was developed specifically for the [Flatland Challenge](https://www.aicrowd.com/challenges/flatland-challenge) in which we strongly encourage you to take part in. 🏆 Challenges
---
**NOTE This document is best viewed in the official documentation site at** [Flatland-RL Docs](http://flatland-rl-docs.s3-website.eu-central-1.amazonaws.com/) This library was developed specifically for the AIcrowd [Flatland challenges](http://flatland.aicrowd.com/research/top-challenge-solutions.html) in which we strongly encourage you to take part in!
- [Flatland 3 Challenge](https://www.aicrowd.com/challenges/flatland-3) - ONGOING!
- [AMLD 2021 Challenge](https://www.aicrowd.com/challenges/flatland)
- [NeurIPS 2020 Challenge](https://www.aicrowd.com/challenges/neurips-2020-flatland-challenge/)
- [2019 Challenge](https://www.aicrowd.com/challenges/flatland-challenge)
## Installation 📦 Setup
### Installation Prerequistes ---
* Install [Anaconda](https://www.anaconda.com/distribution/) by following the instructions [here](https://www.anaconda.com/distribution/). ### Prerequisites (optional)
* Create a new conda environment:
```console
$ conda create python=3.6 --name flatland-rl
$ conda activate flatland-rl
```
* Install the necessary dependencies Install [Anaconda](https://www.anaconda.com/distribution/) and create a new conda environment:
```console ```console
$ conda install -c conda-forge cairosvg pycairo $ conda create python=3.7 --name flatland-rl
$ conda install -c anaconda tk $ conda activate flatland-rl
``` ```
### Install Flatland ### Stable release
#### Stable Release
To install flatland, run this command in your terminal: Install Flatland from pip:
```console ```console
$ pip install flatland-rl $ pip install flatland-rl
``` ```
This is the preferred method to install flatland, as it will always install the most recent stable release. This is the preferred method to install Flatland, as it will always install the most recent stable release.
If you don't have `pip`_ installed, this `Python installation guide`_ can guide
you through the process.
.. _pip: https://pip.pypa.io ### From sources
.. _Python installation guide: http://docs.python-guide.org/en/latest/starting/installation/
The Flatland code source is available from [AIcrowd gitlab](https://gitlab.aicrowd.com/flatland/flatland).
#### From sources Clone the public repository:
The sources for flatland can be downloaded from [gitlab](https://gitlab.aicrowd.com/flatland/flatland)
You can clone the public repository:
```console ```console
$ git clone git@gitlab.aicrowd.com:flatland/flatland.git $ git clone git@gitlab.aicrowd.com:flatland/flatland.git
``` ```
Once you have a copy of the source, you can install it with: Once you have a copy of the source, install it with:
```console ```console
$ python setup.py install $ pip install -e .
``` ```
### Test installation ### Test installation
Test that the installation works Test that the installation works:
```console ```console
$ flatland-demo $ flatland-demo
``` ```
You can also run the full test suite:
```console
### Jupyter Canvas Widget python setup.py test
If you work with jupyter notebook you need to install the Jupyer Canvas Widget. To install the Jupyter Canvas Widget read also
[https://github.com/Who8MyLunch/Jupyter_Canvas_Widget#installation]([https://github.com/Who8MyLunch/Jupyter_Canvas_Widget#installation)
## Basic Usage
Basic usage of the RailEnv environment used by the Flatland Challenge (also see [Example](https://gitlab.aicrowd.com/flatland/flatland/blob/master/examples/introduction_flatland_2_1.py))
```python
from flatland.envs.observations import GlobalObsForRailEnv
# First of all we import the Flatland rail environment
from flatland.envs.rail_env import RailEnv
from flatland.envs.rail_generators import sparse_rail_generator
from flatland.envs.schedule_generators import sparse_schedule_generator
# We also include a renderer because we want to visualize what is going on in the environment
from flatland.utils.rendertools import RenderTool, AgentRenderVariant
width = 100 # With of map
height = 100 # Height of map
nr_trains = 50 # Number of trains that have an assigned task in the env
cities_in_map = 20 # Number of cities where agents can start or end
seed = 14 # Random seed
grid_distribution_of_cities = False # Type of city distribution, if False cities are randomly placed
max_rails_between_cities = 2 # Max number of tracks allowed between cities. This is number of entry point to a city
max_rail_in_cities = 6 # Max number of parallel tracks within a city, representing a realistic trainstation
rail_generator = sparse_rail_generator(max_num_cities=cities_in_map,
seed=seed,
grid_mode=grid_distribution_of_cities,
max_rails_between_cities=max_rails_between_cities,
max_rails_in_city=max_rail_in_cities,
)
# The schedule generator can make very basic schedules with a start point, end point and a speed profile for each agent.
# The speed profiles can be adjusted directly as well as shown later on. We start by introducing a statistical
# distribution of speed profiles
# Different agent types (trains) with different speeds.
speed_ration_map = {1.: 0.25, # Fast passenger train
1. / 2.: 0.25, # Fast freight train
1. / 3.: 0.25, # Slow commuter train
1. / 4.: 0.25} # Slow freight train
# We can now initiate the schedule generator with the given speed profiles
schedule_generator = sparse_schedule_generator(speed_ration_map)
# We can furthermore pass stochastic data to the RailEnv constructor which will allow for stochastic malfunctions
# during an episode.
stochastic_data = {'prop_malfunction': 0.3, # Percentage of defective agents
'malfunction_rate': 30, # Rate of malfunction occurence
'min_duration': 3, # Minimal duration of malfunction
'max_duration': 20 # Max duration of malfunction
}
# Custom observation builder without predictor
observation_builder = GlobalObsForRailEnv()
# Custom observation builder with predictor, uncomment line below if you want to try this one
# observation_builder = TreeObsForRailEnv(max_depth=2, predictor=ShortestPathPredictorForRailEnv())
# Construct the enviornment with the given observation, generataors, predictors, and stochastic data
env = RailEnv(width=width,
height=height,
rail_generator=rail_generator,
schedule_generator=schedule_generator,
number_of_agents=nr_trains,
stochastic_data=stochastic_data, # Malfunction data generator
obs_builder_object=observation_builder,
remove_agents_at_target=True # Removes agents at the end of their journey to make space for others
)
# Initiate the renderer
env_renderer = RenderTool(env, gl="PILSVG",
agent_render_variant=AgentRenderVariant.AGENT_SHOWS_OPTIONS_AND_BOX,
show_debug=False,
screen_height=1000, # Adjust these parameters to fit your resolution
screen_width=1000) # Adjust these parameters to fit your resolution
def my_controller():
"""
You are supposed to write this controller
"""
_action = {}
for _idx in range(NUMBER_OF_AGENTS):
_action[_idx] = np.random.randint(0, 5)
return _action
for step in range(100):
_action = my_controller()
obs, all_rewards, done, info = env.step(_action)
print("Rewards: {}, [done={}]".format( all_rewards, done))
env_renderer.render_env(show=True, frames=False, show_observations=False)
time.sleep(0.3)
``` ```
and **ideally** you should see something along the lines of 👥 Credits
---
![Flatland](https://i.imgur.com/Pc9aH4P.gif)
Best of Luck !! This library was developed by [SBB](https://www.sbb.ch/en/), [Deutsche Bahn](https://www.deutschebahn.com/), [SNCF](https://www.sncf.com/en), [AIcrowd](https://www.aicrowd.com/) and [numerous contributors](http://flatland.aicrowd.com/misc/credits.html) and AIcrowd research fellows from the AIcrowd community.
## Communication
* [Official Documentation](http://flatland-rl-docs.s3-website.eu-central-1.amazonaws.com/)
* [Discussion Forum](https://discourse.aicrowd.com/c/flatland-challenge)
* [Issue Tracker](https://gitlab.aicrowd.com/flatland/flatland/issues/)
➕ Contributions
---
Please follow the [Contribution Guidelines](https://flatland.aicrowd.com/misc/contributing.html) for more details on how you can successfully contribute to the project. We enthusiastically look forward to your contributions!
## Contributions 💬 Communication
Please follow the [Contribution Guidelines](http://flatland-rl-docs.s3-website.eu-central-1.amazonaws.com/contributing.html) for more details on how you can successfully contribute to the project. We enthusiastically look forward to your contributions. ---
## Partners
<a href="https://sbb.ch" target="_blank"><img src="https://i.imgur.com/OSCXtde.png" alt="SBB"/></a>
<a href="https://www.aicrowd.com" target="_blank"><img src="https://avatars1.githubusercontent.com/u/44522764?s=200&v=4" alt="AICROWD"/></a>
* [Discord Channel](https://discord.com/invite/hCR3CZG)
* [Discussion Forum](https://discourse.aicrowd.com/c/neurips-2020-flatland-challenge)
* [Issue Tracker](https://gitlab.aicrowd.com/flatland/flatland/issues/)
🔗 Partners
---
<a href="https://sbb.ch" target="_blank" style="margin-right:30px"><img src="https://annpr2020.ch/wp-content/uploads/2020/06/SBB.png" alt="SBB" width="140"/></a>
<a href="https://www.deutschebahn.com/" target="_blank" style="margin-right:30px"><img src="https://i.imgur.com/pjTki15.png" alt="DB" width="140"/></a>
<a href="https://www.sncf.com/en" target="_blank" style="margin-right:30px"><img src="https://iconape.com/wp-content/png_logo_vector/logo-sncf.png" alt="SNCF" width="140"/></a>
<a href="https://www.aicrowd.com" target="_blank"><img src="https://i.imgur.com/kBZQGI9.png" alt="AIcrowd" width="140"/></a>
...@@ -34,4 +34,6 @@ for entry in [entry for entry in importlib_resources.contents('examples') if ...@@ -34,4 +34,6 @@ for entry in [entry for entry in importlib_resources.contents('examples') if
# https://docs.python.org/3/library/test.html # https://docs.python.org/3/library/test.html
# TODO remove input() from examples? # TODO remove input() from examples?
with swap_attr(sys, "stdin", StringIO("q")): with swap_attr(sys, "stdin", StringIO("q")):
runpy.run_path(file_in, run_name="__main__") runpy.run_path(file_in, run_name="__main__", init_globals={
'argv': ['--sleep-for-animation=False', '--do_rendering=False']
})
...@@ -19,7 +19,9 @@ def profile(resource, entry): ...@@ -19,7 +19,9 @@ def profile(resource, entry):
with swap_attr(sys, "stdin", StringIO("q")): with swap_attr(sys, "stdin", StringIO("q")):
global my_func global my_func
def my_func(): runpy.run_path(file_in, run_name="__main__") def my_func(): runpy.run_path(file_in, run_name="__main__", init_globals={
'argv': ['--sleep-for-animation=False', '--do_rendering=False']
})
cProfile.run('my_func()', sort='time') cProfile.run('my_func()', sort='time')
......
...@@ -8,8 +8,8 @@ from importlib_resources import path ...@@ -8,8 +8,8 @@ from importlib_resources import path
from benchmarks.benchmark_utils import swap_attr from benchmarks.benchmark_utils import swap_attr
print("GRRRRRRRR run_all_examples.py") print("run_all_examples.py")
error_log_examples = {}
for entry in [entry for entry in importlib_resources.contents('examples') if for entry in [entry for entry in importlib_resources.contents('examples') if
not pkg_resources.resource_isdir('examples', entry) not pkg_resources.resource_isdir('examples', entry)
and entry.endswith(".py") and entry.endswith(".py")
...@@ -17,6 +17,7 @@ for entry in [entry for entry in importlib_resources.contents('examples') if ...@@ -17,6 +17,7 @@ for entry in [entry for entry in importlib_resources.contents('examples') if
and 'demo.py' not in entry and 'demo.py' not in entry
and 'DELETE' not in entry and 'DELETE' not in entry
]: ]:
with path('examples', entry) as file_in: with path('examples', entry) as file_in:
print("") print("")
print("") print("")
...@@ -25,12 +26,25 @@ for entry in [entry for entry in importlib_resources.contents('examples') if ...@@ -25,12 +26,25 @@ for entry in [entry for entry in importlib_resources.contents('examples') if
print("*****************************************************************") print("*****************************************************************")
print("Running {}".format(entry)) print("Running {}".format(entry))
print("*****************************************************************") print("*****************************************************************")
with swap_attr(sys, "stdin", StringIO("q")): with swap_attr(sys, "stdin", StringIO("q")):
try: try:
runpy.run_path(file_in, run_name="__main__", init_globals={ runpy.run_path(file_in, run_name="__main__", init_globals={
'argv': ['--sleep-for-animation=False'] 'argv': ['--sleep-for-animation=False', '--do_rendering=False']
}) })
except Exception as e: except Exception as e:
print(e) print(e)
error_log_examples.update({file_in: e})
print("runpy done.") print("runpy done.")
print("Done with {}".format(entry)) print("Done with {}".format(entry))
if len(error_log_examples.keys()) > 0:
print("*****************************************************************")
print("Error log:")
print("*****************************************************************")
print(error_log_examples)
print("*****************************************************************")
else:
print("*****************************************************************")
print("All examples executed - no error.")
print("*****************************************************************")
Changelog Changelog
========== ==========
Changes since Flatland 2.1.0
--------------------------
### Changes in 'schedule_generators'
- Schedule generators now provide the max number of steps allowed per episode
- Pickle files generated with older versions of Flatland need to be regenerated in order to include `_max_episode_steps`
Changes since Flatland 2.0.0 Changes since Flatland 2.0.0
-------------------------- --------------------------
### Changes in `EnvAgent` ### Changes in `EnvAgent`
...@@ -10,6 +15,7 @@ Changes since Flatland 2.0.0 ...@@ -10,6 +15,7 @@ Changes since Flatland 2.0.0
- agent attribute `next_malfunction`is not used anymore, it will be removed fully in future versions. - agent attribute `next_malfunction`is not used anymore, it will be removed fully in future versions.
- `break_agent()` function is introduced which induces malfunctions in agent according to poisson process - `break_agent()` function is introduced which induces malfunctions in agent according to poisson process
- `_fix_agent_after_malfunction()` fixes agents after attribute `malfunction == 0` - `_fix_agent_after_malfunction()` fixes agents after attribute `malfunction == 0`
- Introduced the concept of malfunction generators. Here you can add different malfunction models in future updates. Currently it only loads from files and parameters.
### Changes in `Environment` ### Changes in `Environment`
- moving of member variable `distance_map_computed` to new class `DistanceMap` - moving of member variable `distance_map_computed` to new class `DistanceMap`
......
File added
Authors Authors
======= =======
.. toctree::
:maxdepth: 2
.. include:: ../AUTHORS.rst .. include:: ../AUTHORS.rst
Multi-Agent Interface
=======
.. include:: interface/pettingzoo.rst
.. include:: interface/wrappers.rst
Multi-Agent Pettingzoo Usage
=======
We can use the PettingZoo interface by proving the rail env to the petting zoo wrapper as shown below in the example.
.. literalinclude:: ../tests/test_pettingzoo_interface.py
:language: python
:start-after: __sphinx_doc_begin__
:end-before: __sphinx_doc_end__
Multi-Agent Interface Stable Baseline 3 Training
=======
.. literalinclude:: ../flatland/contrib/training/flatland_pettingzoo_stable_baselines.py
:language: python
:start-after: __sphinx_doc_begin__
:end-before: __sphinx_doc_end__
Multi-Agent Interface Rllib Training
=======
.. literalinclude:: ../flatland/contrib/training/flatland_pettingzoo_rllib.py
:language: python
:start-after: __sphinx_doc_begin__
:end-before: __sphinx_doc_end__
\ No newline at end of file
Multi-Agent Interfaces
==============
.. toctree::
:maxdepth: 2
10_interface
...@@ -15,6 +15,7 @@ Welcome to flatland's documentation! ...@@ -15,6 +15,7 @@ Welcome to flatland's documentation!
07_changes 07_changes
08_authors 08_authors
09_faq_toc 09_faq_toc
10_interface
Indices and tables Indices and tables
================== ==================
......
# PettingZoo
> PettingZoo (https://www.pettingzoo.ml/) is a collection of multi-agent environments for reinforcement learning. We build a pettingzoo interface for flatland.
## Background
PettingZoo is a popular multi-agent environment library (https://arxiv.org/abs/2009.14471) that aims to be the gym standard for Multi-Agent Reinforcement Learning. We list the below advantages that make it suitable for use with flatland
- Works with both rllib (https://docs.ray.io/en/latest/rllib.html) and stable baselines 3 (https://stable-baselines3.readthedocs.io/) using wrappers from Super Suit.
- Clean API (https://www.pettingzoo.ml/api) with additional facilities/api for parallel, saving observation, recording using gym monitor, processing, normalising observations
- Scikit-learn inspired api
e.g.
```python
act = model.predict(obs, deterministic=True)[0]
```
- Parallel learning using literally 2 lines of code to use with stable baselines 3
```python
env = ss.pettingzoo_env_to_vec_env_v0(env)
env = ss.concat_vec_envs_v0(env, 8, num_cpus=4, base_class=stable_baselines3)
```
- Tested and supports various multi-agent environments with many agents comparable to flatland. e.g. https://www.pettingzoo.ml/magent
- Clean interface means we can custom add an experimenting tool like wandb and have full flexibility to save information we want
PettingZoo
==========
..
PettingZoo (https://www.pettingzoo.ml/) is a collection of multi-agent environments for reinforcement learning. We build a pettingzoo interface for flatland.
Background
----------
PettingZoo is a popular multi-agent environment library (https://arxiv.org/abs/2009.14471) that aims to be the gym standard for Multi-Agent Reinforcement Learning. We list the below advantages that make it suitable for use with flatland
* Works with both rllib (https://docs.ray.io/en/latest/rllib.html) and stable baselines 3 (https://stable-baselines3.readthedocs.io/) using wrappers from Super Suit.
* Clean API (https://www.pettingzoo.ml/api) with additional facilities/api for parallel, saving observation, recording using gym monitor, processing, normalising observations
* Scikit-learn inspired api
e.g.
.. code-block:: python
act = model.predict(obs, deterministic=True)[0]
* Parallel learning using literally 2 lines of code to use with stable baselines 3
.. code-block:: python
env = ss.pettingzoo_env_to_vec_env_v0(env)
env = ss.concat_vec_envs_v0(env, 8, num_cpus=4, base_class=’stable_baselines3’)
* Tested and supports various multi-agent environments with many agents comparable to flatland. e.g. https://www.pettingzoo.ml/magent
* Clean interface means we can custom add an experimenting tool like wandb and have full flexibility to save information we want
# Environment Wrappers
> We provide various environment wrappers to work with both the rail env and the petting zoo interface.
## Background
These wrappers changes certain environment behavior which can help to get better reinforcement learning training.
## Supported Inbuilt Wrappers
We provide 2 sample wrappers for ShortestPathAction wrapper and SkipNoChoice wrapper. The wrappers requires many env properties that are only created on environment reset. Hence before using the wrapper, we must reset the rail env. To use the wrappers, simply pass the resetted rail env. Code samples are shown below for each wrapper.
### ShortestPathAction Wrapper
To use the ShortestPathAction Wrapper, simply wrap the rail env as follows
```python
rail_env.reset(random_seed=1)
rail_env = ShortestPathActionWrapper(rail_env)
```
The shortest path action wrapper maps the existing action space into 3 actions - Shortest Path (`0`), Next Shortest Path (`1`) and Stop (`2`). Hence, we must ensure that the predicted action should always be one of these (0, 1 and 2) actions. To route all agents in the shortest path, pass `0` as the action.
### SkipNoChoice Wrapper
To use the SkipNoChoiceWrapper, simply wrap the rail env as follows
```python
rail_env.reset(random_seed=1)
rail_env = SkipNoChoiceCellsWrapper(rail_env, accumulate_skipped_rewards=False, discounting=0.0)
```