コード例 #1
0
def test_exterior_boundaries(three_by_three_grid):
    graph = three_by_three_grid

    for i in [0, 1, 2, 3, 5, 6, 7, 8]:
        graph.nodes[i]["boundary_node"] = True
        graph.nodes[i]["boundary_perim"] = 2
    graph.nodes[4]["boundary_node"] = False

    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    updaters = {
        "exterior_boundaries": exterior_boundaries,
        "boundary_nodes": boundary_nodes,
    }
    partition = Partition(graph, assignment, updaters)

    result = partition["exterior_boundaries"]
    assert result[1] == 6 and result[2] == 10

    # 112    111
    # 112 -> 121
    # 222    222
    flips = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flips)

    result = new_partition["exterior_boundaries"]

    assert result[1] == 10 and result[2] == 6
コード例 #2
0
def test_exterior_boundaries_as_a_set(three_by_three_grid):
    graph = three_by_three_grid

    for i in [0, 1, 2, 3, 5, 6, 7, 8]:
        graph.nodes[i]['boundary_node'] = True
    graph.nodes[4]['boundary_node'] = False

    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    updaters = {
        'exterior_boundaries_as_a_set': exterior_boundaries_as_a_set,
        'boundary_nodes': boundary_nodes
    }
    partition = Partition(graph, assignment, updaters)

    result = partition['exterior_boundaries_as_a_set']
    assert result[1] == {0, 1, 3} and result[2] == {2, 5, 6, 7, 8}

    # 112    111
    # 112 -> 121
    # 222    222
    flips = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flips)

    result = new_partition['exterior_boundaries_as_a_set']

    assert result[1] == {0, 1, 2, 3, 5} and result[2] == {6, 7, 8}
コード例 #3
0
def merge_parts_chen(partition, k, dist_func, draw_map = False):
    #until there are k parts, merge adjacent parts with smallest sum
    assert (len(partition.parts) >= k)
    while len(partition.parts) > k:
        part_rand = random.choice(range(len(partition.parts)))
        # print(partition.centroids[part_rand])
        closest_part = (part_rand + 1) % len(partition.parts)
        dist_min = math.inf
        for e in partition["cut_edges"]:
            if partition.assignment[e[0]] == part_rand:
                i = partition.assignment[e[1]]
                dist_i = dist_func(partition.centroids[part_rand], partition.centroids[i])
                if dist_i < dist_min:
                    closest_part = i
                    dist_min = dist_i
            if partition.assignment[e[1]] == part_rand:
                i = partition.assignment[e[0]]
                dist_i = dist_func(partition.centroids[part_rand], partition.centroids[i])
                if dist_i < dist_min:
                    closest_part = i
                    dist_min = dist_i
        if draw_map:
            gdf_print_map(partition, './figures/iter_merge_'+str(len(partition.parts))+'.png', gdf, unit_key)
        merge_dict = {v:part_rand if partition.assignment[v] == closest_part else partition.assignment[v] for v in partition.graph.nodes()}
        partition = Partition(partition.graph, merge_dict, partition.updaters)
        keyshift = dict(zip(list(partition.parts.keys()), range(len(partition.parts.keys()))))
        keydict = {v:keyshift[partition.assignment[v]] for v in partition.graph.nodes()}
        partition = Partition(partition.graph, keydict, partition.updaters)
    return partition
