#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ from __future__ import annotations; from src.local.typing import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # EXPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __all__ = [ 'Graph', ]; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # CLASS Graph # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class Graph(object): ''' a data structure for graphs ''' nodes: list[Any]; edges: list[tuple[Any,Any]] def __init__(self, nodes: list[Any], edges: list[tuple[Any,Any]]): self.nodes = nodes; self.edges = edges; return; def __len__(self) -> int: return len(self.nodes); def subgraph(self, nodes: list[Any]) -> Graph: ''' @returns graph induced by subset of nodes ''' return Graph( nodes = [ u for u in self.nodes if u in nodes ], edges = [ (u, v) for u, v in self.edges if u in nodes and v in nodes ], ); def successors(self, u: str): ''' @returns list of successor nodes ''' return [ v for (u_, v) in self.edges if u == u_ ]; def predecessors(self, v: str): ''' @returns list of predecessor nodes ''' return [ u for (u, v_) in self.edges if v == v_ ];