Source code for hiper.simulation.attack

# -*- coding: utf-8 -*-
"""
attack.py

Defines the base Attack class and specific attack implementations.
"""

from abc import ABC, abstractmethod
from typing import Any, Dict

from hiper.core.hypernetwork import Hypernetwork


[docs] class Attack(ABC): """ Abstract base class for hypernetwork attacks. An attack represents a single operation that can be applied to a hypernetwork, such as adding or removing nodes or hyperedges. """
[docs] def __init__(self, attack_id: str) -> None: """ Initialize the attack with a unique identifier. Args: attack_id: Unique identifier for this attack. """ self.attack_id = attack_id self._executed = False self._result: Dict[str, Any] = {}
[docs] @abstractmethod def execute(self, hypernetwork: Hypernetwork) -> bool: """ Execute the attack on the given hypernetwork. Args: hypernetwork: The target hypernetwork. Returns: True if the attack was successful, False otherwise. """ pass
[docs] @abstractmethod def describe(self) -> str: """ Return a human-readable description of the attack. Returns: String description of the attack. """ pass
[docs] def is_executed(self) -> bool: """Check if the attack has been executed.""" return self._executed
[docs] def get_result(self) -> Dict[str, Any]: """Get the result of the attack execution.""" return self._result.copy()
[docs] def reset(self) -> None: """Reset the attack state to allow re-execution.""" self._executed = False self._result.clear()
[docs] class AddNodeAttack(Attack): """ Attack that adds a single node to the hypernetwork. """
[docs] def __init__(self, attack_id: str, node_id: int) -> None: """ Initialize the add node attack. Args: attack_id: Unique identifier for this attack. node_id: ID of the node to add. """ super().__init__(attack_id) self.node_id = node_id
[docs] def execute(self, hypernetwork: Hypernetwork) -> bool: """ Execute the node addition attack. Args: hypernetwork: The target hypernetwork. Returns: True if the node was added successfully. """ try: initial_order = hypernetwork.order() hypernetwork.add_node(self.node_id) final_order = hypernetwork.order() self._executed = True self._result = { 'node_id': self.node_id, 'initial_order': initial_order, 'final_order': final_order, 'nodes_added': final_order - initial_order } return True except Exception as e: self._result = {'error': str(e)} return False
[docs] def describe(self) -> str: """Return description of the add node attack.""" return f"Add node {self.node_id}"
[docs] class RemoveNodeAttack(Attack): """ Attack that removes a single node from the hypernetwork. """
[docs] def __init__(self, attack_id: str, node_id: int) -> None: """ Initialize the remove node attack. Args: attack_id: Unique identifier for this attack. node_id: ID of the node to remove. """ super().__init__(attack_id) self.node_id = node_id
[docs] def execute(self, hypernetwork: Hypernetwork) -> bool: """ Execute the node removal attack. Args: hypernetwork: The target hypernetwork. Returns: True if the node was removed successfully. """ try: initial_order = hypernetwork.order() initial_size = hypernetwork.size() # Check if node exists before removal node_exists = self.node_id in hypernetwork.nodes affected_edges = hypernetwork.get_hyperedges( self.node_id) if node_exists else [] hypernetwork.remove_node(self.node_id) final_order = hypernetwork.order() final_size = hypernetwork.size() self._executed = True self._result = { 'node_id': self.node_id, 'node_existed': node_exists, 'initial_order': initial_order, 'final_order': final_order, 'initial_size': initial_size, 'final_size': final_size, 'nodes_removed': initial_order - final_order, 'edges_affected': len(affected_edges), 'edges_removed': initial_size - final_size } return True except Exception as e: self._result = {'error': str(e)} return False
[docs] def describe(self) -> str: """Return description of the remove node attack.""" return f"Remove node {self.node_id}"
[docs] class AddHyperedgeAttack(Attack): """ Attack that adds a single hyperedge to the hypernetwork. """
[docs] def __init__(self, attack_id: str, edge_id: int, members: list[int]) -> None: """ Initialize the add hyperedge attack. Args: attack_id: Unique identifier for this attack. edge_id: ID of the hyperedge to add. members: List of node IDs that form the hyperedge. """ super().__init__(attack_id) self.edge_id = edge_id self.members = list( members) # Make a copy to avoid external modifications
[docs] def execute(self, hypernetwork: Hypernetwork) -> bool: """ Execute the hyperedge addition attack. Args: hypernetwork: The target hypernetwork. Returns: True if the hyperedge was added successfully. """ try: initial_size = hypernetwork.size() initial_order = hypernetwork.order() hypernetwork.add_hyperedge(self.edge_id, self.members) final_size = hypernetwork.size() final_order = hypernetwork.order() self._executed = True self._result = { 'edge_id': self.edge_id, 'members': self.members.copy(), 'initial_size': initial_size, 'final_size': final_size, 'initial_order': initial_order, 'final_order': final_order, 'edges_added': final_size - initial_size, 'nodes_added': final_order - initial_order } return True except Exception as e: self._result = {'error': str(e)} return False
[docs] def describe(self) -> str: """Return description of the add hyperedge attack.""" return f"Add hyperedge {self.edge_id} with members {self.members}"
[docs] class RemoveHyperedgeAttack(Attack): """ Attack that removes a single hyperedge from the hypernetwork. """
[docs] def __init__(self, attack_id: str, edge_id: int) -> None: """ Initialize the remove hyperedge attack. Args: attack_id: Unique identifier for this attack. edge_id: ID of the hyperedge to remove. """ super().__init__(attack_id) self.edge_id = edge_id
[docs] def execute(self, hypernetwork: Hypernetwork) -> bool: """ Execute the hyperedge removal attack. Args: hypernetwork: The target hypernetwork. Returns: True if the hyperedge was removed successfully. """ try: initial_size = hypernetwork.size() # Check if edge exists and get its members before removal edge_exists = self.edge_id in hypernetwork.edges members = hypernetwork.get_nodes( self.edge_id) if edge_exists else [] hypernetwork.remove_hyperedge(self.edge_id) final_size = hypernetwork.size() self._executed = True self._result = { 'edge_id': self.edge_id, 'edge_existed': edge_exists, 'members': members, 'initial_size': initial_size, 'final_size': final_size, 'edges_removed': initial_size - final_size } return True except Exception as e: self._result = {'error': str(e)} return False
[docs] def describe(self) -> str: """Return description of the remove hyperedge attack.""" return f"Remove hyperedge {self.edge_id}"