예제 #1
0
def yosupo_bi_match() -> None:
    # https://judge.yosupo.jp/problem/bipartitematching
    import scipy
    major, minor, _ = map(int, scipy.version.full_version.split('.'))
    if major < 1 or (major == 1 and minor < 4):
        raise RuntimeError
    L, R, M = map(int, input().split())
    sink, source = L + R, L + R + 1
    in_, out = [], []
    edges = []
    for _ in range(M):
        a, b = map(int, input().split())
        in_.append(a)
        out.append(b + L)
        edges.append((a, b + L))
    for i in range(L):
        in_.append(source)
        out.append(i)
        edges.append((i, source))
    for i in range(R):
        in_.append(i + L)
        out.append(sink)
        edges.append((i + L, sink))
    edges.sort()
    graph = csr_matrix((np.ones(L + R + M, dtype=int), (in_, out)),
                       shape=(L + R + M, L + R + M))
    flow = maximum_flow(graph, source, sink)
    ans = []
    for (fr, to), val in zip(edges, flow.residual.data):
        if 0 <= fr < L and L <= to < L + R and val == 1:
            ans.append((fr, to - L))
    print(flow.flow_value)
    print("\n".join(f"{v1} {v2}" for v1, v2 in ans))
def test_ford_fulkerson():
    """
    最大ノード数 M, 最大重み M, 最大辺数ノード数 * 2 で重み付き逆平行有向グラフをランダム作成することを Iteration 回行う。
    それぞれに対し、ソースとシンクを選んでフローを流すことをノード数だけ行い、scipy.sparse.csgraph.maximum_flow と結果を照合するストレステストを行う。
    """
    Iteration = 20
    M = 20
    for _ in range(Iteration):
        n = randint(2, M)

        # ---- ndarray, csr_matrix, エッジを張った FordFulkerson インスタンス生成 ----
        mat = np.full((n, n), 0)
        for _ in range(2 * n):  # 最大で 2 * n 個辺を張る
            a, b = randint(0, n - 1), randint(0, n - 1)
            if a == b:  # 自己ループはだめ
                continue
            if mat[b, a] == 0:  # 逆平行有向グラフにしたいので
                mat[a, b] = randint(1, M)  # 上書きすることも多々あるだろう
        G = csr_matrix(mat)
        FF = FordFulkerson(n)
        for i in range(n):
            for j in range(n):
                if mat[i, j] != 0:
                    assert i != j
                    assert mat[j, i] == 0
                    FF.add_edge(i, j, mat[i, j])

        # ---- source, sink を決定しフローを流して比較 ----
        for i in range(n):
            while True:
                source, sink = randint(0, n - 1), randint(0, n - 1)
                if source != sink:
                    break
            # ford_fulkerson をチェック
            if i % 2 == 0:
                expected_max_flow = cs.maximum_flow(G, source, sink).flow_value
                state = FF.reserve_state()
                got_max_flow = FF.ford_fulkerson(source, sink)
                assert got_max_flow == expected_max_flow
                FF.restore_state(state)
            # edmonds_karp をチェック
            else:
                expected_max_flow = cs.maximum_flow(G, source, sink).flow_value
                state = FF.reserve_state()
                got_max_flow = FF.edmonds_karp(source, sink)
                assert got_max_flow == expected_max_flow
                FF.restore_state(state)
