Skip to content

Commit d07905b

Browse files
weilycoderMr-Python-in-China
authored andcommitted
Add SwitchGraph
1 parent 5116d54 commit d07905b

File tree

1 file changed

+87
-2
lines changed

1 file changed

+87
-2
lines changed

cyaron/graph.py

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from .utils import *
22
from .vector import Vector
33
import random
4-
from typing import TypeVar, Callable
4+
import itertools
5+
from typing import Dict, Iterable, List, Tuple, TypeVar, Callable, Union
56

6-
__all__ = ["Edge", "Graph"]
7+
__all__ = ["Edge", "Graph", "SwitchGraph"]
78

89

910
class Edge:
@@ -34,6 +35,90 @@ def unweighted_edge(edge):
3435
return '%d %d' % (edge.start, edge.end)
3536

3637

38+
class SwitchGraph:
39+
"""A graph which can switch edges quickly
40+
"""
41+
directed: bool
42+
__edges: Dict[Tuple[int, int], int]
43+
44+
def get_edges(self):
45+
ret: List[Tuple[int, int]] = []
46+
for k in self.__edges:
47+
ret.extend(itertools.repeat(k, self.__edges[k]))
48+
return ret
49+
50+
def __insert(self, u: int, v: int):
51+
if (u, v) not in self.__edges:
52+
self.__edges[(u, v)] = 0
53+
self.__edges[(u, v)] += 1
54+
55+
def __remove(self, u: int, v: int):
56+
self.__edges[(u, v)] -= 1
57+
if self.__edges[(u, v)] == 0:
58+
self.__edges.pop((u, v))
59+
60+
def insert(self, u: int, v: int):
61+
"""Add edge (u, v)
62+
"""
63+
self.__insert(u, v)
64+
if not self.directed and u != v:
65+
self.__insert(v, u)
66+
67+
def remove(self, u: int, v: int):
68+
"""Remove edge (u, v)
69+
"""
70+
self.__remove(u, v)
71+
if not self.directed and u != v:
72+
self.__remove(v, u)
73+
74+
def __init__(self,
75+
E: Iterable[Union[Edge, Tuple[int, int]]],
76+
directed: bool = True):
77+
self.directed = directed
78+
self.__edges = {}
79+
for e in E:
80+
if isinstance(e, Edge):
81+
self.__insert(e.start, e.end)
82+
else:
83+
self.__insert(e[0], e[1])
84+
85+
def switch(self, *, self_loop: bool = False, repeated_edges: bool = False):
86+
"""Mutates the current directed graph by swapping pairs of edges, without impacting the degree sequence.
87+
88+
A switch is a general term for a small change in the structure of a graph, achieved by swapping small numbers
89+
of edges.
90+
91+
Returns:
92+
If a switch was performed, then return True. If the switch was rejected, then return False.
93+
"""
94+
first, second = random.choices(list(self.__edges.keys()),
95+
list(self.__edges.values()),
96+
k=2)
97+
x1, y1 = first
98+
x2, y2 = second
99+
100+
if self_loop:
101+
if x1 == x2 or y1 == y2:
102+
return False
103+
else:
104+
if {x1, y1} & {x2, y2} != set():
105+
return False
106+
107+
if repeated_edges:
108+
if (x1, y2) in self.__edges or (x2, y1) in self.__edges:
109+
return False
110+
111+
self.remove(x1, y1)
112+
self.insert(x1, y2)
113+
self.remove(x2, y2)
114+
self.insert(x2, y1)
115+
116+
return True
117+
118+
def __iter__(self):
119+
return iter(self.__edges)
120+
121+
37122
class Graph:
38123
"""Class Graph: A class of the graph
39124
"""

0 commit comments

Comments
 (0)