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.7.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.7-py3-none-any.whl (32.3 kB view details)

Uploaded Python 3

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

Hashes for failure_api-0.1.7.tar.gz
Algorithm Hash digest
SHA256 f2b8a57e07f9d1bab66afc06dff24c39d59d71dede727bf39da9785ff1c601c8
MD5 ed3557684c98fe3e607c9a343ebc3f55
BLAKE2b-256 524e8e1d4eb27860373c831edfe5f8e8866c0e1a134c8c82245f906e71a5dc3b

See more details on using hashes here.

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

Hashes for failure_api-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 8b40ba55cdb6368fc9339faad959525afd288c8a998a9ff0a1d193003232891c
MD5 7a8b2ff270c1c09d16523193e5d80d43
BLAKE2b-256 49be75b9b7ba22c3fe6db097959ec6b2edf043c027769216d345d81514f38551

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