Exemple #1
0
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]
Exemple #2
0
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
Exemple #4
0
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