Skip to content

Commit

Permalink
graph with named edges
Browse files Browse the repository at this point in the history
  • Loading branch information
arashbm committed May 29, 2024
1 parent 72fb668 commit e1db7f6
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "bliss-bind"
version = "0.1.0"
version = "0.2.0"
description = "Minimal Python binding for Bliss: open-source tool for computing canonical labelings and automorphism groups of graphs."
readme = "README.md"
requires-python = ">=3.8"
Expand Down
91 changes: 91 additions & 0 deletions src/bliss_bind/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,92 @@
from .bliss_bind_ext import Graph, Digraph, Stats


class NamedGraph():
def __init__(self):
# maps node index to node names
self.node_name = {}

# maps node names to colors/indces
self.node_color = {}
self.node_index = {}

# maps node names to a set of neighbour node names
self.neighbours = {}

self.g = Graph()

def add_node(self, name, color):
v = self.g.add_vertex(color=color)
if v is None:
return

self.node_name[v] = name
self.node_index[name] = v
self.node_color[name] = color
self.neighbours[name] = set()

def add_link(self, node1, node2):
self.g.add_edge(self.node_index[node1],
self.node_index[node2])
self.neighbours[node1].add(node2)
self.neighbours[node2].add(node1)

def __eq__(self, other):
return self.node_color == other.node_color and \
self.neighbours == other.neighbours

def canonical_labelling(self):
labelling, _ = self.g.canonical_form()
return {self.node_name[i]: l
for i, l in enumerate(labelling)}

def canonical_graph(self):
return self.relabel(self.canonical_labelling())

def relabel(self, labelling):
if set(labelling) != set(self.node_index):
raise ValueError("labelling does not map nodes")

cpy = NamedGraph()
for name, l in labelling.items():
if l in cpy.node_index:
raise ValueError("labelling is not a bijection")
cpy.add_node(l, self.node_color[name])

for name, l in labelling.items():
for n in self.neighbours[name]:
if n >= name:
cpy.add_link(l, labelling[n])

return cpy

def __copy__(self):
return self.relabel({n: n for n in self.node_index})

def get_isomorphism(self, other):
self_degs = sorted(map(len, self.neighbours.values()))
other_degs = sorted(map(len, other.neighbours.values()))
if self_degs != other_degs:
return None

self_cols = sorted(self.node_color.values())
other_cols = sorted(other.node_color.values())
if self_cols != other_cols:
return None

this_can_labelling = self.canonical_labelling()
other_can_labelling = other.canonical_labelling()
if self.relabel(this_can_labelling) != \
other.relabel(other_can_labelling):
return None

inverse_can_labelling = {v: k for k, v in other_can_labelling.items()}
return {k: inverse_can_labelling[v]
for k, v in this_can_labelling.items()}

def find_automorphisms(self):
perms = []
self.g.find_automorphisms(
callback=lambda x: perms.append(x))

return perms

0 comments on commit e1db7f6

Please sign in to comment.