コード例 #4
0
def merge_parts_smallest_sum_alt(partition, k):
    # print('start merge-parts')
    #until there are k parts, merge adjacent parts with smallest sum
    assert (len(partition.parts) >= k)
    neighbor_districts = {}
    for e in partition["cut_edges"]:
        pair = (min(partition.assignment[e[0]], partition.assignment[e[1]]),max(partition.assignment[e[0]], partition.assignment[e[1]]))
        neighbor_districts.update({pair:partition["population"][partition.assignment[e[0]]] + partition["population"][partition.assignment[e[1]]]})
    while len(partition.parts) > k:
        min_sum = min(neighbor_districts.values())
        min_key = [key for key in neighbor_districts.keys() if neighbor_districts[key] == min_sum][0]
        merge_dict = {v:min_key[0] if partition.assignment[v] == min_key[1] else partition.assignment[v] for v in partition.graph.nodes()}
        partition = Partition(partition.graph, merge_dict, partition.updaters)
        #update neighbor_districts
        new_dict = {}
        for key in neighbor_districts.keys():
            if key == min_key:
                continue
            elif key[0] == min_key[1]:
                new_key = (min(min_key[0], key[1]),max(min_key[0], key[1]))
            elif key[1] == min_key[1]:
                new_key = (min(min_key[0], key[0]),max(min_key[0], key[0]))
            elif min_key[0] in [key[0],key[1]]:
                new_key = key
            else:
                new_key = key
            new_val = partition["population"][new_key[0]] + partition["population"][new_key[1]]
            new_dict[new_key] = new_val
        neighbor_districts = new_dict
    keyshift = dict(zip(list(partition.parts.keys()), range(len(partition.parts.keys()))))
    keydict = {v:keyshift[partition.assignment[v]] for v in partition.graph.nodes()}
    return Partition(partition.graph, keydict, partition.updaters)
コード例 #5
0
def discontiguous_partition():
    graph = nx.Graph()
    graph.add_nodes_from(range(4))
    graph.add_edges_from([(0, 1), (1, 2), (2, 3)])
    partition = Partition(graph, {0: 0, 1: 1, 2: 1, 3: 0})

    # This flip will maintain discontiguity.
    partition.test_flips = {1: 0}
    return partition
コード例 #6
0
ファイル: test_tally.py プロジェクト: katiejolly/GerryChain
def test_data_tally_gives_expected_value(three_by_three_grid):
    assignment = {node: 1 for node in three_by_three_grid.nodes}
    data = {node: 1 for node in three_by_three_grid}
    updaters = {'tally': DataTally(data, alias='tally')}
    partition = Partition(three_by_three_grid, assignment, updaters)

    flip = {list(three_by_three_grid.nodes)[0]: 0}
    new_partition = partition.merge(flip)

    assert new_partition['tally'][1] == partition['tally'][1] - 1
コード例 #7
0
ファイル: test_tally.py プロジェクト: katiejolly/GerryChain
def test_data_tally_works_as_an_updater(three_by_three_grid):
    assignment = random_assignment(three_by_three_grid, 4)
    data = {node: random.randint(1, 100) for node in three_by_three_grid.nodes}
    updaters = {'tally': DataTally(data, alias='tally')}
    partition = Partition(three_by_three_grid, assignment, updaters)

    flip = {
        random.choice(list(partition.graph.nodes)): random.choice(range(4))
    }
    new_partition = partition.merge(flip)

    assert new_partition['tally']
