def get_parallel_extension(chord, n_nodes): '''Return a new chord that's parallel to the specified chord''' if chord_length(chord, n_nodes=n_nodes) == 1: raise Exception( "Cannot create parallel chord to chord with adjacent nodes: {}". format(chord)) return [chord[0] + 1, chord[1] - 1]
def diagram_filter(diagram): ''' Filter function that gets passed into gen_possible_diagrams to filter at generation time. The filter applies two basic tests: 1. Skip diagrams containing 2 or 3 moves 2. Skip if other-ends of chords with adjacent nodes are 1 or 2 nodes apart This test is known as the parallel with defect 3 test. Closure arguments: filter_two_moves: Filter out two moves when True filter_three_moves: Filter out three moves when True Arguments: diagram: Diagram to check. Assumption: diagram is compressed, i.e. all 1..2*n_chords nodes are part of a chord. Returns: True (keep diagram) if the diagram meets the requirements False (discard diagram) if the diagram fails either test Raises: None ''' # Allow access to globals set in main. Necessary with multiprocessing.Pool global filter_two_moves global filter_three_moves global max_parallel_defect # Remove diagram nodes with no chord compressed_diag = get_compressed_diagram(diagram) # Filter out 2 and 3 moves. One moves are pre-filtered in chord list if (filter_two_moves and contains_two_move(compressed_diag) or filter_three_moves and contains_three_move(compressed_diag)): return False # Skip diagram # Filter out parallel chords with defect chords_by_node = {node: chord for chord in diagram for node in chord} n_nodes = len(chords_by_node) for node1 in range(1, n_nodes + 1): node2 = node1 % n_nodes + 1 # Adjacent chord chord1 = chords_by_node[node1] chord2 = chords_by_node[node2] if chord_length( (get_other_node(chord1, node1), get_other_node(chord2, node2)), n_nodes) < max_parallel_defect: return False # Skip diagram return True # Keep diagram
def diagram_filter(diagram): # Skip diagrams with 2 or 3 moves # or if other ends of chords with adjacent nodes are too close # Filter out 2 and 3 moves. One moves are pre-filtered in chord list if (contains_two_move(diagram) or contains_three_move(diagram)): return False # Skip diagram # Filter out parallel chords with defect defect_length = 3 chords_by_node = { node:chord for chord in diagram for node in chord} n_nodes = len(chords_by_node) for node1 in range(1, n_nodes+1): node2 = node1 % n_nodes + 1 # Adjacent chord chord1 = chords_by_node[node1] chord2 = chords_by_node[node2] if chord_length((get_other_node(chord1, node1), get_other_node(chord2, node2)), n_nodes) < defect_length: return False # Skip diagram return True # Keep diagram
def main(argv): "Process command line arguments and kick things off" progname = argv[0].split('/')[-1] n_chords = 0 # Cmdline option '-n' scale = 1 # Default Cmdline option '-s' min_chord_length = 1 # Cmdline option '-l' print_status = 100000 # Cmdline option '-p' max_cpus = 1 # Default to single processing. Cmdline option '-c' block_size = 1 # Number of items in a block. block_item = 1 # Which item in block to process - trivial multinode support base_fname = "" # Output filename. Leading chord is '-#_#' appended to name global filter_one_moves global filter_two_moves global filter_three_moves global max_parallel_defect filter_one_moves = False filter_two_moves = False filter_three_moves = False max_parallel_defect = 1 # Parse command line options try: (opts, _) = getopt.getopt(argv[1:], "hn:s:l:p:c:b:i:f:123d:") except getopt.GetoptError as err: print >> sys.stderr, str(err) usage(progname) for opt, arg in opts: if opt == '-b': block_size = int(arg) elif opt == '-c': max_cpus = int(arg) elif opt == '-d': max_parallel_defect = int(arg) elif opt == '-f': base_fname = arg elif opt == '-h': usage(progname) elif opt == '-i': block_item = int(arg) elif opt == '-l': min_chord_length = int(arg) elif opt == '-n': n_chords = int(arg) elif opt == '-p': print_status = int(arg) elif opt == '-s': scale = int(arg) elif opt == '-1': filter_one_moves = True elif opt == '-2': filter_two_moves = True elif opt == '-3': filter_three_moves = True # Validate command line options if n_chords == 0: usage(progname, "Error: Missing required option: -n") if block_size <= 0: usage( progname, "Error: Block size must be greater than zero: {}".format( block_size)) if block_item <= 0: usage( progname, "Error: Block item must be greater than zero: {}".format( block_item)) if min_chord_length <= 0: usage( progname, "Error: Minimum chord length must be greater than zero: {}".format( min_chord_length)) if n_chords <= 0: usage( progname, "Error: Number of chords must be greater than zero: {}".format( n_chords)) if scale <= 0: usage(progname, "Error: Scale must be greater than zero: {}".format(scale)) if print_status <= 0: usage( progname, "Error: Scale must be greater than zero: {}".format(print_status)) if max_cpus < 0: usage( progname, "Error: Max number of CPUs must be zero or larger: {}".format( max_cpus)) if block_item > block_size: usage( progname, "Error: Block item ({}) must be in range 1..blocksize({})".format( block_item, block_size)) if filter_one_moves and min_chord_length < 2: min_chord_length = 2 # Honor filter_one_moves over min_chord_length if max_cpus == 0: max_cpus = cpu_count() # Default to using all CPUs # Create possible chords structure for base diagram diag_node_list = range(scale, n_chords * 2 * scale + 1, scale) diag_possible_chords = get_possible_chords(node_list=diag_node_list) # Remove chords that are too short, i.e. length less than min_chord_len possible_chords_filtered = [] for row in diag_possible_chords: new_row = [ chord for chord in row if min_chord_length <= chord_length(chord, n_nodes=n_chords * 2 * scale) ] if new_row: possible_chords_filtered.append(new_row) # Do the work print >> sys.stderr, "Generating all {}-chord diagrams".format(n_chords) gen_possible_diagrams(n_chords, possible_chords_filtered, diagram_filter=diagram_filter, print_status=print_status, max_cpus=max_cpus, base_fname=base_fname, block_size=block_size, block_item=block_item)
def chord_filter_len_2(chord): '''Goal: Filter length 2 chords. Filters return True to use a node, False to discard. Note: Uses closure for n_chords ''' return chord_length(chord, n_chords) != 2