def test_min_max_nodes(): """ Make sure min_nodes <= max_nodes """ builder = graph_builder(min_nodes=10, max_nodes=5) with pytest.raises(ValueError): builder.example()
def test_node_edge_data(data): """ Make sure node and edge data end up in the right place. """ node_data = st.dictionaries(keys=st.one_of(st.text(), st.integers()), values=st.one_of(st.text(), st.integers()), max_size=2) node_data = data.draw(node_data) node_data_st = st.just(node_data) edge_data = st.dictionaries(keys=st.one_of(st.text(), st.integers()), values=st.one_of(st.text(), st.integers()), max_size=2) edge_data = data.draw(edge_data) edge_data_st = st.just(edge_data) builder = graph_builder(max_nodes=3, max_edges=3, node_data=node_data_st, edge_data=edge_data_st) graph = data.draw(builder) for node in graph: assert graph.nodes[node] == node_data for edge in graph.edges: assert graph.edges[edge] == edge_data
def test_max_edges(): """ Make sure that max_edges is large enough to not conflict with connected=True """ builder = graph_builder(max_nodes=5, connected=True, max_edges=2) with pytest.raises(ValueError): builder.example()
def test_min_nodes(): """ Make sure min_nodes is positive. """ builder = graph_builder(min_nodes=-5) with pytest.raises(ValueError): builder.example()
def test_negative_max_edges(data): """ Make sure that when max_edges < 0, max_edges becomes 0. """ builder = graph_builder(max_nodes=5, connected=False, max_edges=-1) graph = data.draw(builder) note("Number of nodes: {}".format(len(graph.nodes))) note("Number of edges: {}".format(len(graph.edges))) assert len(graph.edges) == 0 assert len(graph.nodes) <= 5
def test_node_keys(data): """ Make sure node keys are drawn from the correct strategy. """ size = 5 base_keys = st.one_of(st.integers(), st.text()) node_keys = st.sets(st.recursive(base_keys, lambda s: st.tuples(s, s)), min_size=size, max_size=size) keys = data.draw(node_keys) graph = data.draw(graph_builder(min_nodes=size, max_nodes=size, node_keys=st.sampled_from(list(keys)))) assert set(graph.nodes) == set(keys)
# pylint: disable=no-value-for-parameter, no-member MAX_NODES = 10 ATTRNAMES = ['attr1', 'attr2'] NODE_DATA = st.dictionaries(keys=st.sampled_from(ATTRNAMES), values=st.integers(min_value=0, max_value=MAX_NODES)) ATTRS = st.lists(st.sampled_from(ATTRNAMES), unique=True, min_size=0, max_size=2) MCS_BUILDER = graph_builder(node_data=NODE_DATA, min_nodes=0, max_nodes=MAX_NODES, node_keys=st.integers(max_value=MAX_NODES, min_value=0)) @settings(max_examples=500, deadline=None) @given(graph1=MCS_BUILDER, graph2=MCS_BUILDER, attrs=ATTRS) def test_maximum_common_subgraph(graph1, graph2, attrs): """ Test ``maximum_common_subgraph`` against ``categorical_maximum_common_subgraph`` as reference implementation. """ expected = vermouth.graph_utils.categorical_maximum_common_subgraph( graph1, graph2, attrs) found = vermouth.graph_utils.maximum_common_subgraph(graph1, graph2, attrs)
def test_graph_builder(data): """ Make sure the number of nodes and edges of the generated graphs is correct, and make sure that graphs that are supposed to be connected are. """ graph_types = st.sampled_from([ nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph, nx.OrderedGraph, nx.OrderedDiGraph, nx.OrderedMultiGraph, nx.OrderedMultiDiGraph ]) graph_type = data.draw(graph_types, label='graph type') node_keys = st.integers() multigraph = graph_type in [ nx.MultiGraph, nx.MultiDiGraph, nx.OrderedMultiGraph, nx.OrderedMultiDiGraph ] min_nodes = data.draw(st.integers(min_value=0, max_value=25), label='min nodes') max_nodes = data.draw(st.integers(min_value=min_nodes, max_value=25), label='max nodes') max_min_edges = None if not multigraph else 50 min_edges = data.draw(st.integers(min_value=0, max_value=max_min_edges), label='min edges') max_edges = data.draw(st.one_of( st.none(), st.integers(min_value=max(min_edges, max_nodes - 1))), label='max edges') if multigraph: max_edges = min(50, max_edges) if max_edges else 50 self_loops = data.draw(st.booleans(), label='self loops') connected = data.draw(st.booleans(), label='connected') strategy = graph_builder(node_keys=node_keys, min_nodes=min_nodes, max_nodes=max_nodes, min_edges=min_edges, max_edges=max_edges, self_loops=self_loops, connected=connected, graph_type=graph_type) graph = data.draw(strategy) note("Number of nodes: {}".format(len(graph))) note("Number of edges: {}".format(len(graph.edges))) if isinstance(graph, nx.DiGraph): max_possible_edges = len(graph.nodes) * (len(graph.nodes) - 1) elif isinstance(graph, nx.Graph): max_possible_edges = len(graph.nodes) * (len(graph.nodes) - 1) // 2 if isinstance(graph, nx.MultiGraph): max_possible_edges = float('inf') if self_loops: max_possible_edges += len(graph.nodes) if max_edges is None: max_edges = float('inf') if max_nodes is None: max_nodes = float('inf') if min_edges > max_possible_edges: min_edges = max_possible_edges if len(graph) < 2: min_edges = 0 note('min_edges: {}'.format(min_edges)) note('max_edges: {}'.format(max_edges)) assert isinstance(graph, graph_type) assert min_nodes <= len(graph.nodes) <= max_nodes assert min_edges <= len(graph.edges) <= max_edges assert self_loops or nx.number_of_selfloops(graph) == 0 if graph: if isinstance(graph, nx.DiGraph): assert not connected or nx.is_weakly_connected(graph) else: assert not connected or nx.is_connected(graph)
import networkx as nx from hypothesis_networkx import graph_builder import sys from Dijkstra import Graph import random from hypothesis import find, settings, Verbosity node_data = st.fixed_dictionaries({'number': st.text()}) edge_data = st.fixed_dictionaries( {'weight': st.floats(allow_nan=False, allow_infinity=False, min_value=1)}) builder = graph_builder(graph_type=nx.MultiDiGraph, node_keys=st.integers(), node_data=node_data, edge_data=edge_data, min_nodes=10, max_nodes=10, min_edges=10, max_edges=None, self_loops=False, connected=True) node_data2 = st.fixed_dictionaries({'number': st.text()}) edge_data2 = st.fixed_dictionaries( {'weight': st.floats(allow_nan=False, allow_infinity=False, min_value=1)}) builder2 = graph_builder(graph_type=nx.DiGraph, node_keys=st.integers(), node_data=node_data, edge_data=edge_data, min_nodes=10, max_nodes=10,
""" Stress test using hypothesis to generate test cases. Idea: - generate random graph - calculate immediate dominators using two different algorithms - compare the results """ from ppci.graph import lt, cfg from ppci.graph.algorithm import fixed_point_dominator import hypothesis from hypothesis_networkx import graph_builder builder = graph_builder(min_nodes=1, max_nodes=None) @hypothesis.given(builder) @hypothesis.settings(max_examples=1000) def test_a(nx_graph): print("nodes", nx_graph.nodes) print("edges", nx_graph.edges) node_map = {} g = cfg.ControlFlowGraph() for n in nx_graph.nodes: n2 = cfg.ControlFlowNode(g) node_map[n] = n2 g.add_node(n2)
def test_multigraph_max_edges_none(): try: graph_builder(graph_type=nx.MultiGraph, max_edges=None).example() except Exception: pytest.fail()
class SMILESTest(RuleBasedStateMachine): @initialize(mol=graph_builder(node_data=node_data, edge_data=edge_data, min_nodes=1, max_nodes=7)) def setup(self, mol): valid_hydrogen_count(mol) self.mol = mol note(self.mol.nodes(data=True)) note(self.mol.edges(data=True)) @rule() def add_explicit_hydrogens(self): add_explicit_hydrogens(self.mol) @rule() def remove_explicit_hydrogens(self): remove_explicit_hydrogens(self.mol) # We can't run this halfway through, because aromaticity does not always get # encoded in the SMILES string. In particular when * elements are involved. # @rule() # def correct_aromatic_rings(self): # correct_aromatic_rings(self.mol) @rule() def fill_valence(self): fill_valence(self.mol) @rule() def increment_bond_orders(self): increment_bond_orders(self.mol) @precondition(lambda self: hasattr(self, 'mol')) @invariant() def write_read_cycle(self): smiles = write_smiles(self.mol) note(self.mol.nodes(data=True)) note(self.mol.edges(data=True)) note(smiles) # self.mol can exist in a mixed implicit/explicit H style. The reference # must be one or the other, since we can't read in mixed mode. We want # to be sure we produce the correct answer in both cases though. for expl_H in (False, True): ref_mol = self.mol.copy() defaults = {'charge': 0, 'hcount': 0} for node in ref_mol: for key, val in defaults.items(): if key not in ref_mol.nodes[node]: ref_mol.nodes[node][key] = val if expl_H: add_explicit_hydrogens(ref_mol) else: remove_explicit_hydrogens(ref_mol) found = read_smiles(smiles, explicit_hydrogen=expl_H, reinterpret_aromatic=False) note(found.nodes(data=True)) note(found.edges(data=True)) assertEqualGraphs(ref_mol, found)