コード例 #8
0
def test_implementation_of_cut_edges_matches_naive_method(three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    partition = Partition(graph, assignment)

    flip = {4: 2}
    new_partition = Partition(parent=partition, flips=flip)
    result = cut_edges(new_partition)

    naive_cut_edges = {
        edge
        for edge in graph.edges if new_partition.crosses_parts(edge)
    }

    assert edge_set_equal(result, naive_cut_edges)
コード例 #9
0
def seam_split_merge(partition1, partition2, k, ep, gdf, pop_col = 'TOTPOP'):
    #merged assignment (put 2 seed maps together along the random split line)
    subgraph_connect = False
    while not subgraph_connect:
        split_part = half_split(partition1, gdf)
        
        merge_assign = {n: partition1.assignment[n] if split_part.assignment[n] == 0 else partition2.assignment[n] for n in split_part.assignment.keys() }
        merge_part = Partition(split_part.graph, merge_assign, split_part.updaters)
        
        num_extra_parts = len(merge_part) - len(partition1)
        
        #districts cut/changed in map merging (i.e. districts eligible for merging/rebalancing)
        dists1 = [k for k in partition1.parts.keys() if k in merge_part.parts.keys()]
        dists2 = [k for k in partition2.parts.keys() if k in merge_part.parts.keys()]
        changed_dists1 = [k for k in dists1 if merge_part.parts[k] != partition1.parts[k]]
        changed_dists2 = [k for k in dists2 if merge_part.parts[k] != partition2.parts[k]]
        changed_dists = changed_dists1 + changed_dists2
        
        num_changed_dists = len(changed_dists)
        dists_to_make = num_changed_dists - num_extra_parts
        
        #lump together all nodes from districts that have been cut
        changed_nodes = []
        for l in changed_dists:
            changed_nodes = changed_nodes + list(merge_part.parts[l])
        
        change_part_assign = {n:1 if n in changed_nodes else 2 for n in split_part.assignment.keys()}
        seam_part = Partition(partition1.graph, change_part_assign, partition1.updaters)
                
         #check if "seam" subgraph is connected, if not, resplit the state and start again
        subgraph = split_part.graph.subgraph(changed_nodes)
        subgraph_connect = nx.is_connected(subgraph)
        
        
        #want graph of just nodes in changed/cut districts
    subgraph_pop = sum([subgraph.nodes[l][pop_col] for l in changed_nodes])
    ideal_subgraph_pop = subgraph_pop/dists_to_make

    #gets stuck here
    
    new_dists_assign0 = recursive_tree_part(subgraph, range(dists_to_make), ideal_subgraph_pop, pop_col, ep, node_repeats = 5) #prob not here, if bad seam, num node repeats wont help
    new_dists_assign = {n: (new_dists_assign0[n] + 2*k) for n in new_dists_assign0.keys()}
 
    final_assign = {d: merge_assign[d] if d not in changed_nodes else new_dists_assign[d] for d in split_part.assignment.keys()}  
    
    return Partition(partition1.graph, final_assign, partition1.updaters), split_part, merge_part, seam_part
               
          
コード例 #10
0
def half_half(partitionA, partitionB, half_pop, pop_col="TOTPOP"):
    # print('start half-half')
    half_assign = recursive_tree_part(partitionA.graph, range(2), half_pop,
                                      pop_col, .02, 3)
    half_part = Partition(partitionA.graph, half_assign, partitionA.updaters)
    V0 = [v for v in partitionA.graph.nodes() if half_assign[v] == 0]
    V1 = [v for v in partitionA.graph.nodes() if half_assign[v] == 1]
    A_split = common_refinement(partitionA, half_part)
    B_split = common_refinement(partitionB, half_part)

    assignmentA0 = {v: A_split.assignment[v] for v in V0}
    assignmentA1 = {v: A_split.assignment[v] for v in V1}
    assignmentB0 = {v: B_split.assignment[v] for v in V0}
    assignmentB1 = {v: B_split.assignment[v] for v in V1}

    mapA0 = {
        i[0]: i[1]
        for i in zip(list(set(assignmentA0.values())), range(len(
            assignmentA0)))
    }
    mapB1 = {
        i[0]: i[1] + len(mapA0)
        for i in zip(list(set(assignmentB1.values())), range(len(
            assignmentB1)))
    }
    mapA1 = {
        i[0]: i[1]
        for i in zip(list(set(assignmentA1.values())), range(len(
            assignmentA1)))
    }
    mapB0 = {
        i[0]: i[1] + len(mapA1)
        for i in zip(list(set(assignmentB0.values())), range(len(
            assignmentB0)))
    }

    assignmentA0B1 = {}
    assignmentA1B0 = {}
    for v in V0:
        assignmentA0B1[v] = mapA0[assignmentA0[v]]
        assignmentA1B0[v] = mapB0[assignmentB0[v]]
    for v in V1:
        assignmentA0B1[v] = mapB1[assignmentB1[v]]
        assignmentA1B0[v] = mapA1[assignmentA1[v]]
    return Partition(partitionA.graph, assignmentA0B1,
                     partitionA.updaters), Partition(partitionA.graph,
                                                     assignmentA1B0,
                                                     partitionA.updaters)
コード例 #11
0
def test_perimeter(three_by_three_grid):
    graph = three_by_three_grid
    for i in [0, 1, 2, 3, 5, 6, 7, 8]:
        graph.nodes[i]["boundary_node"] = True
        graph.nodes[i]["boundary_perim"] = 1
    graph.nodes[4]["boundary_node"] = False

    for edge in graph.edges:
        graph.edges[edge]["shared_perim"] = 1

    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    updaters = {
        "exterior_boundaries": exterior_boundaries,
        "interior_boundaries": interior_boundaries,
        "cut_edges_by_part": cut_edges_by_part,
        "boundary_nodes": boundary_nodes,
        "perimeter": perimeter,
    }
    partition = Partition(graph, assignment, updaters)

    # 112
    # 112
    # 222

    result = partition["perimeter"]

    assert result[1] == 3 + 4  # 3 nodes + 4 edges
    assert result[2] == 5 + 4  # 5 nodes + 4 edges
コード例 #12
0
def test_Partition_can_update_stats():
    graph = networkx.complete_graph(3)
    assignment = {0: 1, 1: 1, 2: 2}

    graph.nodes[0]["stat"] = 1
    graph.nodes[1]["stat"] = 2
    graph.nodes[2]["stat"] = 3

    updaters = {"total_stat": Tally("stat", alias="total_stat")}

    partition = Partition(graph, assignment, updaters)
    assert partition["total_stat"][2] == 3
    flip = {1: 2}

    new_partition = partition.flip(flip)
    assert new_partition["total_stat"][2] == 5
コード例 #13
0
def test_Partition_can_update_stats():
    graph = networkx.complete_graph(3)
    assignment = {0: 1, 1: 1, 2: 2}

    graph.nodes[0]['stat'] = 1
    graph.nodes[1]['stat'] = 2
    graph.nodes[2]['stat'] = 3

    updaters = {'total_stat': Tally('stat', alias='total_stat')}

    partition = Partition(graph, assignment, updaters)
    assert partition['total_stat'][2] == 3
    flip = {1: 2}

    new_partition = partition.merge(flip)
    assert new_partition['total_stat'][2] == 5
def initial_partition(disc):

    updaters = {
        'population': Tally('population'),
        'base': new_base,
        'b_nodes': b_nodes_bi,
        'cut_edges': cut_edges,
        "boundary": bnodes_p,
        'step_num': step_num,
        'geom': geom_wait,
    }

    assignment = {}
    for x in disc.nodes():

        if x[0] > 0:
            assignment[x] = 1
        else:
            assignment[x] = -1

    #b_nodes = {(x[0], partition.assignment[x[1]]) for x in partition["cut_edges"]}.union({(x[1], partition.assignment[x[0]]) for x in partition["cut_edges"]})

    partition = Partition(disc, assignment, updaters=updaters)

    return partition
コード例 #15
0
def merge_parts_smallest_sum(partition, k):
    #until there are k parts, merge adjacent parts with smallest sum
    assert (len(partition.parts) >= k)
    while len(partition.parts) > k:
        min_pair = (partition.assignment[list(partition["cut_edges"])[0][0]],partition.assignment[list(partition["cut_edges"])[0][1]])
        min_sum = math.inf
        for e in partition["cut_edges"]:
            edge_sum = partition["population"][partition.assignment[e[0]]] + partition["population"][partition.assignment[e[1]]]
            if  edge_sum < min_sum:                
                min_sum = edge_sum
                min_pair = (partition.assignment[e[0]], partition.assignment[e[1]])
        merge_dict = {v:min_pair[0] if partition.assignment[v] == min_pair[1] else partition.assignment[v] for v in partition.graph.nodes()}
        partition = Partition(partition.graph, merge_dict, partition.updaters)
    keyshift = dict(zip(list(partition.parts.keys()), range(len(partition.parts.keys()))))
    keydict = {v:keyshift[partition.assignment[v]] for v in partition.graph.nodes()}
    return Partition(partition.graph, keydict, partition.updaters)
コード例 #16
0
def test_perimeter(three_by_three_grid):
    graph = three_by_three_grid
    for i in [0, 1, 2, 3, 5, 6, 7, 8]:
        graph.nodes[i]['boundary_node'] = True
        graph.nodes[i]['boundary_perim'] = 1
    graph.nodes[4]['boundary_node'] = False

    for edge in graph.edges:
        graph.edges[edge]['shared_perim'] = 1

    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    updaters = {
        'exterior_boundaries': exterior_boundaries,
        'interior_boundaries': interior_boundaries,
        'cut_edges_by_part': cut_edges_by_part,
        'boundary_nodes': boundary_nodes,
        'perimeter': perimeter
    }
    partition = Partition(graph, assignment, updaters)

    # 112
    # 112
    # 222

    result = partition['perimeter']

    assert result[1] == 3 + 4  # 3 nodes + 4 edges
    assert result[2] == 5 + 4  # 5 nodes + 4 edges
コード例 #17
0
def test_cut_edges_doesnt_duplicate_edges_with_different_order_of_nodes(
        three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    partition = Partition(graph, assignment)
    # 112    111
    # 112 -> 121
    # 222    222
    flip = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flip)

    result = new_partition['cut_edges']

    for edge in result:
        assert (edge[1], edge[0]) not in result
コード例 #18
0
def metamander_around_partition(graph, dual, target_partition, tag):
    updaters = {'population': Tally('population'),
                        'cut_edges': cut_edges,
                        'step_num': step_num,
                        }
    
    assignment = {}
    for x in graph.nodes():
        color = 0
        for block in target_partition.keys():
            if x in target_partition[block]:
                assignment[x] = color
            color += 1
    
    target_partition = Partition(graph, assignment, updaters = updaters)
    plt.figure()
    
    viz(graph, set([]), target_partition.parts)
    plt.savefig("./plots/target_map" + tag + ".png", format = 'png')
    plt.close()
    
    print("made partition")
    crosses = compute_cross_edge(graph, target_partition)
    
    k = len(target_partition.parts)
    
    dual_crosses = []
    for edge in dual.edges:
        if dual.edges[edge]["original_name"] in crosses:
            dual_crosses.append(edge)
            
    print("making dual distances")
    dual = distance_from_partition(dual, dual_crosses)
    print('finished making dual distances')
    special_faces = assign_special_faces(dual,2)
    print('finished assigning special faces')
    g_sierpinsky = face_sierpinski_mesh(graph, special_faces)
    print("made metamander")
    # change from RVAP and UVAP to approprate election data columns 
    for node in g_sierpinsky:
        g_sierpinsky.nodes[node]['C_X'] = g_sierpinsky.nodes[node]['pos'][0]
        g_sierpinsky.nodes[node]['C_Y'] = g_sierpinsky.nodes[node]['pos'][1]
        if 'population' not in g_sierpinsky.nodes[node]:
            g_sierpinsky.nodes[node]['population'] = 0
        if 'EL16G_PR_D' not in g_sierpinsky.nodes[node]:
            g_sierpinsky.nodes[node]['EL16G_PR_D'] = 0
        if 'EL16G_PR_R' not in g_sierpinsky.nodes[node]:
            g_sierpinsky.nodes[node]['EL16G_PR_R'] = 0
        ##Need to add the voting data
    total_pop = sum( [ g_sierpinsky.nodes[node]['population'] for node in g_sierpinsky])
    
    #sierp_partition = build_trivial_partition(g_sierpinsky)
    
    plt.figure()
    nx.draw(g_sierpinsky, pos=nx.get_node_attributes(g_sierpinsky, 'pos'), node_size = 1, width = 1, cmap=plt.get_cmap('jet'))
    plt.savefig("./plots/sierpinsky_mesh.png", format='png')
    plt.close()
    
    left_mander, right_mander = produce_sample(g_sierpinsky, k , tag)
コード例 #19
0
ファイル: test_validity.py プロジェクト: mggg/GerryChain
def discontiguous_partition_with_flips():
    graph = nx.Graph()
    graph.add_nodes_from(range(4))
    graph.add_edges_from([(0, 1), (1, 2), (2, 3)])
    partition = Partition(Graph.from_networkx(graph), {0: 0, 1: 1, 2: 1, 3: 0})

    # This flip will maintain discontiguity.
    return partition, {1: 0}
コード例 #20
0
def shift_part_keys(partition):
    #get final partition to have parts in 0 indexed range of # total parts
    final_values = list(set(dict(partition.assignment).values()))
    final_assign = {}
    for key, value in dict(partition.assignment).items():
        final_assign[key] = final_values.index(partition.assignment[key])

    return Partition(partition.graph, final_assign, partition.updaters)
コード例 #21
0
def contiguous_partition_with_flips():
    graph = nx.Graph()
    graph.add_nodes_from(range(4))
    graph.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)])
    partition = Partition(graph, {0: 0, 1: 1, 2: 1, 3: 0})

    # This flip will maintain contiguity.
    return partition, {0: 1}
