def test_get_span_complement(self): diag = Diagram([(1, 4), (2, 5), (3, 8), (6, 7)]) span = Span(4, 5) cspan = diag.get_span_complement(span) self.assertEqual(cspan, Span(1, 2)) ccspan = diag.get_span_complement(cspan) self.assertEqual(span, ccspan) # Double complement returns original
def check_diagram(sparse_diagram, ext_possible_chords, ext_min, ext_max): # Skip diagrams with 1, 2 or 3 moves compressed_diag = get_compressed_diagram(sparse_diagram) if (contains_one_move(compressed_diag) or contains_two_move(compressed_diag) or contains_three_move(compressed_diag)): return (sparse_diagram, [], []) # Find the permitted single chord extensions invariant_chords = get_invariant_chords_for_diagram( sparse_diagram, ext_possible_chords, diagram_filter=diagram_filter, doScale=False) if len(invariant_chords) == 0: # Skip diagrams with no invariant chords return (sparse_diagram, invariant_chords, []) # Test planarability of sparse_diag plus combinations of min..max chords planarable_extension_sets = [] for n_extensions in range(ext_min, ext_max+1): for extensions in combinations(invariant_chords, n_extensions): # Skip extension chord pair if they share any nodes uniq_nodes = {node for ext in extensions for node in ext} if len(uniq_nodes) != n_extensions * 2: continue diag = Diagram(sparse_diagram + list(extensions)) if diag.is_planarable(): planarable_extension_sets.append((timestamp(), extensions)) return (sparse_diagram, invariant_chords, planarable_extension_sets)
def diagram_filter(orig_sparse_diag, extension_chord, extended_sparse_diag): diag = Diagram(extended_sparse_diag) diag.compress() if (contains_one_move(diag) or contains_three_move(diag)): return False # Skip this diagram return True # Use this diagram
def check_123_planarable(diagram): # Skip diagrams with 1, 2 or 3 moves if (contains_one_move(diagram) or contains_two_move(diagram) or contains_three_move(diagram)): return (diagram, False) # Test planarability of sparse_diag diag = Diagram(diagram) rv = diag.is_planarable() return (diagram, rv)
def test_BoundaryTracker_get_regions_for_node(self): diag = Diagram([(1, 4), (2, 5), (3, 8), (6, 7)]) bounds = BoundaryTracker() region_factory = RegionFactory() outside = region_factory.get_next_region_id() bounds.add(Span(1, 8), outside, outside) # Initially all nodes outside # Add chord (1,4) regionA = region_factory.get_next_region_id() bounds.add(Span(1, 4), outside, regionA) # Add chord (2,5) - segment (4,5) regionB = region_factory.get_next_region_id() bounds.add(Span(4, 5), outside, regionB) bounds.add(Span(1, 2), regionA, regionB) self.assertEqual(([['A', 'B'], ['@', 'A']]), bounds.get_regions_for_node(2)) with self.assertRaisesRegexp( Exception, "get_regions_for_node: No boundary found containing node: 17"): bounds.get_regions_for_node(17)
def test_BoundaryTracker_get_spans_from_node(self): # Setup boundaries for 1st three chords in diagram diag = Diagram([(1, 4), (2, 5), (3, 8), (6, 7)]) bounds = BoundaryTracker() region_factory = RegionFactory() outside = region_factory.get_next_region_id() bounds.add(Span(1, 8), outside, outside) # Initially all nodes outside # Add chord (1,4) regionA = region_factory.get_next_region_id() bounds.add(Span(1, 4), outside, regionA) # Add chord (2,5) - segment (4,5) regionB = region_factory.get_next_region_id() bounds.add(Span(4, 5), outside, regionB) # Test available spans to close (4,5) regionB spans = bounds.get_spans_from_node(4, diag, 5) self.assertEqual(spans, [[1, 2]]) bounds.add(Span(1, 2), regionA, regionB) # Add chord (6, 7) (next in numeric order) span(6,7) # It's a 1-move loop, region is already closed regionC = region_factory.get_next_region_id() bounds.add(Span(6, 7), regionA, regionC) bounds.add(Span(5, 6), regionA, regionA) # Add chord(3, 8), span(7, 8) regionD = region_factory.get_next_region_id() bounds.add(Span(7, 8), regionA, regionD) # Test available spans to close (7,8) regionD spans = bounds.get_spans_from_node(7, diag, 8) self.assertEqual(spans, [[5, 6], [6, 7]])
def check_planarable_2move(diagram): # Scale up by 3 to leave 2 open nodes between each existing node diagx3 = Diagram(diagram) diagx3.scale(3) # Find parallel chord to each existing chord n_chords = diagx3.size() chords = [ get_parallel_extension(chord, n_chords*2*3) for chord in diagx3 ] n_extensions = n_chords # Only check with 1 extension per chord chord_combos = combinations(chords, n_extensions) for chord_combo in chord_combos: # Append this chord_combo to new copy of diagx3 test_diag = Diagram(diagx3) for chord in chord_combo: test_diag.append(chord) if test_diag.is_planarable(): return (diagram, test_diag, chord_combo) return (diagram, None, None)
def test_BoundaryTracker_validate_all_regions_closed_3_chord(self): "Verify regression on diagram: [(1, 2), (3, 6), (4, 5)]" diag = Diagram([(1, 2), (3, 6), (4, 5)]) bounds = BoundaryTracker() region_factory = RegionFactory() outside = region_factory.get_next_region_id() regionA = region_factory.get_next_region_id() regionB = region_factory.get_next_region_id() regionC = region_factory.get_next_region_id() bounds.add(Span(1, 6), outside, outside) bounds.add(Span(1, 2), outside, regionA) bounds.add(Span(4, 5), outside, regionB) bounds.add(Span(3, 4), outside, regionC) bounds.add(Span(5, 6), outside, regionC) self.assertTrue(bounds.validate_all_regions_closed(diag))
def test_BoundaryTracker_order_spans_in_closed_loop(self): diag = Diagram([(1, 4), (2, 5), (3, 8), (6, 7)]) spans = (Span(1, 2), Span(2, 3), Span(3, 4)) self.assertEqual( BoundaryTracker.order_spans_in_closed_loop(spans, diag), [[3, 4], [1, 2], [2, 3]]) spans = (Span(3, 4), Span(1, 2), Span(7, 8), Span(5, 6)) self.assertEqual( BoundaryTracker.order_spans_in_closed_loop(spans, diag), [[5, 6], [7, 8], [3, 4], [1, 2]]) spans = [Span(6, 7)] self.assertEqual( BoundaryTracker.order_spans_in_closed_loop(spans, diag), [[6, 7]]) spans = [Span(1, 2), Span(5, 6)] # Incomplete loop self.assertEqual( BoundaryTracker.order_spans_in_closed_loop(spans, diag), None) spans = [Span(1, 2), Span(4, 5), Span(2, 3)] # Loop plus extra span self.assertEqual( BoundaryTracker.order_spans_in_closed_loop(spans, diag), None)
def test_BoundaryTracker_get_spans_along_region(self): "Verify get_spans_along_region used as generator" diag = Diagram([[1, 8], [2, 9], [3, 12], [4, 7], [5, 10], [6, 11]]) bounds = BoundaryTracker() outside = bounds.region_factory.get_next_region_id() regionA = bounds.region_factory.get_next_region_id() regionB = bounds.region_factory.get_next_region_id() bounds.add(Span(1, 12), outside, outside) bounds.add(Span(4, 7), regionA, outside, Chord([4, 7])) bounds.add(Span(7, 8), regionB, outside, Chord([1, 8])) locator = outside new_region = regionB generator = bounds.gen_region_bounds(Span(7, 8), 8, locator, new_region, diag) expected = ( # Result 1: Simple region, closed on same side ({ '@_@': [[8, 12]], '@_A': [[4, 7]], '@_B': [[1, 4], [7, 8]] }, [[7, 8], [3, 4], [2, 3], [1, 2]]), # Result 2: Complex region, up and over the top ({ '@_@': [[8, 12]], '@_B': [[1, 4], [7, 8]], 'A_B': [[4, 7]] }, [[7, 8], [4, 5], [5, 6], [6, 7], [3, 4], [2, 3], [1, 2]])) count = 0 for (result_pair, expected_pair) in zip(generator, expected): count += 1 self.assertEqual(result_pair[0].boundaries, expected_pair[0]) self.assertEqual(result_pair[1], expected_pair[1]) self.assertEqual(count, 2)
def test_BoundaryTracker_validate_all_regions_closed(self): # Validate regions after adding boundaries for each chord diag = Diagram([(1, 4), (2, 5), (3, 8), (6, 7)]) bounds = BoundaryTracker() region_factory = RegionFactory() outside = region_factory.get_next_region_id() bounds.add(Span(1, 8), outside, outside) # Initially all nodes outside self.assertTrue(bounds.validate_all_regions_closed(diag)) # Add chord (1,4) regionA = region_factory.get_next_region_id() bounds.add(Span(1, 4), outside, regionA) self.assertTrue(bounds.validate_all_regions_closed(diag)) # Add chord (2,5) - segment (4,5) regionB = region_factory.get_next_region_id() bounds.add(Span(4, 5), outside, regionB) bounds.add(Span(1, 2), regionA, regionB) self.assertTrue(bounds.validate_all_regions_closed(diag)) # Add chord (6, 7) (next in numeric order) span(6,7) # It's a 1-move loop, region is already closed regionC = region_factory.get_next_region_id() bounds.add(Span(6, 7), regionA, regionC) bounds.add(Span(5, 6), regionA, regionA) self.assertTrue(bounds.validate_all_regions_closed(diag)) # Add chord(3, 8), span(7, 8) regionD = region_factory.get_next_region_id() bounds.add(Span(7, 8), regionA, regionD) self.assertFalse(bounds.validate_all_regions_closed(diag)) bounds.add(Span(5, 6), regionA, regionD) self.assertFalse(bounds.validate_all_regions_closed(diag)) bounds.add(Span(2, 3), outside, regionD) self.assertTrue(bounds.validate_all_regions_closed(diag))
def test_Diagram_is_planarable_5_chord_regression2(self): "Rotation of test 5_chord_regression1" # This is False diag = Diagram([[1, 7], [2, 3], [4, 9], [5, 8], [6, 10]]) self.assertFalse(diag.is_planarable())
def test_Diagram_is_planarable_5_chord_regression3(self): # This is True diag = Diagram([[1, 8], [2, 5], [3, 10], [4, 9], [6, 7]]) self.assertTrue(diag.is_planarable())
def test_Diagram_is_planarable_4_chord_test1(self): diag = Diagram([(1, 4), (2, 3), (5, 8), (6, 7)]) self.assertTrue(diag.is_planarable())
def test_Diagram_is_planarable_5_chord_regression1(self): diag = Diagram([(1, 2), (3, 8), (4, 7), (5, 9), (6, 10)]) self.assertFalse(diag.is_planarable())
def test_remove_one_move(self): diag = Diagram([(1, 6), (2, 3), (4, 7), (5, 8)]) diag.remove_one_moves() final_diag = Diagram([(1, 4), (2, 5), (3, 6)]) self.assertEqual(diag, final_diag)
def test_Diagram_is_planarable_4_chord_regression3(self): diag = Diagram([(1, 8), (2, 6), (3, 5), (4, 7)]) self.assertFalse(diag.is_planarable())
def test_Diagram_is_planarable_6_chord_regression3(self): diag = Diagram([[1, 4], [2, 5], [3, 12], [6, 9], [7, 11], [8, 10]]) self.assertFalse(diag.is_planarable())
def test_Diagram_is_planarable_21_chord_1(self): diag = Diagram([(1, 42), (2, 37), (3, 36), (4, 31), (5, 30), (6, 25), (7, 24), (8, 23), (9, 26), (10, 29), (11, 32), (12, 35), (13, 38), (14, 41), (15, 40), (16, 39), (17, 34), (18, 33), (19, 28), (20, 27), (21, 22)]) self.assertTrue(diag.is_planarable())
def test_Diagram_is_planarable_5_chord_regression4(self): # This is True diag = Diagram([[1, 3], [2, 10], [4, 7], [5, 8], [6, 9]]) self.assertFalse(diag.is_planarable())
def test_Diagram_is_planarable_3_chord_positive(self): diag = Diagram([(1, 2), (3, 6), (4, 5)]) self.assertTrue(diag.is_planarable())
def test_Diagram_is_planarable_7_chord(self): diag = Diagram([(1, 10), (2, 7), (3, 6), (4, 11), (5, 12), (13, 8), (14, 9)]) self.assertTrue(diag.is_planarable())
def test_Diagram_is_planarable_2_move_crossed(self): "Verify that the crossed 2-move fails in all rotations" for _ in range(0, 4): diag = Diagram([(1, 3), (2, 4)]) self.assertFalse(diag.is_planarable())
def test_Diagram_is_planarable_maindiag(self): diag = Diagram([(1, 4), (2, 5), (3, 8), (6, 7)]) self.assertTrue(diag.is_planarable())
def test_Diagram_is_planarable_6_chord_regression1(self): # This is True diag = Diagram([[1, 8], [2, 9], [3, 12], [4, 7], [5, 10], [6, 11]]) self.assertTrue(diag.is_planarable())
def test_Diagram_is_planarable_3_chord_regression4(self): 'Form region opposite the typical - but works - interesting' diag = Diagram([[1, 4], [6, 2], [3, 5]]) self.assertFalse(diag.is_planarable())
def test_Diagram_is_planarable_6_chord_regression4(self): diag = Diagram([[1, 10], [2, 7], [3, 6], [4, 13], [5, 12], [8, 11], [9, 14]]) self.assertTrue(diag.is_planarable())
def test_Diagram_is_planarable_4_chord_regression1(self): diag = Diagram([[1, 6], [2, 5], [3, 7], [4, 8]]) self.assertFalse(diag.is_planarable())
def test_Diagram_is_planarable_3_chord_regression1(self): diag = Diagram([(1, 4), (2, 6), (3, 5)]) self.assertFalse(diag.is_planarable())
def test_Diagram_is_planarable_4_chord_regression2(self): diag = Diagram([[1, 6], [2, 3], [4, 7], [5, 8]]) self.assertTrue(diag.is_planarable())