def find_flow_and_split(top_level_indices, graph_rep_array, n_1, n_2,
                        classifier_probs):
    sink_idx = n_1 + n_2 + 1
    top_level_indices_1 = None
    top_level_indices_2 = None
    #Create subgraph from index array provided
    graph_rep_curr = graph_rep_array[top_level_indices]
    graph_rep_curr = graph_rep_curr[:, top_level_indices]
    graph_rep_curr, n_1_curr, n_2_curr = graph_rescale(graph_rep_curr,
                                                       top_level_indices, n_1,
                                                       n_2)
    graph_curr = csr_matrix(graph_rep_curr)
    flow_curr = maximum_flow(graph_curr, 0, len(top_level_indices) - 1)
    # Checking if full flow occurred, so no need to split
    if flow_curr.flow_value == n_1_curr * n_2_curr:
        set_classifier_prob_full_flow(top_level_indices, n_1_curr, n_2_curr,
                                      sink_idx, classifier_probs)
        return top_level_indices_1, top_level_indices_2, flow_curr
    elif flow_curr.flow_value == 0:
        set_classifier_prob_no_flow(top_level_indices, sink_idx, n_1,
                                    classifier_probs)
        return top_level_indices_1, top_level_indices_2, flow_curr
    # Finding remaining capacity edges
    remainder_array = graph_curr - flow_curr.residual

    rev_edge_ptr, tails = _make_edge_pointers(remainder_array)

    edge_ptr = remainder_array.indptr
    capacities = remainder_array.data
    heads = remainder_array.indices

    edge_list_curr = find_remaining_cap_edges(edge_ptr, capacities, heads,
                                              tails, 0,
                                              len(top_level_indices) - 1)

    #     print(edge_list_curr)
    gz_idx = []
    for item in edge_list_curr:
        gz_idx.append(item[0])
        gz_idx.append(item[1])
    if len(gz_idx) > 0:
        gz_idx = np.array(gz_idx)
        gz_idx_unique = np.unique(gz_idx)
        top_level_gz_idx = top_level_indices[gz_idx_unique]
        top_level_gz_idx = np.insert(top_level_gz_idx, len(top_level_gz_idx),
                                     sink_idx)
        top_level_indices_1 = top_level_gz_idx
    else:
        top_level_gz_idx = np.array([0, sink_idx])
    # Indices without flow
    top_level_z_idx = np.setdiff1d(top_level_indices, top_level_gz_idx)
    if len(top_level_z_idx) > 0:
        # Add source and sink back to zero flow idx array
        top_level_z_idx = np.insert(top_level_z_idx, 0, 0)
        top_level_z_idx = np.insert(top_level_z_idx, len(top_level_z_idx),
                                    sink_idx)
        top_level_indices_2 = top_level_z_idx

    return top_level_indices_1, top_level_indices_2, flow_curr
예제 #4
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_simple_graph(method):
    # This graph looks as follows:
    #     (0) --5--> (1)
    graph = csr_matrix([[0, 5], [0, 0]])
    res = maximum_flow(graph, 0, 1, method=method)
    assert res.flow_value == 5
    expected_flow = np.array([[0, 5], [-5, 0]])
    assert_array_equal(res.flow.toarray(), expected_flow)
예제 #5
0
파일: test_flow.py 프로젝트: mhwende/scipy
def test_simple_graph(dfs):
    # This graph looks as follows:
    #     (0) --5--> (1)
    graph = csr_matrix([[0, 5], [0, 0]])
    res = maximum_flow(graph, 0, 1, dfs=dfs)
    assert res.flow_value == 5
    expected_residual = np.array([[0, 5], [-5, 0]])
    assert_array_equal(res.residual.toarray(), expected_residual)
예제 #6
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_bottle_neck_graph(method):
    # This graph cannot use the full capacity between 0 and 1:
    #     (0) --5--> (1) --3--> (2)
    graph = csr_matrix([[0, 5, 0], [0, 0, 3], [0, 0, 0]])
    res = maximum_flow(graph, 0, 2, method=method)
    assert res.flow_value == 3
    expected_flow = np.array([[0, 3, 0], [-3, 0, 3], [0, -3, 0]])
    assert_array_equal(res.flow.toarray(), expected_flow)
예제 #7
0
def _part_two(data):
    """
    Once again solve a matching problem with
    maxflow
    """

    c = _parse_allergens(data)

    allergens = sorted(c.keys())
    ingredients = set()
    for r in c.values():
        ingredients.update(r)
    ingredients = list(ingredients)

    print(allergens)
    print(ingredients)

    assert len(ingredients) == len(allergens)

    N = 1 + len(ingredients) + len(allergens) + 1

    def a_index(a):
        return 1 + a

    def i_index(i):
        return 1 + len(allergens) + i

    C = np.zeros([N, N], dtype=int)
    src = 0
    snk = N - 1
    for a, alg in enumerate(allergens):
        C[src, a_index(a)] = 1  # src to left side
        print(a, alg, c[alg])
        for ing in c[alg]:
            i = ingredients.index(ing)
            C[a_index(a), i_index(i)] = 1

    for i in range(len(ingredients)):
        C[i_index(i), snk] = 1  # rhs to sink

    print(C)

    result = maximum_flow(csr_matrix(C), src, snk)

    assert result.flow_value == len(ingredients), result

    print(f"flow_value: {result.flow_value}")

    answer = []
    for a, alg in enumerate(allergens):
        for ing in c[alg]:
            i = ingredients.index(ing)
            if result.residual[a_index(a), i_index(i)] == 1:
                answer.append(ing)
                break

    return ','.join(answer)
예제 #8
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_disconnected_graph(method):
    # This tests the following disconnected graph:
    #     (0) --5--> (1)    (2) --3--> (3)
    graph = csr_matrix([[0, 5, 0, 0], [0, 0, 0, 0], [0, 0, 9, 3], [0, 0, 0,
                                                                   0]])
    res = maximum_flow(graph, 0, 3, method=method)
    assert res.flow_value == 0
    expected_flow = np.zeros((4, 4), dtype=np.int32)
    assert_array_equal(res.flow.toarray(), expected_flow)