コード例 #22
0
def build_balanced_k_partition(graph, k, pop_col, pop_target, epsilon):
    
    assignment = recursive_tree_part(graph, k, pop_target, pop_col, epsilon)
    updaters = {'population': Tally('population'),
                        'cut_edges': cut_edges,
                        'step_num': step_num,
                        }
    partition = Partition(graph, assignment=assignment, updaters=updaters)
    return partition
コード例 #23
0
def tiled_recom(partition1, partition2, verbose=False):
    remaining_nodes = set(partition1.graph.nodes)
    tile_assign = {}
    highest_key = len(partition1) - 1

    while len(remaining_nodes) > 0:
        random_node = random.sample(remaining_nodes, 1)[0]
        part_choice = random.choice([partition1, partition2])
        part_choice_name = '1' if part_choice == partition1 else '2'
        assigned_dist = part_choice.assignment[random_node]
        other_nodes_in_dist = set([
            n for n in remaining_nodes
            if part_choice.assignment[n] == assigned_dist
        ])

        if verbose:
            print("node", random_node, "part", part_choice_name,
                  "assigned dist", assigned_dist)
            print("len other nodes", len(other_nodes_in_dist),
                  "len part's dist", len(part_choice.parts[assigned_dist]))

        if len(other_nodes_in_dist) == len(part_choice.parts[assigned_dist]):
            highest_key += 1
            for node in other_nodes_in_dist:
                tile_assign[node] = highest_key
            remaining_nodes = remaining_nodes.difference(other_nodes_in_dist)

        else:
            part_choice = partition2 if part_choice == partition1 else partition1
            assigned_dist = part_choice.assignment[random_node]
            part_choice_name = '1' if part_choice == partition1 else '2'
            other_nodes_in_dist = set([
                n for n in remaining_nodes
                if part_choice.assignment[n] == assigned_dist
            ])

            if verbose:
                print("node", random_node, "ALT part", part_choice_name,
                      "ALT assigned dist", assigned_dist)
                print("len other nodes", len(other_nodes_in_dist),
                      "len part's dist", len(part_choice.parts[assigned_dist]))

            if len(other_nodes_in_dist) == len(
                    part_choice.parts[assigned_dist]):
                highest_key += 1
                for node in other_nodes_in_dist:
                    tile_assign[node] = highest_key
                remaining_nodes = remaining_nodes.difference(
                    other_nodes_in_dist)

            else:
                if verbose:
                    print("lone node!")
                tile_assign[random_node] = 1000
                remaining_nodes = remaining_nodes.difference({random_node})

    return Partition(partition1.graph, tile_assign, partition1.updaters)
