Source code for decent_bench.benchmark_problem

from collections.abc import Sequence
from dataclasses import dataclass
from functools import reduce
from operator import add
from typing import TYPE_CHECKING, Any

import networkx as nx
from networkx import Graph
from numpy import float64
from numpy.typing import NDArray

import decent_bench.centralized_algorithms as ca
from decent_bench.cost_functions import CostFunction, LinearRegressionCost, LogisticRegressionCost
from decent_bench.datasets import SyntheticClassificationData
from decent_bench.schemes import (
    AgentActivationScheme,
    AlwaysActive,
    CompressionScheme,
    DropScheme,
    GaussianNoise,
    NoCompression,
    NoDrops,
    NoiseScheme,
    NoNoise,
    Quantization,
    UniformActivationRate,
    UniformDropRate,
)

if TYPE_CHECKING:
    AnyGraph = Graph[Any]
else:
    AnyGraph = Graph


[docs] @dataclass(eq=False) class BenchmarkProblem: """ Benchmark problem to run algorithms on, defining settings such as communication constraints and topology. Args: topology_structure: graph defining how agents are connected cost_functions: local cost functions, each one is given to one agent optimal_x: solution that minimizes the sum of the cost functions, used for calculating metrics agent_activation_schemes: setting for agent activation/participation, each scheme is applied to one agent compression_scheme: message compression setting noise_scheme: message noise setting drop_scheme: message drops setting """ topology_structure: AnyGraph optimal_x: NDArray[float64] cost_functions: Sequence[CostFunction] agent_activation_schemes: Sequence[AgentActivationScheme] compression_scheme: CompressionScheme noise_scheme: NoiseScheme drop_scheme: DropScheme
[docs] def create_regression_problem( cost_function_cls: type[LinearRegressionCost | LogisticRegressionCost], *, n_agents: int = 100, n_neighbors_per_agent: int = 3, asynchrony: bool = False, compression: bool = False, noise: bool = False, drops: bool = False, ) -> BenchmarkProblem: """ Create out-of-the-box regression problems. Args: cost_function_cls: type of cost function n_agents: number of agents n_neighbors_per_agent: number of neighbors per agent asynchrony: if true, agents only have a 50% probability of being active/participating at any given time compression: if true, messages are rounded to 4 significant digits noise: if true, messages are distorted by Gaussian noise drops: if true, messages have a 50% probability of being dropped """ topology_structure = nx.random_regular_graph(n_neighbors_per_agent, n_agents, seed=0) dataset = SyntheticClassificationData( n_classes=2, n_partitions=n_agents, n_samples_per_partition=10, n_features=3, seed=0 ) costs = [cost_function_cls(*p) for p in dataset.get_training_partitions()] sum_cost = reduce(add, costs) optimal_x = ca.accelerated_gradient_descent(sum_cost, x0=None, max_iter=50000, stop_tol=1e-100, max_tol=1e-16) agent_activation_schemes = [UniformActivationRate(0.5) if asynchrony else AlwaysActive()] * n_agents compression_scheme = Quantization(n_significant_digits=4) if compression else NoCompression() noise_scheme = GaussianNoise(mean=0, sd=0.001) if noise else NoNoise() drop_scheme = UniformDropRate(drop_rate=0.5) if drops else NoDrops() return BenchmarkProblem( topology_structure=topology_structure, cost_functions=costs, optimal_x=optimal_x, agent_activation_schemes=agent_activation_schemes, compression_scheme=compression_scheme, noise_scheme=noise_scheme, drop_scheme=drop_scheme, )