예제 #9
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_add_reverse_edges_large_graph(method):
    # Regression test for https://github.com/scipy/scipy/issues/14385
    n = 100_000
    indices = np.arange(1, n)
    indptr = np.array(list(range(n)) + [n - 1])
    data = np.ones(n - 1, dtype=np.int32)
    graph = csr_matrix((data, indices, indptr), shape=(n, n))
    res = maximum_flow(graph, 0, n - 1, method=method)
    assert res.flow_value == 1
    expected_flow = graph - graph.transpose()
    assert_array_equal(res.flow.data, expected_flow.data)
    assert_array_equal(res.flow.indices, expected_flow.indices)
    assert_array_equal(res.flow.indptr, expected_flow.indptr)
예제 #10
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_example_from_clrs_chapter_26_1(method):
    # See page 659 in CLRS second edition, but note that the maximum flow
    # we find is slightly different than the one in CLRS; we push a flow of
    # 12 to v_1 instead of v_2.
    graph = csr_matrix([[0, 16, 13, 0, 0, 0], [0, 0, 10, 12, 0, 0],
                        [0, 4, 0, 0, 14, 0], [0, 0, 9, 0, 0, 20],
                        [0, 0, 0, 7, 0, 4], [0, 0, 0, 0, 0, 0]])
    res = maximum_flow(graph, 0, 5, method=method)
    assert res.flow_value == 23
    expected_flow = np.array([[0, 12, 11, 0, 0, 0], [-12, 0, 0, 12, 0, 0],
                              [-11, 0, 0, 0, 11, 0], [0, -12, 0, 0, -7, 19],
                              [0, 0, -11, 7, 0, 4], [0, 0, 0, -19, -4, 0]])
    assert_array_equal(res.flow.toarray(), expected_flow)
def solve_for_row_and_column_sums(row_sums, col_sums):
    """
    applies the max flow algorithm for matrix rounding
    
    """
    
    m = len(row_sums)    
    n = len(col_sums)
    
    # produce a sparse matrix object and solve
    graph = csr_matrix(prod_target_matrix(row_sums, col_sums))
    
    solution = maximum_flow(graph, 0, m+n+1).residual.toarray()[1:(m+1), (m+1):(m+n+1)]
    
    return solution
예제 #12
0
def scipy_maxflow(G: nx.DiGraph, s, t, capacity='capacity', **kwargs):
    cap = nx.get_edge_attributes(G, capacity)
    edges = G.edges
    cap = [cap[e] for e in edges]

    edges = np.array(edges)
    sparse_G = csr_matrix((cap, (edges[:, 0], edges[:, 1])),
                          shape=(edges.max() + 1, ) * 2)

    res = csgraph.maximum_flow(sparse_G, s, t)

    R = nx.algorithms.flow.utils.build_residual_network(G, 'capacity')
    R.graph['flow_value'] = res.flow_value
    residual = res.residual

    for i, j in R.edges:
        R[i][j]['flow'] = residual[i, j]

    return R
예제 #13
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_backwards_flow(method):
    # This example causes backwards flow between vertices 3 and 4,
    # and so this test ensures that we handle that accordingly. See
    #     https://stackoverflow.com/q/38843963/5085211
    # for more information.
    graph = csr_matrix([[0, 10, 0, 0, 10, 0, 0, 0], [0, 0, 10, 0, 0, 0, 0, 0],
                        [0, 0, 0, 10, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 10],
                        [0, 0, 0, 10, 0, 10, 0, 0], [0, 0, 0, 0, 0, 0, 10, 0],
                        [0, 0, 0, 0, 0, 0, 0, 10], [0, 0, 0, 0, 0, 0, 0, 0]])
    res = maximum_flow(graph, 0, 7, method=method)
    assert res.flow_value == 20
    expected_flow = np.array([[0, 10, 0, 0, 10, 0, 0, 0],
                              [-10, 0, 10, 0, 0, 0, 0, 0],
                              [0, -10, 0, 10, 0, 0, 0, 0],
                              [0, 0, -10, 0, 0, 0, 0, 10],
                              [-10, 0, 0, 0, 0, 10, 0, 0],
                              [0, 0, 0, 0, -10, 0, 10, 0],
                              [0, 0, 0, 0, 0, -10, 0, 10],
                              [0, 0, 0, -10, 0, 0, -10, 0]])
    assert_array_equal(res.flow.toarray(), expected_flow)
