def test_loops(self): # Loop, no automorphisms g1 = pysaucy.Graph([[0, 1], []]) result = pysaucy.run_saucy(g1) self.assertEqual(result, (1.0, 0, 1, 1, 0, 0, 0, [0, 1])) # No loop, automorphisms g2 = pysaucy.Graph([[1], []]) result = pysaucy.run_saucy(g2) self.assertEqual(result, (2.0, 0, 2, 3, 0, 1, 2, [0, 0])) # Loops, automorphisms g3 = pysaucy.Graph([[0, 1], [1]]) result = pysaucy.run_saucy(g3) self.assertEqual(result, (2.0, 0, 2, 3, 0, 1, 2, [0, 0]))
def test_karate(self): karate = pysaucy.examples.karate() result = pysaucy.run_saucy(karate) self.assertEqual(480, result[0] * 10**result[1]) orbit_sizes = collections.defaultdict(int) for orbit_id in result[7]: orbit_sizes[orbit_id] += 1 self.assertEqual(len(orbit_sizes), 27)
def test_on_automorphism_callback(self): karate = pysaucy.examples.karate() generators = [] def on_aut(graph, perm, supp): generators.append(perm) result = pysaucy.run_saucy(karate, on_automorphism=on_aut) self.assertEqual(result[5], len(generators)) # Too few parameters def invalid_callback_1(a, b): pass with self.assertRaises(RuntimeError): pysaucy.run_saucy(karate, on_automorphism=invalid_callback_1) # No parameters def invalid_callback_2(): pass with self.assertRaises(RuntimeError): pysaucy.run_saucy(karate, on_automorphism=invalid_callback_2) # Too many parameters def invalid_callback_3(a, b, c, d): pass with self.assertRaises(RuntimeError): pysaucy.run_saucy(karate, on_automorphism=invalid_callback_3)
def test_color_partition(self): k11 = pysaucy.examples.complete(11) colors = [0] * 11 colors[10] = 1 # colors 'fixes' one node by putting it into another partition # => Aut(k11, colors) ~ Aut(k10) result = pysaucy.run_saucy(k11, colors=colors) self.assertTupleEqual(tuple(list(result)[:7]), (3.6287999999999996, 6, 10, 35, 0, 9, 18))
def analyze(g): """ This function analyzes a graph and returns a data-record which is a dictionary of results for the different performance indices. :param g: A graph :return: Result record """ record = {} logging.debug('Analyzing {} ({}, {})'.format(g.name, g.number_of_nodes(), g.number_of_edges())) if not nx.is_connected(g): raise DisconnectedError('{} is not connected: {}'.format(g, nx.number_connected_components(g))) record['name'] = g.name record['n'] = g.number_of_nodes() record['m'] = g.number_of_edges() record['density'] = nx.density(g) # record['degrees'] = networkx.degree(g) # record['diameter'] = networkx.diameter(g) # Compute modularity logging.debug('Compute modularity') record['modularity'] = _compute_modularity(g) empty_result = {'num_orbits': 'NA', 'num_generators': 'NA', 'aut_group_size': 'NA'} # Compute the automorphism group with saucy logging.debug('Convert saucy') g_pysaucy = networkx_to_pysaucy(g) colors = _get_color_partition(g) del g try: logging.debug('Run saucy') result = pysaucy.run_saucy(g_pysaucy, colors) except Exception as e: logging.error('{}: {}'.format(record['name'], e)) record.update(empty_result) else: grpsize1, grpsize2, levels, nodes, bads, num_generators, support, orbit_ids = result orbit_sizes = collections.defaultdict(int) for orbit_id in orbit_ids: orbit_sizes[orbit_id] += 1 record['num_orbits'] = len(orbit_sizes) record['num_generators'] = num_generators record['aut_group_size'] = grpsize1 record['aut_group_size_exp'] = grpsize2 return record
def test_wrong_parameters(self): g = pysaucy.Graph([]) g._adjacency_list = None with self.assertRaises(AttributeError) as e: pysaucy.run_saucy(g) self.assertIn('Error accessing attribute.', e.exception.message) g._adjacency_list = 1 with self.assertRaises(AttributeError) as e: pysaucy.run_saucy(g) self.assertIn('Error accessing attribute.', e.exception.message) g._adjacency_list = [["1", 2, 3], [""]] with self.assertRaises(TypeError) as e: pysaucy.run_saucy(g) self.assertIn('Not a Python integer.', e.exception.message) g._adjacency_list = [[1, 2, 3], []] with self.assertRaises(ValueError) as e: pysaucy.run_saucy(g) self.assertIn('Invalid node id.', e.exception.message) c_int = 2**31 g._adjacency_list = [[c_int]] with self.assertRaises(ValueError) as e: pysaucy.run_saucy(g) self.assertIn( 'Could not convert Python integer to C integer as it is too large.', e.exception.message) c_int = 2**31 - 1 g._adjacency_list = [[c_int]] with self.assertRaises(ValueError) as e: pysaucy.run_saucy(g) self.assertIn('Invalid node id.', e.exception.message)
def test_null_graph(self): null = pysaucy.Graph([]) with self.assertRaises(AttributeError) as e: pysaucy.run_saucy(null) self.assertIn('Empty graph detected.', e.exception.message)
def test_empty_k10(self): empty = pysaucy.Graph([[]] * 10) result = pysaucy.run_saucy(empty) self.assertTupleEqual(tuple(list(result)[:7]), (3.6287999999999996, 6, 10, 35, 0, 9, 18))
def test_k10(self): k10 = pysaucy.examples.complete(10) result = pysaucy.run_saucy(k10) self.assertTupleEqual(tuple(list(result)[:7]), (3.6287999999999996, 6, 10, 35, 0, 9, 18))
def test_k1000(self): result = pysaucy.run_saucy(self.k1000) self.assertTupleEqual( tuple(list(result)[:7]), (4.023872600770939, 2567, 1000, 3995, 0, 999, 1998))