def analyze_singluar_values(nodes, edges, rank, filename):
    idxs = {}
    for i, k in enumerate(nodes):  #enumerate(adjlist.keys()):
        idxs[k] = i
    rows, cols = [], []
    for u, v in edges:
        rows.append(idxs[u])
        cols.append(idxs[v])
        rows.append(idxs[v])
        cols.append(idxs[u])
    nnz = len(rows)
    incident_matrix = coo_matrix((np.ones(nnz), (rows, cols)),
                                 shape=(len(nodes), len(nodes)))

    _1, s, _2 = svds(incident_matrix.tocsc(), k=rank)
    s = sorted(s, reverse=True)

    with open(
            "../results/{}_decomposition_singluar_values.txt".format(filename),
            "w") as f:
        for _x, _y in zip(np.arange(1, len(s) + 1), s):
            f.write(f'{_x} {_y}\n')

    utils.logAnalysis(
        np.arange(1,
                  len(s) + 1), s,
        "../plots/{}_decomposition_singular_values.png".format(filename),
        "Rank", "Singular value", "Distribution of Singular Values")
def analyze_singular_values(graph, rank=100):
    print("Analyzing singular values...")
    incident_matrix, nnz = graph.get_incidence_matrix()
    _, s, _ = svds(incident_matrix.tocsc(), k=rank)
    s = sorted(s, reverse=True)
    with open("../results/{}_singular_values.txt".format(graph.datatype), "w") as f:
        for _x, _y in zip(np.arange(1,len(s)+1), s):
            f.write(f'{_x} {_y}\n')
    utils.logAnalysis(np.arange(1,len(s)+1), s,
                      "../plots/{}_singular_values.png".format(graph.datatype),
                      "Rank", "Singular value", "Singular Values")
def analyze_hyperedge_sizes(graph):
    print("Analyzing hyperedge sizes...")
    sizeList = [len(indices) for _, indices in graph.edges]
    sizes, freq = np.unique(sizeList, return_counts=True)
    with open("../results/{}_hyperedge_sizes.txt".format(graph.datatype), "w") as f:
        for _x, _y in zip(sizes, freq):
            f.write(f'{_x} {_y}\n')
    # draw log-log plot (y-axis: fraction of nodes, x-axis: degree)
    utils.logAnalysis(sizes, freq,
                      "../plots/{}_hyperedge_sizes.png".format(graph.datatype),
                      "Edge size", "Count", "Hyperedge Sizes")
    print("The average size of edges:", np.mean(sizeList))
def analyze_degrees(graph):
    print("Analyzing degrees...")
    degreeList = [len(indices) for indices in graph.node2edge]
    degrees, freq = np.unique(degreeList, return_counts=True)
    with open("../results/{}_degrees.txt".format(graph.datatype), "w") as f:
        for _x, _y in zip(degrees, freq):
            f.write(f'{_x} {_y}\n')

    start_idx = int(degrees[0] == 0)
    utils.logAnalysis(degrees[start_idx:], freq[start_idx:],
                      "../plots/{}_degrees.png".format(graph.datatype),
                      "Degree", "Count", "Degrees")    
    print("The average degree of nodes:", np.mean(degreeList))
def analyze_degrees(nodes, edges, filename):
    adjlist = {u: [] for u in nodes}
    for u, v in edges:
        adjlist[u].append(v)
        adjlist[v].append(u)
    degreeList = [len(v) for v in adjlist.values()]
    degrees, freq = np.unique(degreeList, return_counts=True)

    with open("../results/{}_decomposition_degrees.txt".format(filename),
              "w") as f:
        for _x, _y in zip(degrees, freq):
            f.write(f'{_x} {_y}\n')

    start_idx = int(degrees[0] == 0)
    utils.logAnalysis(degrees[start_idx:], freq[start_idx:],
                      "../plots/{}_decomposition_degrees.png".format(filename),
                      "Degree", "Count", "Degrees")
def analyze_intersection(graph):
    print("Analyzing interesting pairs and intersection sizes...")
    inter_cnt, hyperedge_cnt = [0], [0]
    size_cnt = {}
    for i in tqdm.trange(1, graph.number_of_edges()):
        if graph.edges[i][0] != graph.edges[i-1][0]:
            inter_cnt.append(inter_cnt[-1])
            hyperedge_cnt.append(hyperedge_cnt[-1])
        hyperedge_cnt[-1] = i
        counter = {}
        for idx in graph.edges[i][1]:
            for edge_idx in graph.node2edge[graph.idx2node[idx]]:
                if edge_idx >= i: break
                counter[edge_idx] = counter.get(edge_idx, 0) + 1
        inter_cnt[-1] += len(counter)
        for v in counter.values():
            size_cnt[v] = size_cnt.get(v, 0) + 1
            
    inter_cnt = np.array(inter_cnt)
    hyperedge_cnt = np.array(hyperedge_cnt)

    with open("../results/{}_intersecting_pairs.txt".format(graph.datatype), "w") as f:
        for _x, _y in zip(hyperedge_cnt * (hyperedge_cnt + 1) / 2, inter_cnt):
            f.write(f'{_x} {_y}\n')
    
    start_idx = 0
    while inter_cnt[start_idx] == 0: start_idx += 1
    utils.logAnalysis((hyperedge_cnt * (hyperedge_cnt + 1) / 2)[start_idx:], inter_cnt[start_idx:],
                      "../plots/{}_intersecting_pairs.png".format(graph.datatype),
                      "# of all pairs", "# of intersecting pairs", "Intersecting Pairs")
    
    soi_keys, soi_values = zip(*sorted(size_cnt.items(), key=lambda x: x[0]))
    
    with open("../results/{}_intersection_sizes.txt".format(graph.datatype), "w") as f:
        for _x, _y in zip(soi_keys, soi_values):
            f.write(f'{_x} {_y}\n')
    
    start_idx = 0
    while soi_values[start_idx] == 0: start_idx += 1
    utils.logAnalysis(soi_keys[start_idx:], soi_values[start_idx:],
                      "../plots/{}_intersection_sizes.png".format(graph.datatype),
                      "Intersection size", "Count", "Intersection Sizes")
def analyze_edge_density(graph):
    print("Analyzing edge density...")
    keys = set([t for t, _ in graph.edges])
    if graph.datatype == 'model': keys.add(0)
    
    node_cnt = {k: 0 for k in keys}
    edge_cnt = {k: 0 for k in keys}
    for t, _ in graph.nodes: node_cnt[t] += 1
    for t, _ in graph.edges: edge_cnt[t] += 1
    node_cnt = [v for _, v in sorted(node_cnt.items(), key=lambda x: x[0])]
    edge_cnt = [v for _, v in sorted(edge_cnt.items(), key=lambda x: x[0])]
    for i in range(1, len(keys)):
        node_cnt[i] += node_cnt[i-1]
        edge_cnt[i] += edge_cnt[i-1]
    start_idx = 0
    while node_cnt[start_idx] == 0 or edge_cnt[start_idx] == 0: start_idx += 1
    with open("../results/{}_edge_density.txt".format(graph.datatype), "w") as f:
        for _d, _f in zip(node_cnt, edge_cnt):
            f.write(f'{_d} {_f}\n')
    utils.logAnalysis(node_cnt[start_idx:], edge_cnt[start_idx:],
                      "../plots/{}_edge_density.png".format(graph.datatype),
                      "# of nodes", "# of edges", "Edge Density")