Source code for eclypse.builders.infrastructure.generators.b_cube

"""BCube infrastructure generator.

This module provides a factory function to instantiate a BCube(k, n) network topology,
a server-centric architecture designed for modular data centers. The topology is
constructed recursively, enabling high fault-tolerance and multiple parallel paths
between servers.

The topology is defined by two parameters:
- `k`: the recursion level (BCube₀, BCube₁, ..., BCube_k)
- `n`: the number of ports per switch (and switches per level)

A BCube(k, n) contains:
- n^(k+1) servers
- k * n^k switches
- Each server is connected to (k + 1) switches, one per level.

The implementation follows the definition from:
Guo et al. "BCube: a high performance, server-centric network
architecture for modular data centers"
ACM SIGCOMM Computer Communication Review, 2009. https://dl.acm.org/doi/10.1145/1592568.1592577
"""

from __future__ import annotations

from typing import (
    TYPE_CHECKING,
)

from eclypse.graph import Infrastructure

if TYPE_CHECKING:
    from collections.abc import Callable

    import networkx as nx

    from eclypse.graph.assets import Asset
    from eclypse.utils.types import (
        InitPolicy,
        UpdatePolicies,
    )


[docs] def get_b_cube( k: int, n: int, infrastructure_id: str = "b_cube", update_policies: UpdatePolicies = None, node_assets: dict[str, Asset] | None = None, link_assets: dict[str, Asset] | None = None, include_default_assets: bool = False, strict: bool = False, resource_init: InitPolicy = "max", path_algorithm: Callable[[nx.Graph, str, str], list[str]] | None = None, seed: int | None = None, ) -> Infrastructure: """Factory for generating a BCube(k, n) topology. A BCube is a server-centric topology designed for modular data centers. It provides multiple parallel paths between servers and is highly fault-tolerant. Args: k (int): Recursion level of the BCube. Determines depth (e.g., 0 = star). n (int): Number of ports per switch, and number of switches per level. infrastructure_id (str): Unique ID for the infrastructure instance.\ Defaults to "b_cube". update_policies (Callable | list[Callable] | None): Graph update policies.\ Defaults to None. node_assets (dict[str, Asset] | None): Default attributes for all nodes.\ Defaults to None. link_assets (dict[str, Asset] | None): Default attributes for all links.\ Defaults to None. include_default_assets (bool): Whether to include default assets. \ Defaults to False. strict (bool): If True, raises an error if the asset values are not \ consistent with their spaces. Defaults to False. resource_init (InitPolicy): Initialization policy for resources. \ Defaults to "max". path_algorithm (Callable[[nx.Graph, str, str], list[str]] | None): \ Algorithm to compute paths. Defaults to None. Defaults to None. seed (int | None): Seed for random number generation. Defaults to None. Returns: Infrastructure: The BCube topology as an Infrastructure object. """ infra = Infrastructure( infrastructure_id=infrastructure_id, update_policies=update_policies, node_assets=node_assets, edge_assets=link_assets, include_default_assets=include_default_assets, resource_init=resource_init, path_algorithm=path_algorithm, seed=seed, ) # Total number of servers num_servers = n ** (k + 1) servers = [f"server_{i}" for i in range(num_servers)] for s in servers: infra.add_node(s, strict=strict) # Add switches and connect them to servers for level in range(k + 1): num_switches = n**level for sw_idx in range(num_switches): sw_id = f"sw_{level}_{sw_idx}" infra.add_node(sw_id, strict=strict) for port in range(n): server_idx = ( sw_idx * n + port if level == 0 else port * n**level + sw_idx ) server_id = f"server_{server_idx}" infra.add_edge(sw_id, server_id, symmetric=True) return infra