Skip to main content

Loose building blocks to create agent-environment loops.

Project description

License Last Commit Coverage Tests PyPI PyPI PyPI

🌐 Environment Framework

This repository contains the Python package environment-framework. The project aims to provide loose building blocks to manage the logic, observation, estimation and visualization of an agent-environment loop. It can be used to implement problems which might be solved with reinforcement learning or dynamic programming algorithms.

A wrapper around gymnasium is provided to connect to well-known frameworks in the field.

The wrapper for gymnasium uses the gymnasium>=0.26 API structure!

🤔 Why create this project?

The project emerges from a previous project of mine. It was used to separate the different elements of the projects agent-environment-loop.

🚀 Get Started

Installation

pip3 install environment-framework

👩‍🏫 GridWorld Example

The implemented example of GridWorld can also be found in a Jupyter notebook grid_world.ipynb.

pip3 install "environment-framework[extra]"
jupyter lab
class Action:
    UP = 0
    DOWN = 1
    RIGHT = 2
    LEFT = 3

class GridWorldGame:
    def __init__(self, size: int) -> None:
        self.size = size
        self.player_position = (0, 0)
        self.target_position = (0, 0)
        self.reset()

    @property
    def done(self) -> bool:
        return self.player_position == self.target_position

    @property
    def space(self) -> Space:
        return Discrete(4)

    def act(self, action: int, **_: Any) -> None:
        if action == Action.UP:
            self.player_position = (self.player_position[0], self.player_position[1] - 1)
        if action == Action.DOWN:
            self.player_position = (self.player_position[0], self.player_position[1] + 1)
        if action == Action.RIGHT:
            self.player_position = (self.player_position[0] + 1, self.player_position[1])
        if action == Action.LEFT:
            self.player_position = (self.player_position[0] - 1, self.player_position[1])
        corrected_x = max(0, min(self.size - 1, self.player_position[0]))
        corrected_y = max(0, min(self.size - 1, self.player_position[1]))
        self.player_position = (corrected_x, corrected_y)

    def reset(self) -> None:
        def get_random_position() -> int:
            return randint(0, self.size - 1)
        self.player_position = (get_random_position(), get_random_position())
        self.target_position = (get_random_position(), get_random_position())
        if self.done:
            self.reset()

class GridWorldObserver:
    def __init__(self, game: GridWorldGame) -> None:
        self.game = game

    @property
    def space(self) -> Space:
        return Box(shape=(4,), low=-math.inf, high=math.inf)

    def observe(self) -> NDArray:
        return np.array(
            [*self.game.player_position, *self.game.target_position],
            dtype=np.float32,
        )

class GridWorldEstimator:
    def __init__(self, game: GridWorldGame) -> None:
        self.game = game

    def estimate(self) -> float:
        return -1 + float(self.game.done)

class GridWorldVisualizer(PygameHumanVisualizer):
    BLUE = [0, 0, 255]
    GREEN = [0, 255, 0]

    def __init__(self, game: GridWorldGame) -> None:
        super().__init__(50)
        self.game = game

    def render_rgb(self) -> NDArray[np.uint8]:
        frame = [[[0 for k in range(3)] for j in range(self.game.size)] for i in range(self.game.size)]
        frame[self.game.player_position[1]][self.game.player_position[0]] = self.BLUE
        frame[self.game.target_position[1]][self.game.target_position[0]] = self.GREEN
        return np.array(frame, dtype=np.uint8)

class GridWorldLevel(Level):
    _game: GridWorldGame
    _observer: GridWorldObserver
    _estimator: GridWorldEstimator
    _visualizer: GridWorldVisualizer

    def reset(self) -> None:
        self._game.reset()

    def step(self, action: int) -> Any:
        self._game.act(action)

game = GridWorldGame(7)
level = GridWorldLevel(
    game,
    GridWorldObserver(game),
    GridWorldEstimator(game),
    GridWorldVisualizer(game),
)
simulator = Simulator(level, 50)
FPS = 4
DONE = False
while not DONE:
    action = simulator.action_space.sample()
    simulator.step(action)
    obs = simulator.observe()
    reward = simulator.estimate()
    simulator.render_human(FPS)
    DONE = simulator.truncated or simulator.done
simulator.close()

📃 Documentation

Some doc-strings are already added. Documentation is a work-in-progress and will be updated on a time by time basis.

💃🕺 Contribution

I welcome everybody contributing to this project. Please read the CONTRIBUTING.md for more information. Feel free to open an issue on the project if you have any further questions.

💻 Development

The repository provides tools for development using hatch.

All dependencies for the project also can be found in a requirements-file.

Install the development dependencies.

pip3 install -r requirements/dev.txt

or

pip3 install "environment-framework[dev]"

Tools

To run all development tools, type checking, linting and tests hatch is required.

make all

Type checking

Type checking with mypy.

make mypy

Linting

Linting with pylint.

make lint

Tests

Run tests with pytest.

make test

Update dependencies

Update python requirements with pip-compile.

make update

🧾 License

This repository is licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

environment_framework-0.6.0.tar.gz (8.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

environment_framework-0.6.0-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file environment_framework-0.6.0.tar.gz.

File metadata

  • Download URL: environment_framework-0.6.0.tar.gz
  • Upload date:
  • Size: 8.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: Hatch/1.16.5 cpython/3.10.20 HTTPX/0.28.1

File hashes

Hashes for environment_framework-0.6.0.tar.gz
Algorithm Hash digest
SHA256 4aaf64a7eb1c6552fd270b44f4f552a7bde4ce8b1508cd9f301e72104c9a598d
MD5 af150bc5a332d7291c35187c9a4738f5
BLAKE2b-256 8b4da883583a33f6e6226b5063395d1c5efe7aaca939f8aa49639fbe29a4a551

See more details on using hashes here.

File details

Details for the file environment_framework-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for environment_framework-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 76c4c420652f78577acf4d192d54be55a4358dc17a04c3b94eb103c4ce7c6693
MD5 3a749305ecfffafbe06ab8511c17ee90
BLAKE2b-256 efcd6ba13400f44bfd80381f2106f6ef285211fa65b4361355f850a6d029394e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page