-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
1,826 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
## Description | ||
**Westworld** is a multi-agent simulation library, its goal to simulate and optimize systems and environments with multiple agents interacting. Its inspiration is drawn from Unity software and [Unity ML Agents](https://github.com/Unity-Technologies/ml-agents), adapted in Python. | ||
|
||
The goal is to be able to simulate environments in logistics, retails, epidemiology, providing pre-coded spatial environments and communication between agents. Optimization can be included using heuristics as well as Reinforcement Learning. | ||
The goal is to be able to simulate environments in logistics, retail, epidemiology, providing pre-coded spatial environments and communication between agents. Optimization can be included using heuristics as well as Reinforcement Learning. | ||
|
||
!!! warning "Experimental" | ||
This library is extremely experimental, under active development and alpha-release | ||
|
@@ -59,3 +59,6 @@ poetry run python | |
## Contributors | ||
- [Théo Alves Da Costa](mailto:[email protected]) | ||
|
||
## Javascript version | ||
A javascript version is being developed at https://github.com/TheoLvs/westworldjs | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ | |
## Description | ||
**Westworld** is a multi-agent simulation library, its goal to simulate and optimize systems and environments with multiple agents interacting. Its inspiration is drawn from Unity software and [Unity ML Agents](https://github.com/Unity-Technologies/ml-agents), adapted in Python. | ||
|
||
The goal is to be able to simulate environments in logistics, retails, epidemiology, providing pre-coded spatial environments and communication between agents. Optimization can be included using heuristics as well as Reinforcement Learning. | ||
The goal is to be able to simulate environments in logistics, retail, epidemiology, providing pre-coded spatial environments and communication between agents. Optimization can be included using heuristics as well as Reinforcement Learning. | ||
|
||
!!! warning "Experimental" | ||
This library is extremely experimental, under active development and alpha-release | ||
|
@@ -15,6 +15,58 @@ The goal is to be able to simulate environments in logistics, retails, epidemiol | |
*The name is of course inspired by the TV series Westworld, which is actually a gigantic multi-agent simulation system.* | ||
|
||
|
||
## Quickstart | ||
Let's model an ecosystem of rabbits looking and competing for food | ||
|
||
![](./tutorials/img/Quickstart_1631837803.gif) | ||
|
||
```python | ||
from westworld.environment import GridEnvironment | ||
from westworld.agents import BaseAgent | ||
from westworld.objects import BaseCollectible | ||
from westworld.simulation import Simulation | ||
from westworld.colors import * | ||
|
||
class Food(BaseCollectible): | ||
pass | ||
|
||
class Rabbit(BaseAgent): | ||
|
||
def __init__(self,x,y,curiosity = 5): | ||
super().__init__(x,y,color = (229, 229, 229),curiosity = curiosity) | ||
|
||
def step(self): | ||
|
||
# Find closest food | ||
targets = self.find_closest(name = "Food",k = 1) | ||
|
||
# If there is still food, move towards the food | ||
if len(targets) > 0: | ||
|
||
target = targets[0] | ||
|
||
# Use naive pathfinding for faster computation as there is no obstacle | ||
self.move_towards(obj = target,naive = True) | ||
|
||
# Otherwise just wandering | ||
# Changing direction every n steps where n = curiosity | ||
else: | ||
self.wander() | ||
|
||
food_spawner = lambda x,y : Food(x,y,color = (220,150,50),img_asset = "ball") | ||
rabbit_spawner = lambda x,y : Rabbit(x,y,curiosity = 5) | ||
|
||
# Setup environment | ||
env = GridEnvironment(20,10,20,show_grid = True,background_color=(102, 178, 102),grid_color=(127, 191, 127),toroidal=True) | ||
env.spawn(rabbit_spawner,3) | ||
env.spawn(food_spawner,20) | ||
env.render() | ||
|
||
# Make simulation | ||
sim = Simulation(env,fps = 10,name="Quickstart") | ||
_,_ = sim.run_episode(n_steps = 50,save = True,replay = True,save_format="gif",) | ||
``` | ||
|
||
## Features | ||
### Current features | ||
- Easy creation of Grid and non-grid environments | ||
|
@@ -59,6 +111,6 @@ poetry run python | |
- [Théo Alves Da Costa](mailto:[email protected]) | ||
|
||
|
||
|
||
|
||
## Javascript version | ||
A javascript version is being developed at https://github.com/TheoLvs/westworldjs | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Movements | ||
|
||
For each step in the simulation, the environment will calculate what happens to every non-stationary objects binded to it. | ||
In particular, the agents who will probably move between t and t+1. | ||
|
||
If you can subclass the ``step()`` function for any custom movements. There are already many pre-coded functions to make your agent move. | ||
|
||
We will need the basic westworld imports for this tutorial | ||
```python | ||
from westworld.environment import GridEnvironment | ||
from westworld.agents import BaseAgent | ||
from westworld.simulation import Simulation | ||
from westworld.colors import BLUE,GREEN,RED | ||
``` | ||
|
||
## Random Walk | ||
The most simple move there is: taking a random step. | ||
|
||
As you can see, you simply subclass the ``BaseAgent``, setup a random walk in one line of code and add it to the environment | ||
|
||
```python | ||
class Agent(BaseAgent): | ||
def step(self): | ||
self.random_walk() | ||
|
||
# Define all agents | ||
agent1 = Agent(2,3,curiosity=5,color = GREEN) | ||
agent2 = Agent(17,7,curiosity=2,color = BLUE) | ||
agent3 = Agent(8,1,curiosity=20,color = RED) | ||
|
||
# Define environment | ||
env = GridEnvironment(width = 20,height = 10,cell_size = 20,show_grid = True) | ||
|
||
# Add agents to the environment | ||
env.add_object([agent1,agent2,agent3]) | ||
env.render() | ||
|
||
# Make simulation | ||
sim = Simulation(env,fps = 10,name="RandomWalk") | ||
_,_ = sim.run_episode(n_steps = 20,save = True,replay = True,save_format="gif") | ||
``` | ||
![](./img/RandomWalk_1631837258.gif) | ||
|
||
## Wandering | ||
If you need an agent to explore the environment, you can use the ``.wander()`` function. | ||
Basically the agent will walk straight in a direction, and change direction at some point using a ``curiosity`` factor - ie for ``curiosity = 5`` it will change direction every 5 steps (in the example below, compare the behavior of the 3 agents with a different curiosity). | ||
|
||
In a ``GridEnvironment``, the direction angle is approximated by sampling horizontal and vertical movements on the grid to match the angle as best as possible. | ||
|
||
```python | ||
class Agent(BaseAgent): | ||
def step(self): | ||
self.wander() | ||
``` | ||
![](./img/RandomWalk_1631836560.gif) | ||
|
||
|
||
## Pathfinding | ||
Another useful behavior is moving towards a point. This is done using pathfinding algorithms. | ||
|
||
If there are some obstacles, you may require advanced pathfinding (tutorial to come) which is more expensive to compute. Without obstacles you can use naive pathfinding. | ||
|
||
Just use the ``.move_towards()`` function and your agents will move towards a given target | ||
|
||
```python | ||
class Agent(BaseAgent): | ||
def step(self): | ||
self.move_towards(0,0,naive = True) | ||
``` | ||
![](./img/RandomWalk_1631837025.gif) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Objects | ||
Understanding the different objects in ``Westworld`` | ||
|
||
> WIP | ||
## Agents | ||
|
||
## Obstacles | ||
|
||
## Triggers | ||
|
||
## Collectibles | ||
|
||
## Creating multiple objects with the spawner | ||
|
||
## Layers |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# Quickstart | ||
|
||
Getting started with ``westworld`` in a few lines of code - Westworld is multi-agent simulation library in Python. You can use it to simulate spatial environments with agents moving, interacting with each other, finding their path and avoiding obstacles, ... | ||
|
||
In this quickstart, we will create a super simple ecosystem of rabbits competing and looking for food and eating them when they find it. | ||
|
||
![](./img/Quickstart_1631837803.gif) | ||
|
||
|
||
## Preparing the basic imports | ||
We will import necessary objects classes, the environment and simulation wrappers. | ||
```python | ||
from westworld.environment import GridEnvironment | ||
from westworld.agents import BaseAgent | ||
from westworld.objects import BaseCollectible | ||
from westworld.simulation import Simulation | ||
``` | ||
## Defining the food to collect | ||
Objects that are collected by agents and then disappear are called ``Collectibles``. They can trigger something once an agent collects them and then are destroyed. We will then subclass this Collectible class to create our Food object. | ||
```python | ||
class Food(BaseCollectible): | ||
pass | ||
``` | ||
Yes this class does nothing. For now. Actually we will just use the name of the class ``Food`` in the Rabbit behavior function to look for those collectibles. Of course we could add more features to this collectible, for example increase the life of the rabbit once eaten. | ||
|
||
|
||
## Defining the rabbits | ||
We will then define a rabbit whose behavior will be described in a ``.step()`` function - ie everything that happens between t and t+1 | ||
|
||
- Looking for the closest food piece using helper function ``.find_closest()`` (we will use the class name here to find for the ``Food`` objects) | ||
- If it finds any, the rabbit will move towards the object to collect it using ``.move_towards()`` helper function until collecting it and going to the next closest | ||
- If there aren't anymore food, the rabbit will just ``.wander()`` around the environment | ||
|
||
|
||
```python | ||
class Rabbit(BaseAgent): | ||
|
||
def __init__(self,x,y): | ||
super().__init__(x,y,color = (229, 229, 229),curiosity = 5) | ||
|
||
def step(self): | ||
|
||
# Find closest food | ||
targets = self.find_closest(name = "Food",k = 1) | ||
|
||
# If there is still food, move towards the food | ||
if len(targets) > 0: | ||
|
||
target = targets[0] | ||
|
||
# Use naive pathfinding for faster computation as there is no obstacle | ||
self.move_towards(obj = target,naive = True) | ||
|
||
# Otherwise just wandering | ||
# Changing direction every n steps where n = curiosity | ||
else: | ||
self.wander() | ||
``` | ||
|
||
## Preparing spawners | ||
Spawners will help us add multiple rabbits and food pieces at the same time, it's a generator of custom objects in your environment. | ||
We will simply use a lambda function: | ||
|
||
``` | ||
rabbit_spawner = lambda x,y : Rabbit(x,y) | ||
food_spawner = lambda x,y : Food(x,y,color = (220,150,50),img_asset = "ball") | ||
``` | ||
|
||
For the Food object we use default arguments of ``BaseCollectible`` objects to change the food color and shape (make it look like a ball). | ||
|
||
## Defining the environment | ||
Now we need to put those food and rabbits somewhere, let's create a grid environment. There are many arguments to define width, height, cell size, colors, etc... | ||
```python | ||
env = GridEnvironment(20,10,20,show_grid = True,background_color=(102, 178, 102),grid_color=(127, 191, 127),toroidal=True) | ||
``` | ||
|
||
We now add a few rabbits and food pieces using the spawner. | ||
```python | ||
env.spawn(rabbit_spawner,3) | ||
env.spawn(food_spawner,20) | ||
``` | ||
|
||
And we initalize the environment and visualize it using ``.render()`` function | ||
```python | ||
env.render() | ||
``` | ||
|
||
## Launching the simulation | ||
Next step is to simulate what happens in the environment with the step rules that we defined. We now wrap the environment in a ``Simulation`` object and run an episode of 50 steps. We save the simulation to a gif to be visualized. | ||
|
||
```python | ||
sim = Simulation(env,fps = 10,name="Quickstart") | ||
_,_ = sim.run_episode(n_steps = 50,save = True,replay = True,save_format="gif",) | ||
``` | ||
|
||
We get the following simulation: | ||
|
||
![](./img/Quickstart_1631837803.gif) | ||
|
||
## Going further | ||
There are so many behaviors you can customize using precoded functions in westworld or write your own, you can add obstacles, put the agents in a maze, define other agents, complexify agent behavior, log information over time. You are not even obliged to use a grid environment and can work in a continuous environment. | ||
|
||
For this ecosystem simulation, there are also many improvements you can do: add rabbit reproduction, short sightedness, introduce predators or different type of food. We will see a more complex example in another tutorial. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.