Skip to content
Open
43 changes: 43 additions & 0 deletions tests/test_counting.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import numpy as np
import pandas as pd
import networkx as nx
from scipy.sparse import csr_matrix

@pytest.fixture
Expand Down Expand Up @@ -54,6 +55,7 @@ def smp_star():
smp = MatchingProblem(tmplt, world)
return smp


@pytest.fixture
def smp_node_cover():
"""Create a subgraph matching problem requiring the use of node cover."""
Expand Down Expand Up @@ -178,3 +180,44 @@ def test_count_isomorphisms_overlapping_cands(self, smp_overlapping_cands):
assert np.sum(smp_overlapping_cands.candidates()) == 7
count = count_isomorphisms(smp_overlapping_cands, verbose=True)
assert count == 6

def test_count_isomorphisms_random_all_matches(self):
"""
Perform a test where every possible mapping of template to world nodes
is a match.
"""
for i in range(10):
random_adj = np.random.random((5, 5))
# No self loops
np.fill_diagonal(random_adj, 0)
t_graph = Graph([csr_matrix(random_adj)])

complete_graph = nx.complete_graph(5)
w_graph = uclasm.from_networkx_graph(complete_graph)

smp = MatchingProblem(t_graph, w_graph)

count = count_isomorphisms(smp, verbose=True)
assert count == 120 # 5 factorial

eq_count = count_isomorphisms(smp, verbose=True, tmplt_equivalence=True)
assert count == 120

def test_count_isomorphisms_random_no_matches(self):
for i in range(10):
random_adj = np.random.random((5, 5))
# No self loops
np.fill_diagonal(random_adj, 0)
t_graph = Graph([csr_matrix(random_adj)])

empty_adj = csr_matrix(np.zeros((5,5)))
w_graph = Graph([empty_adj])

smp = MatchingProblem(t_graph, w_graph)

count = count_isomorphisms(smp, verbose=True)
assert count == 0

eq_count = count_isomorphisms(smp, verbose=True, tmplt_equivalence=True)
assert count == 0

58 changes: 58 additions & 0 deletions tests/test_equivalence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
Tests for structural equivalence.
"""
import pytest
import networkx as nx

from uclasm.graph import from_networkx_graph


@pytest.fixture
def star_graph_5():
"""
Creates the star graph S5, the graph with 1 central node and 5 spokes.
The node with index 0 should be the central node.
"""
star_graph = nx.star_graph(5)
return from_networkx_graph(star_graph)


@pytest.fixture
def complete_graph_5():
"""
Creates the complete graph K5, the graph with 5 nodes each connected to
every other node.
"""
complete_graph = nx.complete_graph(5)
return from_networkx_graph(complete_graph)


@pytest.fixture
def path_graph_5():
"""
Creates the path graph P5, the path graph with 5 nodes.
"""
path_graph = nx.path_graph(5)
return from_networkx_graph(path_graph)


def test_star_graph_equivalence(star_graph_5):
equiv = star_graph_5.equivalence_classes
assert len(equiv.classes) == 2
assert equiv.classes[0] == {0}
rep_1 = equiv.representative(1)
assert equiv.classes[rep_1] == {1,2,3,4,5}


def test_complete_graph_equivalence(complete_graph_5):
equiv = complete_graph_5.equivalence_classes
assert len(equiv.classes) == 1
rep = equiv.representative(0)
assert equiv.classes[rep] == {0,1,2,3,4}


def test_path_graph_equivalence(path_graph_5):
equiv = path_graph_5.equivalence_classes
assert len(equiv.classes) == 5
for i in range(5):
assert equiv.classes[i] == {i}
1 change: 1 addition & 0 deletions uclasm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
from .utils import *
from .matching import *
from .interface import *
from .equivalence import *
Loading