A modular communication failure API for Multi-Agent Reinforcement Learning environments
Project description
failure-api
A modular failure injection API for Multi-Agent Reinforcement Learning (MARL) environments.
Built on top of PettingZoo, this package introduces wrappers that simulate communication failures and observation noise between agents — enabling robust training under partial observability and degraded communication.
Installation
pip install failure-api
Components
Wrappers
| Wrapper | Purpose |
|---|---|
BaseWrapper |
Provides utility functions such as RNG seeding. |
SharedObsWrapper |
Enables shared observations across agents; used internally. |
CommunicationWrapper |
Dynamically masks agent observations/actions based on failures. |
NoiseWrapper |
Injects noise into shared observations, excluding already masked values. |
Communication Models
| Model | Description |
|---|---|
ProbabilisticModel |
Drops communication links using Bernoulli sampling with fixed probability. |
BaseMarkovModel |
Models temporally correlated failures with a Markov chain. |
DistanceModel |
Drops communication based on exceeding a distance threshold. |
DelayBasedModel |
Delays messages with probabilistic delivery and expiration. |
SignalBasedModel |
Applies degradation using inverse-square signal loss and random drops. |
Noise Models
| Model | Description |
|---|---|
GaussianNoiseModel |
Adds Gaussian noise: X + N(μ, σ²); useful for random sensor noise. |
LaplacianNoiseModel |
Adds Laplacian noise: X + Laplace(μ, b); good for sparse spikes. |
CustomNoise |
Accepts any callable function for custom distortion logic. |
All models inherit from the NoiseModel base class and implement .apply().
Example Usage
from mpe2 import simple_spread_v3
from failure_api.wrappers import CommunicationWrapper, NoiseWrapper
from failure_api.communication_models import ProbabilisticModel, BaseMarkovModel
from failure_api.noise_models import GaussianNoiseModel
from pettingzoo.utils import aec_to_parallel
# Base PettingZoo environment
env = simple_spread_v3.env(N=3, max_cycles=25)
agent_ids = env.possible_agents
# Apply communication failure model
model = ProbabilisticModel(agent_ids=agent_ids, failure_prob=0.8)
wrapped_env = CommunicationWrapper(env, failure_models=[model])
# Convert to parallel API
parallel_env = aec_to_parallel(wrapped_env)
# Run Simulation
observations, _ = parallel_env.reset(seed=42)
initial_comm_matrix = wrapped_env.get_communication_state().astype(int)
print(f"\nInitial Communication Matrix (0=masked, 1=visible)\n")
print(initial_comm_matrix)
for _ in range(10):
actions = {agent: parallel_env.action_space(agent).sample() for agent in parallel_env.agents}
observations, rewards, terminations, truncations, infos = parallel_env.step(actions)
print(f"Masked State: (0=masked, 1=visible)\n", wrapped_env.get_communication_state())
if all(terminations.values()) or all(truncations.values()):
break
#%%
# OPTIONAL: Noise model, can be used with/without Communication wrapper
# to compare observations before noise is injected, the communication wrapper
# needs to be called to get the raw observation.
# Base PettingZoo environment
noise_env = simple_spread_v3.env(N=3, max_cycles=25)
agent_ids = env.possible_agents
comm_wrapper = CommunicationWrapper(noise_env, failure_models=[ProbabilisticModel(
agent_ids, failure_prob=0.8
)]) # step will not be taken so as not to mask observations
# convert to parallel env
parallel_comm_wrapper = aec_to_parallel(comm_wrapper)
comm_obs, _ = parallel_comm_wrapper.reset(seed=42)
comm_obs_agent_0 = comm_obs[agent_ids[0]]
# Inject Noise
noise_wrapper = NoiseWrapper(comm_wrapper, noise_model=
GaussianNoiseModel(mean=0.1, std=0.2 ))
# Convert to parallel API
noise_parallel_env = aec_to_parallel(noise_wrapper)
# Run Simulation
noisy_obs, _ = noise_parallel_env.reset(seed=42)
noisy_obs_agent_0 = noisy_obs[agent_ids[0]]
print("\nComparison for agent_0")
for other_agent in comm_obs_agent_0:
print(f"\nObservation from {other_agent}:")
print(f" Clean:")
print(f"{comm_obs_agent0[other_agent]:.3f}")
print(f"\n Noisy :")
print(f"{noisy_obs_agent0[other_agent]:.3f}")
Custom Noise Example
from failure_api.noise_models import CustomNoise
def zero_every_other(obs, space=None):
obs[::2] = 0
return obs
noise = CustomNoise(noise_fn=zero_every_other)
env = NoiseWrapper(env, noise_model=noise)
Features
- ✅ Pluggable communication failure and noise models
- 🔁 Compatible with both AEC and Parallel API in PettingZoo
- 🔒 Observation masking via active communication matrix
- 🎯 Observation noise excludes zero-masked (unseen) values
- 🤖 Supports MARL training frameworks (e.g. IQL, QMIX)
- 🧩 Fully extensible for custom failure scenarios
API Highlights
CommunicationWrapper
- Applies observation/action masking using
ActiveCommunication - Works with any PettingZoo AEC environment
- Internally uses
SharedObsWrapper - Supports multi-model failure injection
NoiseWrapper
- Adds noise only to visible observations
- Maintains shape and structure of observation space
- Customizable with user-defined noise logic
Requirements
- Python 3.8+
pettingzoogymnasiumnumpyscipy- (Optional):
matplotlib,tqdm,networkx
Testing
Use this to inspect the communication mask during runtime:
print(env.get_communication_state()) # Visualize active communication links
Extendability
You can define your own failure or noise model by subclassing:
from failure_api.communication_models import CommunicationModels
class MyFailureModel(CommunicationModels):
def update_connectivity(self, comm_matrix):
# Custom logic here
return comm_matrix
Citation
If you use this in academic work, please cite:
@bachelorsthesis{adegun2025marlapi,
author = {Oluwadamilare Israel Adegun},
title = {Development of a Multi-Agent Reinforcement Learning API for Dynamic Observation and Action Spaces},
school = {University of Duisburg-Essen},
year = {2025},
note = {[Online; accessed 21-May-2025]}
}
🔗 Links
- 🔗 GitHub: https://github.com/dreyman91/FailureAPI
- 📦 PyPI: pypi.org/project/failure-api
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file failure_api-0.1.7.tar.gz.
File metadata
- Download URL: failure_api-0.1.7.tar.gz
- Upload date:
- Size: 24.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2b8a57e07f9d1bab66afc06dff24c39d59d71dede727bf39da9785ff1c601c8
|
|
| MD5 |
ed3557684c98fe3e607c9a343ebc3f55
|
|
| BLAKE2b-256 |
524e8e1d4eb27860373c831edfe5f8e8866c0e1a134c8c82245f906e71a5dc3b
|
File details
Details for the file failure_api-0.1.7-py3-none-any.whl.
File metadata
- Download URL: failure_api-0.1.7-py3-none-any.whl
- Upload date:
- Size: 32.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b40ba55cdb6368fc9339faad959525afd288c8a998a9ff0a1d193003232891c
|
|
| MD5 |
7a8b2ff270c1c09d16523193e5d80d43
|
|
| BLAKE2b-256 |
49be75b9b7ba22c3fe6db097959ec6b2edf043c027769216d345d81514f38551
|