Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Rewrite test_metis.py to test exposed functions #44

Merged
merged 1 commit into from
Jul 22, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 77 additions & 52 deletions nxmetis/tests/test_metis.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import itertools
import nose.tools

import networkx as nx

import nxmetis
from nxmetis import exceptions
from nxmetis import _metis
from nxmetis import types
Expand All @@ -17,59 +20,81 @@ def make_cycle(n):

class TestMetis(object):

def test_node_nd(self):
n = 16
xadj, adjncy = make_cycle(n)
perm, iperm = _metis.node_nd(xadj, adjncy)
nose.tools.assert_equal(set(perm), set(range(n)))
nose.tools.assert_equal(abs(perm[-1] - perm[-2]), n // 2)
nose.tools.ok_(set(range(min(perm[-2:]) + 1, max(perm[-2:]))) in
(set(perm[0:n // 2 - 1]), set(perm[n // 2 - 1:-2])))
nose.tools.ok_(all(i == perm[iperm[i]] for i in range(n)))

def test_selfloops(self):
n = 16
xadj = list(range(0, 3 * n + 1, 3))
adjncy = list(
itertools.chain.from_iterable(
zip(itertools.chain([n - 1], range(n - 1)),
range(n),
itertools.chain(range(1, n), [0]))))
perm, iperm = _metis.node_nd(xadj, adjncy)
nose.tools.assert_equal(set(perm), set(range(n)))
nose.tools.assert_equal(abs(perm[-1] - perm[-2]), n // 2)
nose.tools.ok_(set(range(min(perm[-2:]) + 1, max(perm[-2:]))) in
(set(perm[0:n // 2 - 1]), set(perm[n // 2 - 1:-2])))
nose.tools.ok_(all(i == perm[iperm[i]] for i in range(n)))

def test_part_graph(self):
n = 16
xadj, adjncy = make_cycle(n)
for recursive in (False, True):
objval, part = _metis.part_graph(
xadj, adjncy, 2, recursive=recursive)
nose.tools.assert_equal(objval, 2)
nose.tools.assert_equal(set(part), set(range(2)))
it = itertools.dropwhile(lambda x: x == 0, itertools.cycle(part))
nose.tools.assert_equal(
list(itertools.takewhile(lambda x: x == 1, it)), [1] * (n // 2))

def test_compute_vertex_separator(self):
n = 16
xadj, adjncy = make_cycle(n)
sepsize, part = _metis.compute_vertex_separator(xadj, adjncy)
nose.tools.assert_equal(sepsize, 2)
nose.tools.assert_equal(len(part), n)
part1, part2, sep = (list(filter(lambda i: part[i] == k, range(n)))
for k in range(3))
nose.tools.assert_equal(sorted(part1 + part2 + sep), list(range(n)))
def setUp(self):
self.node_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
1, 2, 3, 4, 5, 6]
self.G = nx.Graph()
self.G.add_path(self.node_list)
self.G.add_edge(self.node_list[-1], self.node_list[0])

def test_node_nested_dissection_unweighted(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test that exercises the package's ability to handle self loops. IIRC, METIS crashes when you have self loops in graphs.

node_ordering = nxmetis.node_nested_dissection(self.G)
nose.tools.assert_equal(len(self.G), len(node_ordering))
nose.tools.assert_equal(set(self.G), set(node_ordering))

# Tests for exercising package's ability to handle self-loops
# METIS crashes on self loops. networkx-metis should not
self.G.add_edge(1, 1)
self.G.add_edge('a', 'a')
node_ordering = nxmetis.node_nested_dissection(self.G)
nose.tools.assert_equal(len(self.G), len(node_ordering))
nose.tools.assert_equal(set(self.G), set(node_ordering))

def test_partition(self):
partition = nxmetis.partition(self.G, 4)
# When we choose one node from one part of the partitioned Graph,
# It must be adjacent to one or more of the nodes in the same part.
# This is to verify the continuity of the chain of nodes.
parts = partition[1] # List containing partitioned node lists
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep this loops as the underlying METIS functions are different.


nose.tools.assert_equal(list(partition)[0], 4)

for part in parts:
nose.tools.assert_not_equal(0, len(part)) # Non-empty set
nose.tools.assert_equal(len(part), len(set(part))) # Duplicate-free
nose.tools.ok_(nx.is_connected(self.G.subgraph(part))) # Connected

# Disjoint sets
for part1, part2 in itertools.combinations(parts, 2):
nose.tools.assert_equal(set(), set(part1) & set(part2))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about exhaustiveness?


# These parts must be exhaustive with the node list of the Graph
parts_combined = parts[0] + parts[1] + parts[2] + parts[3]
nose.tools.assert_equal(set(parts_combined), set(self.G))

def test_vertex_separator(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify this test the same way as test_partition.

bisection = nxmetis.vertex_separator(self.G)
sep, part1, part2 = nxmetis.vertex_separator(self.G)

# The two separator nodes must not be present in the
# two bisected chains
nose.tools.ok_(sep[0] not in part1)
nose.tools.ok_(sep[0] not in part2)
nose.tools.ok_(sep[1] not in part1)
nose.tools.ok_(sep[1] not in part2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to first check that len(sep) is two. You also need to verify that sep[0] is different from seq[1].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Added them L#78 and L#77


# There should be two different separator nodes
nose.tools.assert_equal(len(sep), 2)
nose.tools.assert_equal(abs(sep[1] - sep[0]), n // 2)
nose.tools.assert_equal(
sorted(map(sorted, [part1, part2])),
sorted(map(sorted,
[[(sep[0] + i) % n for i in range(1, n // 2)],
[(sep[1] + i) % n for i in range(1, n // 2)]])))
nose.tools.assert_not_equal(sep[0], sep[1])

# The lists should be exhaustive with the node list of the Graph
nose.tools.assert_equal(set(sep) | set(part1) | set(part2),
set(self.G))

# The parts must be disjoint sets
nose.tools.assert_equal(set(), set(part1) & set(part2))

# Non-empty set
nose.tools.assert_not_equal(len(part1), 0)
nose.tools.assert_not_equal(len(part2), 0)

# Duplicate-free
nose.tools.assert_equal(len(part1), len(set(part1)))
nose.tools.assert_equal(len(part2), len(set(part2)))

# Connected
nose.tools.ok_(nx.is_connected(self.G.subgraph(part1)))
nose.tools.ok_(nx.is_connected(self.G.subgraph(part2)))

def test_MetisOptions(self):
n = 16
Expand Down