decent_bench.networks#

class decent_bench.networks.Network(graph: networkx.Graph[Agent], message_noise: NoiseScheme | dict[Agent, NoiseScheme] | None = None, message_compression: CompressionScheme | dict[Agent, CompressionScheme] | None = None, message_drop: DropScheme | dict[Agent, DropScheme] | None = None)[source]#

Bases: ABC

Base network object defining communication logic shared by all network types.

Parameters:
  • graph – NetworkX graph defining the network topology, with Agent nodes.

  • message_noise – noise scheme(s) to apply to messages sent by agents in the network. Can be a single NoiseScheme instance when all agents use the same kind of noise scheme, a dictionary mapping each agent to its scheme when agents use different schemes, or None to apply no noise to any agent.

  • message_compression – compression scheme(s) to apply to messages sent by agents in the network. Can be a single CompressionScheme instance when all agents use the same kind of compression scheme, a dictionary mapping each agent to its scheme when agents use different schemes, or None to apply no compression to any agent.

  • message_drop – drop scheme(s) to apply to messages sent by agents in the network. Can be a single DropScheme instance when all agents use the same kind of drop scheme, a dictionary mapping each agent to its scheme when agents use different schemes, or None to apply no message drop to any agent.

Raises:

ValueError – if the graph is not connected, if it is directed, if it is a multi-graph, if its nodes are not of type Agent, if any two agents have incompatible costs, or if any agent is already assigned to another network (i.e. it has index != -1).

property graph: networkx.Graph[Agent]#

Underlying NetworkX graph; mutating it will change the network.

property G: networkx.Graph[Agent]#

Alias for the underlying graph.

agents() list[Agent][source]#

Get all agents in the network.

Warning

This includes agents that may be inactive in the current iteration. It is generally recommended to use active_agents() instead, which returns only active agents, unless you have a specific reason to access inactive agents or need to access all agents regardless of activation status.

snapshot_agents() list[Agent][source]#

Get agents whose state should be snapshotted during algorithm execution.

property degrees: dict[Agent, int]#

Degree of each agent in the network.

property edges: list[tuple[Agent, Agent]]#

Edges of the network as (agent, agent) tuples.

active_agents() list[Agent][source]#

Get all active agents.

Whether an Agent is active or not at a given time is defined by its AgentActivationScheme.

connected_agents(agent: Agent) list[Agent][source]#

Agents directly connected to agent in the underlying graph.

Warning

This includes agents that may be inactive in the current iteration. It is generally recommended to use active_connected_agents() instead, which returns only active agents, unless you have a specific reason to access inactive agents or need to access all connected agents regardless of activation status.

active_connected_agents(agent: Agent) list[Agent][source]#

Agents directly connected to agent and are active at the given iteration.

send(sender: Agent, receiver: Agent | Sequence[Agent] | None = None, msg: Array | None = None, channel: str = 'default') None[source]#

Send message to one or more agents.

The message may be compressed, distorted by noise, and/or dropped depending on the network’s CompressionScheme, NoiseScheme, and DropScheme. The potentially compressed and noisy message (if not dropped) is then instantaneously available to each receiver.

Parameters:
  • sender – sender agent

  • receiver – receiver agent, sequence of receiver agents, or None to broadcast to connected agents.

  • msg – array message to send

  • channel – channel used to identify the message stream.

Raises:

ValueError – if msg is not provided, if agents are not part of the network, or if sender/receiver are not connected and active.

class decent_bench.networks.P2PNetwork(graph: networkx.Graph[Any], agents: Sequence[Agent], *, message_noise: NoiseScheme | dict[Agent, NoiseScheme] | None = None, message_compression: CompressionScheme | dict[Agent, CompressionScheme] | None = None, message_drop: DropScheme | dict[Agent, DropScheme] | None = None)[source]#

Bases: Network

Peer-to-peer network architecture where agents communicate directly with each other.

