Skip to main content

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+
  • pettingzoo
  • gymnasium
  • numpy
  • scipy
  • (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


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

failure_api-0.1.6.tar.gz (24.9 kB view details)

Uploaded Source

Built Distribution

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

failure_api-0.1.6-py3-none-any.whl (32.3 kB view details)

Uploaded Python 3

File details

Details for the file failure_api-0.1.6.tar.gz.

File metadata

  • Download URL: failure_api-0.1.6.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

Hashes for failure_api-0.1.6.tar.gz
Algorithm Hash digest
SHA256 3e878f8a6034daedba4c5ae71c0047669fc8686151b5aaf686d2257292496e60
MD5 f56a2768a59eec1ede52b603aa9e1f02
BLAKE2b-256 70d4932b5b43932db51f3a72d48f9249c816c1679d3f63c517bd1a4ecadf9c7b

See more details on using hashes here.

File details

Details for the file failure_api-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: failure_api-0.1.6-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

Hashes for failure_api-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 8468a8e844aa46f17a16d5a000798c54ac30368c577f5190af324bf14d899a72
MD5 9411c49ef64808979b746c1c08a367af
BLAKE2b-256 79989f36bffdb39605bb72acdfd0994362c8253dff968c40d0c103f0b52d9688

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