def apply(self, graph: Graph, prod_input: List[str], orientation: int = 0, **kwargs) -> List[str]: [initial_node_id] = prod_input initial_node_data = graph.nodes[initial_node_id] if initial_node_data['layer'] != 0: raise ValueError('bad layer') if initial_node_data['label'] != 'E': raise ValueError('bad label') positions = self.__get_positions(kwargs['positions'] if 'positions' in kwargs else None) # change label initial_node_data['label'] = 'e' vx_tl = gen_name() vx_tr = gen_name() vx_bl = gen_name() vx_br = gen_name() graph.add_node(vx_bl, layer=1, position=positions[0], label='E') graph.add_node(vx_br, layer=1, position=positions[1], label='E') graph.add_node(vx_tl, layer=1, position=positions[2], label='E') graph.add_node(vx_tr, layer=1, position=positions[3], label='E') if orientation % 2 == 1: [vx_bl, vx_br, vx_tr, vx_tl] = [vx_br, vx_tr, vx_tl, vx_bl] graph.add_edge(vx_tl, vx_tr) graph.add_edge(vx_tr, vx_br) graph.add_edge(vx_br, vx_bl) graph.add_edge(vx_bl, vx_tl) graph.add_edge(vx_tr, vx_bl) i1 = add_interior(graph, vx_tl, vx_tr, vx_bl) i2 = add_interior(graph, vx_tr, vx_br, vx_bl) graph.add_edge(i1, initial_node_id) graph.add_edge(i2, initial_node_id) return [i1, i2]
def test_happy_path(self): graph = Graph() e1 = gen_name() e2 = gen_name() e3 = gen_name() graph.add_node(e1, layer=1, position=(1.0, 2.0), label='E') graph.add_node(e2, layer=1, position=(1.0, 1.0), label='E') graph.add_node(e3, layer=1, position=(2.0, 1.0), label='E') graph.add_edge(e1, e2) graph.add_edge(e1, e3) graph.add_edge(e2, e3) i = add_interior(graph, e1, e2, e3) [i1, i2] = P2().apply(graph, [i]) self.assertEqual(len(graph.nodes()), 10) self.assertEqual(len(graph.edges()), 19) self.assertEqual(graph.nodes[i]['label'], 'i') self.assertTrue(graph.has_edge(i, i1)) self.assertTrue(graph.has_edge(i, i2)) self.assertEqual(graph.nodes[i1]['label'], 'I') self.assertEqual(graph.nodes[i2]['label'], 'I') self.assertEqual(graph.nodes[i1]['layer'], graph.nodes[i]['layer'] + 1) self.assertEqual(graph.nodes[i2]['layer'], graph.nodes[i]['layer'] + 1) i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer']) self.assertEqual(len(i1_neighbors), 3) i2_neighbors = get_neighbors_at(graph, i2, graph.nodes[i2]['layer']) self.assertEqual(len(i2_neighbors), 3) common_neighbors = [x for x in i1_neighbors if x in i2_neighbors] for n in i1_neighbors: if n not in common_neighbors: self.assertEqual(graph.nodes[n]['label'], 'E') self.assertEqual( len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])), 3) for n in i2_neighbors: if n not in common_neighbors: self.assertEqual(graph.nodes[n]['label'], 'E') self.assertEqual( len(get_neighbors_at(graph, n, graph.nodes[i2]['layer'])), 3) for c_neighbor in common_neighbors: self.assertEqual(graph.nodes[c_neighbor]['label'], 'E') self.assertEqual( len( get_neighbors_at(graph, c_neighbor, graph.nodes[i1]['layer'])), 5)
def apply(self, graph: Graph, prod_input: List[str], orientation: int = 0, **kwargs) -> List[str]: [i] = prod_input i_data = graph.nodes[i] self.__check_prod_input(graph, prod_input) i_data['label'] = 'i' i_layer = i_data['layer'] new_layer = i_layer + 1 i_neighbors = get_neighbors_at(graph, i, i_layer) # e1 doesn't mean e1 with (x1, y1) vx_e1 = gen_name() vx_e2 = gen_name() vx_e3 = gen_name() e1_pos = graph.nodes[i_neighbors[0]]['position'] e2_pos = graph.nodes[i_neighbors[1]]['position'] e3_pos = graph.nodes[i_neighbors[2]]['position'] graph.add_node(vx_e1, layer=new_layer, position=e1_pos, label='E') graph.add_node(vx_e2, layer=new_layer, position=e2_pos, label='E') graph.add_node(vx_e3, layer=new_layer, position=e3_pos, label='E') graph.add_edge(vx_e1, vx_e2) graph.add_edge(vx_e2, vx_e3) graph.add_edge(vx_e3, vx_e1) b = add_break(graph, [(vx_e1, vx_e2), (vx_e2, vx_e3), (vx_e3, vx_e1)]) b_neighbors = get_neighbors_at(graph, b, i_layer + 1) remaining = [x for x in [vx_e1, vx_e2, vx_e3] if x not in b_neighbors][0] graph.add_edge(b, remaining) i1 = add_interior(graph, b_neighbors[0], b, remaining) i2 = add_interior(graph, b_neighbors[1], b, remaining) graph.add_edge(i1, i) graph.add_edge(i2, i) return [i1, i2]
def test_bad_input_links(self): graph = Graph() e1 = gen_name() e2 = gen_name() e3 = gen_name() graph.add_node(e1, layer=1, position=(1.0, 2.0), label='E') graph.add_node(e2, layer=1, position=(1.0, 1.0), label='E') graph.add_node(e3, layer=1, position=(2.0, 1.0), label='E') graph.add_edge(e1, e2) graph.add_edge(e1, e3) i = add_interior(graph, e1, e2, e3) with self.assertRaises(AssertionError): P2().apply(graph, [i])
def test_bad_input_vertex_count(self): graph = Graph() positions = [(1.0, 1.0), (1.0, 3.0), (2.0, 3.0), (3.0, 3.0), (2.0, 2.0)] [e1, e2, e23, e3, e31] = self.create_nodes(graph, 1, 'E', positions) self.create_edges_chain(graph, [e1, e2, e23, e3, e31, e1]) i = add_interior(graph, e1, e2, e3) with self.assertRaises(AssertionError): [i1, i3, i2a, i2b] = P5().apply(graph, [i]) self.assertEqual(len(graph.nodes()), 6) self.assertEqual(len(graph.edges()), 8) if self.showPlots: pyplot.title("Vertex missing", fontsize=16) visualize_graph_3d(graph) pyplot.show()
def test_bad_input_i_label(self): graph = Graph() positions = [(1.0, 1.0), (1.0, 2.0), (1.0, 3.0), (2.0, 3.0), (3.0, 3.0), (2.0, 2.0)] [e1, e12, e2, e23, e3, e31] = self.create_nodes(graph, 1, 'E', positions) self.create_edges_chain(graph, [e1, e12, e2, e23, e3, e31, e1]) i = add_interior(graph, e1, e2, e3) graph.nodes[i]['label'] = 'i' with self.assertRaises(AssertionError): [i1, i3, i2a, i2b] = P5().apply(graph, [i]) self.assertEqual(len(graph.nodes()), 7) self.assertEqual(len(graph.edges()), 9) if self.showPlots: pyplot.title("Wrong 'i' label", fontsize=16) visualize_graph_3d(graph) pyplot.show()
def apply(self, graph: Graph, prod_input: List[str], orientation: int = 0, **kwargs) -> List[str]: eps = kwargs.get('epsilon', 1e-6) self.__check_prod_input(graph, prod_input, eps) [i] = prod_input i_data = graph.nodes[i] i_data['label'] = 'i' i_layer = i_data['layer'] new_layer = i_layer + 1 # get 'E' nodes from the left side of production [e1, e2, e3] = self.get_corner_nodes(graph, i, i_layer, orientation) e12 = self.get_node_between(graph, e1, e2, i_layer, eps) e23 = self.get_node_between(graph, e2, e3, i_layer, eps) e31 = self.get_node_between(graph, e3, e1, i_layer, eps) # create new 'E' nodes in the next layer new_e1 = gen_name() new_e2 = gen_name() new_e3 = gen_name() new_e12 = gen_name() new_e23 = gen_name() new_e31 = gen_name() graph.add_node(new_e1, layer=new_layer, position=graph.nodes[e1]['position'], label='E') graph.add_node(new_e2, layer=new_layer, position=graph.nodes[e2]['position'], label='E') graph.add_node(new_e3, layer=new_layer, position=graph.nodes[e3]['position'], label='E') graph.add_node(new_e12, layer=new_layer, position=graph.nodes[e12]['position'], label='E') graph.add_node(new_e23, layer=new_layer, position=graph.nodes[e23]['position'], label='E') graph.add_node(new_e31, layer=new_layer, position=graph.nodes[e31]['position'], label='E') # create edges between new 'E' nodes graph.add_edge(new_e1, new_e12) graph.add_edge(new_e12, new_e2) graph.add_edge(new_e2, new_e23) graph.add_edge(new_e23, new_e3) graph.add_edge(new_e3, new_e31) graph.add_edge(new_e31, new_e1) graph.add_edge(new_e23, new_e31) graph.add_edge(new_e12, new_e31) graph.add_edge(new_e2, new_e31) # create new 'I' nodes and edges between new 'I' nodes and new 'E' nodes i1 = add_interior(graph, new_e1, new_e12, new_e31) i3 = add_interior(graph, new_e3, new_e23, new_e31) i2a = add_interior(graph, new_e2, new_e12, new_e31) i2b = add_interior(graph, new_e2, new_e23, new_e31) # create edges between new 'I' nodes and parent 'i' node graph.add_edge(i1, i) graph.add_edge(i3, i) graph.add_edge(i2a, i) graph.add_edge(i2b, i) return [i1, i3, i2a, i2b]
def test_happy_path(self): graph = Graph() positions = [(1.0, 1.0), (1.0, 2.0), (1.0, 3.0), (2.0, 3.0), (3.0, 3.0), (2.0, 2.0)] [e1, e12, e2, e23, e3, e31] = self.create_nodes(graph, 1, 'E', positions) self.create_edges_chain(graph, [e1, e12, e2, e23, e3, e31, e1]) i = add_interior(graph, e1, e2, e3) if self.showPlots: pyplot.title("Correct input", fontsize=16) visualize_graph_3d(graph) pyplot.show() [i1, i3, i2a, i2b] = P5().apply(graph, [i]) if self.showPlots: pyplot.title("Correct output", fontsize=16) visualize_graph_3d(graph) pyplot.show() pyplot.title("Correct output (layer = 1)", fontsize=16) visualize_graph_layer(graph, 1) pyplot.show() pyplot.title("Correct output (layer = 2)", fontsize=16) visualize_graph_layer(graph, 2) pyplot.show() # if correct number of nodes and edges self.assertEqual(len(graph.nodes()), 17) self.assertEqual(len(graph.edges()), 34) # if cross-layer interior connections self.assertEqual(graph.nodes[i]['label'], 'i') self.assertTrue(graph.has_edge(i, i1)) self.assertTrue(graph.has_edge(i, i3)) self.assertTrue(graph.has_edge(i, i2a)) self.assertTrue(graph.has_edge(i, i2b)) # if new interiors has correct labels and layers self.assertEqual(graph.nodes[i1]['label'], 'I') self.assertEqual(graph.nodes[i3]['label'], 'I') self.assertEqual(graph.nodes[i2a]['label'], 'I') self.assertEqual(graph.nodes[i2b]['label'], 'I') self.assertEqual(graph.nodes[i1]['layer'], graph.nodes[i]['layer'] + 1) self.assertEqual(graph.nodes[i3]['layer'], graph.nodes[i]['layer'] + 1) self.assertEqual(graph.nodes[i2a]['layer'], graph.nodes[i]['layer'] + 1) self.assertEqual(graph.nodes[i2b]['layer'], graph.nodes[i]['layer'] + 1) # if each new interior has 3 neighbors i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer']) self.assertEqual(len(i1_neighbors), 3) i3_neighbors = get_neighbors_at(graph, i3, graph.nodes[i3]['layer']) self.assertEqual(len(i3_neighbors), 3) i2a_neighbors = get_neighbors_at(graph, i2a, graph.nodes[i2a]['layer']) self.assertEqual(len(i2a_neighbors), 3) i2b_neighbors = get_neighbors_at(graph, i2b, graph.nodes[i2b]['layer']) self.assertEqual(len(i2b_neighbors), 3) # if new nodes are in correct positions new_e1 = get_node_at(graph, 2, (1.0, 1.0)) new_e12 = get_node_at(graph, 2, (1.0, 2.0)) new_e2 = get_node_at(graph, 2, (1.0, 3.0)) new_e23 = get_node_at(graph, 2, (2.0, 3.0)) new_e3 = get_node_at(graph, 2, (3.0, 3.0)) new_e31 = get_node_at(graph, 2, (2.0, 2.0)) self.assertIsNotNone(new_e1) self.assertIsNotNone(new_e12) self.assertIsNotNone(new_e2) self.assertIsNotNone(new_e23) self.assertIsNotNone(new_e3) self.assertIsNotNone(new_e31) # if interiors connect with all new 6 vertices all_neighbors = i1_neighbors + i3_neighbors + i2a_neighbors + i2b_neighbors all_neighbors = list(dict.fromkeys(all_neighbors)) # remove duplicates self.assertEqual(len(all_neighbors), 6) # if each vertex has correct label for n in all_neighbors: self.assertEqual(graph.nodes[n]['label'], 'E') # if each vertex has correct number of neighbors (based on neighbour interiors count) for n in all_neighbors: node_neighbors = get_neighbors_at(graph, n, graph.nodes[n]['layer']) i_neighbors = [ x for x in node_neighbors if graph.nodes[x]['label'] == 'I' ] if len(i_neighbors) == 1: self.assertEqual(len(node_neighbors), 3) elif len(i_neighbors) == 2: self.assertEqual(len(node_neighbors), 5) else: # 4 self.assertEqual(len(node_neighbors), 9)
def test_parent_graph(self): graph = Graph() positions = [(1.0, 1.0), (1.0, 9.0), (9.0, 1.0), (9.0, 9.0), (5.0, 5.0), (3.0, 7.0), (7.0, 7.0), (6.0, 6.0), (4.0, 8.0)] [e0a, e1, e0b, e0c, e2, e12, e3, e23, e31] = self.create_nodes(graph, 1, 'E', positions) self.create_edges_chain(graph, [e0a, e1, e12, e0a, e2, e12]) self.create_edges_chain(graph, [e0a, e0b, e2, e23, e0b, e3, e23]) self.create_edges_chain(graph, [e0b, e0c, e3, e31, e0c, e1, e31]) i_0a_1_12 = add_interior(graph, e0a, e1, e12) i_0a_12_2 = add_interior(graph, e0a, e12, e2) i_0a_0b_2 = add_interior(graph, e0a, e0b, e2) i_0b_2_23 = add_interior(graph, e0b, e2, e23) i_0b_23_3 = add_interior(graph, e0b, e23, e3) i_0b_0c_3 = add_interior(graph, e0b, e3, e0c) i_0c_1_31 = add_interior(graph, e1, e31, e0c) i_0c_3_31 = add_interior(graph, e31, e3, e0c) i = add_interior(graph, e1, e2, e3) if self.showPlots: pyplot.title("Correct subgraph input", fontsize=16) visualize_graph_layer(graph, 1) pyplot.show() [i1, i3, i2a, i2b] = P5().apply(graph, [i]) if self.showPlots: pyplot.title("Correct subgraph output", fontsize=16) visualize_graph_3d(graph) pyplot.show() pyplot.title("Correct subgraph output (layer=1)", fontsize=16) visualize_graph_layer(graph, 1) pyplot.show() pyplot.title("Correct subgraph output (layer=2)", fontsize=16) visualize_graph_layer(graph, 2) pyplot.show() # if edges are unchanged self.assertTrue(graph.has_edge(e0a, e1)) self.assertTrue(graph.has_edge(e1, e12)) self.assertTrue(graph.has_edge(e12, e0a)) self.assertTrue(graph.has_edge(e0a, e2)) self.assertTrue(graph.has_edge(e2, e12)) self.assertTrue(graph.has_edge(e0a, e0b)) self.assertTrue(graph.has_edge(e0b, e2)) self.assertTrue(graph.has_edge(e2, e23)) self.assertTrue(graph.has_edge(e23, e0b)) self.assertTrue(graph.has_edge(e0b, e3)) self.assertTrue(graph.has_edge(e3, e23)) self.assertTrue(graph.has_edge(e0b, e0c)) self.assertTrue(graph.has_edge(e0c, e3)) self.assertTrue(graph.has_edge(e3, e31)) self.assertTrue(graph.has_edge(e31, e0c)) self.assertTrue(graph.has_edge(e0c, e1)) self.assertTrue(graph.has_edge(e1, e31)) # if interior links are unchanged self.assertTrue(graph.has_edge(i, e1)) self.assertTrue(graph.has_edge(i, e2)) self.assertTrue(graph.has_edge(i, e3)) self.assertTrue(graph.has_edge(i_0a_1_12, e0a)) self.assertTrue(graph.has_edge(i_0a_1_12, e1)) self.assertTrue(graph.has_edge(i_0a_1_12, e12)) self.assertTrue(graph.has_edge(i_0a_12_2, e0a)) self.assertTrue(graph.has_edge(i_0a_12_2, e12)) self.assertTrue(graph.has_edge(i_0a_12_2, e2)) self.assertTrue(graph.has_edge(i_0a_0b_2, e0a)) self.assertTrue(graph.has_edge(i_0a_0b_2, e0b)) self.assertTrue(graph.has_edge(i_0a_0b_2, e2)) self.assertTrue(graph.has_edge(i_0b_2_23, e0b)) self.assertTrue(graph.has_edge(i_0b_2_23, e2)) self.assertTrue(graph.has_edge(i_0b_2_23, e23)) self.assertTrue(graph.has_edge(i_0b_23_3, e0b)) self.assertTrue(graph.has_edge(i_0b_23_3, e23)) self.assertTrue(graph.has_edge(i_0b_23_3, e3)) self.assertTrue(graph.has_edge(i_0b_0c_3, e0b)) self.assertTrue(graph.has_edge(i_0b_0c_3, e3)) self.assertTrue(graph.has_edge(i_0b_0c_3, e0c)) self.assertTrue(graph.has_edge(i_0c_1_31, e1)) self.assertTrue(graph.has_edge(i_0c_1_31, e31)) self.assertTrue(graph.has_edge(i_0c_1_31, e0c)) self.assertTrue(graph.has_edge(i_0c_3_31, e31)) self.assertTrue(graph.has_edge(i_0c_3_31, e3)) self.assertTrue(graph.has_edge(i_0c_3_31, e0c)) # if vertex labels are unchanged self.assertEqual(graph.nodes[e0a]['label'], 'E') self.assertEqual(graph.nodes[e1]['label'], 'E') self.assertEqual(graph.nodes[e0b]['label'], 'E') self.assertEqual(graph.nodes[e0c]['label'], 'E') self.assertEqual(graph.nodes[e2]['label'], 'E') self.assertEqual(graph.nodes[e12]['label'], 'E') self.assertEqual(graph.nodes[e3]['label'], 'E') self.assertEqual(graph.nodes[e23]['label'], 'E') self.assertEqual(graph.nodes[e31]['label'], 'E') # if number of neighbors is unchanged # if each vertex has correct number of neighbors (based on neighbour interiors count) for n in [e0a, e1, e0b, e0c, e2, e12, e3, e23, e31]: node_neighbors = get_neighbors_at(graph, n, graph.nodes[n]['layer']) i_neighbors = [ x for x in node_neighbors if graph.nodes[x]['label'] == 'I' or graph.nodes[x]['label'] == 'i' ] e_neighbors = [ x for x in node_neighbors if graph.nodes[x]['label'] == 'E' or graph.nodes[x]['label'] == 'e' ] if len(e_neighbors) == len(i_neighbors): self.assertEqual(len(node_neighbors), len(i_neighbors) * 2) else: self.assertEqual(len(node_neighbors), (len(i_neighbors) * 2) + 1) # if vertices position is unchanged self.assertEqual(graph.nodes[e0a]['position'], (1.0, 1.0)) self.assertEqual(graph.nodes[e1]['position'], (1.0, 9.0)) self.assertEqual(graph.nodes[e0b]['position'], (9.0, 1.0)) self.assertEqual(graph.nodes[e0c]['position'], (9.0, 9.0)) self.assertEqual(graph.nodes[e2]['position'], (5.0, 5.0)) self.assertEqual(graph.nodes[e12]['position'], (3.0, 7.0)) self.assertEqual(graph.nodes[e3]['position'], (7.0, 7.0)) self.assertEqual(graph.nodes[e23]['position'], (6.0, 6.0)) self.assertEqual(graph.nodes[e31]['position'], (4.0, 8.0))