예제 #14
0
    def reduction_implication_network(self, rounding_parameter):
        """
        Use an implication network to reduce the current problem instance.
        :param rounding_parameter: the projection data will be truncated to [rounding_parameter], in order to be able
               to use integer capacities in the implication network.
        """
        current_N = self.A.shape[1]
        A_csc = self.A.tocsc()
        B = 10**rounding_parameter * A_csc.transpose() * A_csc
        int_y = (10**rounding_parameter * self.y +
                 0.1 * np.ones_like(self.y)).astype(int)
        diagonal = B.diagonal()
        B -= csr_matrix(np.diag(diagonal))
        A_y = self.A.transpose() @ int_y
        outeredges = csr_matrix(2 * A_y - diagonal)
        Adjacency_matrix = 2 * sparse.bmat(
            [[None, 2 * B, None, None],
             [None, None, None, outeredges.transpose()],
             [outeredges, None, None, None], [None, None, 0, None]],
            format='csr')
        max_flow_output = csgraph.maximum_flow(Adjacency_matrix, 2 * current_N,
                                               2 * current_N + 1)

        flow = max_flow_output.residual
        symmetric_central_flow = flow[:current_N, current_N:2 *
                                      current_N] + flow[:current_N,
                                                        current_N:2 *
                                                        current_N].transpose()
        symmetric_central_flow.data //= 2
        flow[:current_N, current_N:2 * current_N] = symmetric_central_flow
        flow[current_N:2 * current_N, :current_N] = -symmetric_central_flow
        symmetric_outer_flow = \
            flow[2*current_N, :current_N] + flow[current_N: 2 * current_N, 2*current_N + 1].transpose()
        symmetric_outer_flow.data //= 2
        flow[2 * current_N, :current_N] = symmetric_outer_flow
        flow[current_N:2 * current_N,
             2 * current_N + 1] = symmetric_outer_flow.transpose()

        residual = Adjacency_matrix - flow
        residual.eliminate_zeros()
        n_components, labels = csgraph.connected_components(
            residual, connection='strong')

        component_type = np.zeros(n_components, dtype=int)
        # Type 14: u and 1 - u are both contained in the component
        # Type 15: u is contained in the component, 1 - u is not, no path from u to u - 1
        # Type 16: u is contained in the component, 1 - u is not, there exists a path from u to u - 1
        indices = []
        vals = []
        for i in range(current_N):
            component = labels[i]
            if component_type[component] == 0:
                if component == labels[i + current_N]:
                    component_type[component] = 14
                else:
                    reachable = csgraph.breadth_first_order(
                        residual, i, return_predecessors=False)
                    if i + current_N in reachable:
                        component_type[component] = 16
                    else:
                        component_type[component] = 15
            if component_type[component] == 15:
                indices.append(i)
                vals.append(1)
            elif component_type[component] == 16:
                indices.append(i)
                vals.append(0)

        no_reductions = len(indices)
        order = np.array(indices).argsort()
        for j in range(no_reductions):
            i = order[no_reductions - j - 1]
            self.problem_reduction_single(indices[i], vals[i])
        return 0
예제 #15
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_raises_when_sink_is_out_of_bounds(sink, method):
    with pytest.raises(ValueError):
        graph = csr_matrix([[0, 1], [0, 0]])
        maximum_flow(graph, 0, sink, method=method)
예제 #16
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_raises_when_source_is_sink():
    with pytest.raises(ValueError):
        graph = csr_matrix([[0, 1], [0, 0]])
        maximum_flow(graph, 0, 0)
        maximum_flow(graph, 0, 0, method='edmonds_karp')
예제 #17
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_raises_on_non_square_input():
    with pytest.raises(ValueError):
        graph = csr_matrix([[0, 1, 2], [2, 1, 0]])
        maximum_flow(graph, 0, 1)
예제 #18
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_raises_on_floating_point_input():
    with pytest.raises(ValueError):
        graph = csr_matrix([[0, 1.5], [0, 0]], dtype=np.float64)
        maximum_flow(graph, 0, 1)
        maximum_flow(graph, 0, 1, method='edmonds_karp')
예제 #19
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_raises_on_csc_input():
    with pytest.raises(TypeError):
        graph = csc_matrix([[0, 1], [0, 0]])
        maximum_flow(graph, 0, 1)
        maximum_flow(graph, 0, 1, method='edmonds_karp')
예제 #20
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_residual_raises_deprecation_warning():
    graph = csr_matrix([[0, 5, 0], [0, 0, 3], [0, 0, 0]])
    res = maximum_flow(graph, 0, 2)
    with pytest.deprecated_call():
        res.residual