Parameters:
  • graph – NetworkX graph defining the network topology.

  • agents – list of agents corresponding to the nodes in graph. The agents in the list are assigned in order to each node of the graph. Agents must have unique ids.

  • message_noise – noise scheme(s) to apply to messages sent by agents in the network. Can be a single NoiseScheme instance to apply the same scheme to all agents, a dictionary mapping each agent to its scheme, or None to apply no noise to any agent.

  • message_compression – compression scheme(s) to apply to messages sent by agents in the network. Can be a single CompressionScheme instance to apply the same scheme to all agents, a dictionary mapping each agent to its scheme, or None to apply no compression to any agent.

  • message_drop – drop scheme(s) to apply to messages sent by agents in the network. Can be a single DropScheme instance to apply the same scheme to all agents, a dictionary mapping each agent to its scheme, or None to apply no message drop to any agent.

Raises:

ValueError – if length of agents doesn’t match the number of nodes in graph, or if any two agents have the same ids.

property weights: Array#

Symmetric, doubly stochastic matrix for consensus weights. Initialized using the Metropolis-Hastings method.

Use weights[i, j] or weights[i.index, j.index] to get the weight between agent i and j.

property adjacency: Array[source]#

Adjacency matrix of the network.

Use adjacency[i, j] or adjacency[i.index, j.index] to get the adjacency between agent i and j.

neighbors(agent: Agent) list[Agent][source]#

Alias for connected_agents().

active_neighbors(agent: Agent) list[Agent][source]#

Alias for active_connected_agents().

broadcast(sender: Agent, msg: Array, channel: str = 'default') None[source]#

Send to all neighbors (alias for send() with receiver=None).

class decent_bench.networks.FedNetwork(clients: Sequence[Agent], server: Agent | None = None, *, message_noise: NoiseScheme | dict[Agent, NoiseScheme] | None = None, message_compression: CompressionScheme | dict[Agent, CompressionScheme] | None = None, message_drop: DropScheme | dict[Agent, DropScheme] | None = None)[source]#

Bases: Network

Federated learning network with one server node connected to all client nodes (star topology).

Parameters:
  • clients – list of client agents in the network.

  • server – server agent in the network. If None, a default server with zero cost and always active scheme will be created. Custom servers must use AlwaysActive.

  • message_noise – noise scheme(s) to apply to messages sent by agents in the network. Can be a single NoiseScheme instance when all agents use the same kind of noise scheme, a dictionary mapping each agent to its scheme when agents use different schemes, or None to apply no noise to any agent.

  • message_compression – compression scheme(s) to apply to messages sent by agents in the network. Can be a single CompressionScheme instance when all agents use the same kind of compression scheme, a dictionary mapping each agent to its scheme when agents use different schemes, or None to apply no compression to any agent.

  • message_drop – drop scheme(s) to apply to messages sent by agents in the network. Can be a single DropScheme instance when all agents use the same kind of drop scheme, a dictionary mapping each agent to its scheme when agents use different schemes, or None to apply no message drop to any agent.

Raises:

ValueError – if clients is empty or if a custom server does not use AlwaysActive.

server() Agent[source]#

Agent acting as the central server.

coordinator() Agent[source]#

Alias for server.

agents() list[Agent][source]#

Get all client agents (excludes the server/coordinator).

Warning

This includes agents that may be inactive in the current iteration. It is generally recommended to use active_agents() instead, which returns only active agents, unless you have a specific reason to access inactive agents or need to access all agents regardless of activation status.

active_agents() list[Agent][source]#

Get all active client agents (excludes the server/coordinator).

Whether an Agent is active or not at a given time is defined by its AgentActivationScheme.

clients() list[Agent][source]#

Alias for agents().

active_clients() list[Agent][source]#

Alias for active_agents().

send(sender: Agent, receiver: Agent | Sequence[Agent] | None = None, msg: Array | None = None, channel: str = 'default') None[source]#

Send message(s) in a federated learning network.

Only server <-> client communication is allowed. Client-to-client and server-to-server communication will raise an error.

Raises:

ValueError – if server-to-server or client-to-client communication is attempted, or if a non-server tries to send to multiple receivers. Also see Network.send() for generic validation.

broadcast(msg: Array, channel: str = 'default') None[source]#

Send the same message from the server to every client (synchronous FL push).