コード例 #24
0
def test_cut_edges_can_handle_multiple_flips(three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    partition = Partition(graph, assignment)
    # 112    111
    # 112 -> 121
    # 222    222
    flip = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flip)

    result = new_partition['cut_edges']

    naive_cut_edges = {
        tuple(sorted(edge))
        for edge in graph.edges if new_partition.crosses_parts(edge)
    }
    assert result == naive_cut_edges
コード例 #25
0
def test_cut_edges_by_part_doesnt_duplicate_edges_with_opposite_order_of_nodes(
        three_by_three_grid):
    graph = three_by_three_grid
    assignment = {0: 1, 1: 1, 2: 2, 3: 1, 4: 1, 5: 2, 6: 2, 7: 2, 8: 2}
    updaters = {'cut_edges_by_part': cut_edges_by_part}
    partition = Partition(graph, assignment, updaters)
    # 112    111
    # 112 -> 121
    # 222    222
    flip = {4: 2, 2: 1, 5: 1}

    new_partition = Partition(parent=partition, flips=flip)

    result = new_partition['cut_edges_by_part']

    for part in result:
        for edge in result[part]:
            assert (edge[1], edge[0]) not in result
コード例 #26
0
def main(config_data, id):
    try:
        timeBeg = time.time()
        print('Experiment', id, 'has begun')
        # Save configuration into global variable
        global config
        config = config_data

        graph = Graph.from_json(config['INPUT_GRAPH_FILENAME'])

        # List of districts in original graph
        parts = list(
            set([
                graph.nodes[node][config['ASSIGN_COL']]
                for node in graph.nodes()
            ]))
        # Ideal population of districts
        ideal_pop = sum(
            [graph.nodes[node][config['POP_COL']]
             for node in graph.nodes()]) / len(parts)

        election = Election(config['ELECTION_NAME'], {
            'PartyA': config['PARTY_A_COL'],
            'PartyB': config['PARTY_B_COL']
        })

        updaters = {
            'population': Tally(config['POP_COL']),
            'cut_edges': cut_edges,
            config['ELECTION_NAME']: election
        }

        partDict = recursive_tree_part(graph, parts, ideal_pop,
                                       config['POP_COL'], config['EPSILON'],
                                       config['NODE_REPEATS'])
        for node in graph.nodes():
            graph.nodes[node][config['ASSIGN_COL']] = partDict[node]
        part = Partition(graph=graph,
                         assignment=config['ASSIGN_COL'],
                         updaters=updaters)
        for len_ in config['RUN_LENGTHS']:
            for num in range(config['RUNS_PER_LEN']):
                run_chain(part, config['CHAIN_TYPE'], len_, ideal_pop,
                          '{}_{}_{}_{}'.format(config['TAG'], id, len_, num))

        print('Experiment {} completed in {} seconds'.format(
            id,
            time.time() - timeBeg))

    except Exception as e:
        # Print notification if any experiment fails to complete
        track = traceback.format_exc()
        print(track)
        print('Experiment {} failed to complete after {:.2f} seconds'.format(
            id,
            time.time() - timeBeg))