예제 #21
0
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import maximum_flow
import numpy as np
inf = 100000000
n = int(input())
l = list(map(int , input().split())) # plus one is the index
e = int(input())
m = [[0 for i in range(n+1)] for i in range(n+1)]
for i in range(e):
    q1 , q2 , c = tuple(map(int ,input().split()))
    m[q1][q2] = c
for i in range(n):
    if l[i]==1:
        m[0][i+1]=inf

graph = csr_matrix(m)

print(maximum_flow(graph, 0, l.index(2)+1).flow_value)
##connect all source with one source before them with edge capacity of infinte
#index zero is the base source
#source : 1 , node : 0  , sink : 2
예제 #22
0
def _get_valid_rules(rules, tickets) -> Dict[str, int]:
    # Let's try this using maxflow
    R = len(rules)
    T = len(tickets)
    # F is just number of rules
    F = R

    N = 1 + R + F + 1

    C = np.zeros((N, N), dtype=int)

    # Initialize arcs from source to tickets
    src = 0
    snk = N - 1

    def rule_index(r):
        return 1 + r

    def field_index(f):
        return 1 + R + f

    # source to rule
    for r in range(R):
        C[src, rule_index(r)] = 1

    # fields to snk
    for f in range(F):
        C[field_index(f), snk] = 1

    # rules
    for r in range(R):
        for f in range(F):
            valid = all(rules[r].is_valid(t[f]) for t in tickets)

            if not valid:
                continue
            C[rule_index(r), field_index(f)] = 1

    print(f"dims: T: {T}, F: {F}, R: {R}, N: {N}")
    print(C)

    print("Converting to CSR...")
    C = csr_matrix(C)

    print(f"Solving max flow for matrix shape {C.shape}...")

    result = maximum_flow(C, src, snk)

    print(f"result: {result.flow_value}")

    if (result.flow_value != R):
        print(f"Uh oh, not enough flow!")

    residual = result.residual

    matches = dict()
    for r in range(R):
        for f in range(F):
            try:
                if residual[rule_index(r), field_index(f)] == 1:
                    rule = rules[r]
                    if rule.name in matches:
                        raise ValueError()
                    matches[rule.name] = f
            except KeyError:
                continue

    if not set(range(F)) == set(matches.values()):
        print("Error: Invalid matching!")

    return matches
예제 #23
0
파일: test_flow.py 프로젝트: mhwende/scipy
def test_raises_when_source_is_out_of_bounds(source):
    with pytest.raises(ValueError):
        graph = csr_matrix([[0, 1], [0, 0]])
        maximum_flow(graph, source, 1)
예제 #24
0
 def time_maximum_flow(self, n, density):
     maximum_flow(self.data, 0, n - 1)
예제 #25
0
파일: test_flow.py 프로젝트: zhaog6/scipy
def test_raises_on_dense_input():
    with pytest.raises(TypeError):
        graph = np.array([[0, 1], [0, 0]])
        maximum_flow(graph, 0, 1)
        maximum_flow(graph, 0, 1, method='edmonds_karp')
예제 #26
0
	def min_cut(self):
		self.graph = csr_matrix((self.weight, (self.from_node, self.to_node)), shape=(self.N+2, self.N+2))
		max_flow = maximum_flow(self.graph, self.bgd_src, self.fgd_sink)
		return max_flow
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import shortest_path, floyd_warshall, dijkstra, bellman_ford, johnson, NegativeCycleError, maximum_bipartite_matching, maximum_flow, minimum_spanning_tree
import numpy as np

n, m = map(int, input().split())
edges = [list(map(int, input().split())) for i in range(m)]


def graph_csr(edges, n, directed=True, indexed_1=True):  # 隣接リストから粗行列を作成
    arr = np.array(edges, dtype=np.int64).T
    arr = arr.astype(np.int64)
    index = int(indexed_1)
    if not directed:
        return csr_matrix((np.concatenate([arr[2], arr[2]]), (np.concatenate([arr[0]-index, arr[1]-index]), np.concatenate([arr[1]-index, arr[0]-index]))), shape=(n, n))
    else:
        return csr_matrix((arr[2], (arr[0]-index, arr[1]-index)), shape=(n, n))


csr = graph_csr(edges, n)
try:
    print(floyd_warshall(csr))
except NegativeCycleError:
    print('-1')
dijkstra(csr, indices=0)
bellman_ford(csr, indices=0)
maximum_bipartite_matching(csr, perm_type='column')
maximum_flow(csr, source=0, sink=1).flow_value
maximum_flow(csr, source=0, sink=1).residual
int(sum(minimum_spanning_tree(csr).data))