コード例 #27
0
def test_tally_multiple_columns(graph_with_d_and_r_cols):
    graph = graph_with_d_and_r_cols

    updaters = {'total': Tally(['D', 'R'], alias='total')}
    assignment = {i: 1 if i in range(4) else 2 for i in range(9)}

    partition = Partition(graph, assignment, updaters)
    expected_total_in_district_one = sum(
        graph.nodes[i]['D'] + graph.nodes[i]['R'] for i in range(4))
    assert partition['total'][1] == expected_total_in_district_one
コード例 #28
0
def merge_small_neighbor(partition,k):
    #finds smallest district in map and merges with its smallest neighbor (by population)
    #repeats until k dists reached
    merged_assign = dict(partition.assignment)
    cut_edge_list = list(partition["cut_edges"])
    while len(partition) > k:  
        smallest_pop_dist = min(partition["population"], key= partition["population"].get)
        dist_edges = [e for e in cut_edge_list for z in [0,1] if partition.assignment[e[z]] == smallest_pop_dist]
        neighbor_dists= list(np.unique([partition.assignment[e[z]] for z in [0,1] for e in dist_edges] ))
        neighbor_dists.remove(smallest_pop_dist)
        neighbor_pops = {q: partition["population"][q] for q in neighbor_dists}
        neighbor_smallest_pop = min(neighbor_pops, key=neighbor_pops.get)  

        for n in partition.parts[smallest_pop_dist]:
            merged_assign[n] = neighbor_smallest_pop
        
        partition = Partition(partition.graph, merged_assign, partition.updaters)
    
    return Partition(partition.graph, merged_assign, partition.updaters)
コード例 #29
0
def half_split(partition, gdf, pop_col="TOTPOP"):
    tot_pop = sum(
        [partition.graph.nodes[v][pop_col] for v in partition.graph.nodes()])
    rand_split_assign = recursive_tree_part(partition.graph, range(2),
                                            tot_pop / 2, pop_col, .01, 3)

    return Partition(partition.graph, rand_split_assign, partition.updaters)


################################  testing ########################################
コード例 #30
0
def test_tally_multiple_columns(graph_with_d_and_r_cols):
    graph = graph_with_d_and_r_cols

    updaters = {"total": Tally(["D", "R"], alias="total")}
    assignment = {i: 1 if i in range(4) else 2 for i in range(9)}

    partition = Partition(graph, assignment, updaters)
    expected_total_in_district_one = sum(
        graph.nodes[i]["D"] + graph.nodes[i]["R"] for i in range(4))
    assert partition["total"][1] == expected_total_in_district_one