def L_P_RWWR(network):
    num_add = 0  # the number of egdes to be added
    nodes_pair_without_edge = []  # the pairs of nodes without edges
    probability_add = []  # the probabilities of the pairs of nodes to be added
    score = 0  # the score of each pair of nodes in link prediction model
    total_score_without_edge = 0.0  # the sum of scores of pairs of nodes without edge

    #  calculate the score of each pair of nodes
    for i, elei in enumerate(list(network.nodes()), 1):
        for j, elej in enumerate(list(network.nodes()), 1):

            if i >= j:
                continue
            if not network.has_edge(elei, elej):
                try:
                    score = (CCD(network, elei, elej, i, j, 0.15) +
                             CCD(network, elej, elei, j, i, 0.15)) / 2
                except:
                    continue
                total_score_without_edge += score
                nodes_pair_without_edge.append((elei, elej, score))

    for a, b, c in nodes_pair_without_edge:
        probability_add.append(
            c / total_score_without_edge
        )  # calculate the probabilities of edges to be added
    # select edges to be added according to probabilities
    edges_add = calculate_param.prob_select_distinct(nodes_pair_without_edge,
                                                     probability_add, num_add)
    for a, b, c in edges_add:
        network.add_edge(a, b)  # add selected edges

    return True
def L_P_KatzIndex(network, max_length):
    num_add = 0  # the number of egdes to be added
    nodes_pair_without_edge = []  # the pairs of nodes without edges
    probability_add = []  # the probabilities of the pairs of nodes to be added
    score = 0.0  # the score of each pair of nodes in link prediction model
    score_old = 0.0  # the last score of each pair of nodes in link prediction model
    total_score_without_edge = 0.0  # the sum of scores of pairs of nodes without edge
    B = 0.1  # a free parameter to control path weights. The longer the path is, the less contribution the path made to the similarity

    #  calculate the score of each pair of nodes
    for i, elei in enumerate(list(network.nodes())):
        for j, elej in enumerate(list(network.nodes())):

            if i >= j:
                continue
            if not network.has_edge(elei, elej):
                try:
                    for l in range(2, max_length):
                        score_old = score
                        score += pow(B, l) * pow(nx.to_numpy_array(network),
                                                 l)[i][j]
                        if is_katz_converge(score, score_old):
                            break
                except:
                    continue
                total_score_without_edge += score
                nodes_pair_without_edge.append((elei, elej, score))

    for a, b, c in nodes_pair_without_edge:
        probability_add.append(
            c / total_score_without_edge
        )  # calculate the probabilities of edges to be added
    # select edges to be added according to probabilities
    edges_add = calculate_param.prob_select_distinct(nodes_pair_without_edge,
                                                     probability_add, num_add)
    for a, b, c in edges_add:
        network.add_edge(a, b)  # add selected edges

    return True
def L_P_ACT(network):
    num_add = 0  # the number of egdes to be added
    nodes_pair_without_edge = [
    ]  # the pairs of nodes with edges and without edges
    probability_add = []  # the probabilities of the pairs of nodes to be added
    score = 0.0  # the score of each pair of nodes in link prediction model
    total_score_without_edge = 0.0  # the sum of scores of pairs of nodes without edge

    #  calculate the score of each pair of nodes
    for i, elei in enumerate(list(network.nodes(), 0)):
        for j, elej in enumerate(list(network.nodes(), 0)):

            if i >= j:
                continue
            if not network.has_edge(elei, elej):
                try:
                    L = nx.laplacian_matrix(network).A
                    L_aa = L[i][i]
                    L_bb = L[j][j]
                    L_ab = L[i][j]  # 修改L[a][b]变为L[i][j]
                    score = 1 / L_aa + L_bb - 2 * L_ab
                except:
                    continue
                total_score_without_edge += score
                nodes_pair_without_edge.append((elei, elej, score))

    for a, b, c in nodes_pair_without_edge:
        probability_add.append(
            c / total_score_without_edge
        )  # calculate the probabilities of edges to be added
    # select edges to be added according to probabilities
    edges_add = calculate_param.prob_select_distinct(nodes_pair_without_edge,
                                                     probability_add, num_add)
    for a, b, c in edges_add:
        network.add_edge(a, b)  # add selected edges

    return True
def L_P_SimRank(network, C=0.8, max_iter=100):
    # C: float, 0< C <=1, it is the decay factor which represents the relative importance between in-direct neighbors and direct neighbors.
    # max_iter: integer, the number specifies the maximum number of iterations for simrank
    num_add = 0  # the number of egdes to be added
    nodes_pair_without_edge = []  # the pairs of nodes without edges
    probability_add = []  # the probabilities of the pairs of nodes to be added
    score = 0.0  # the score of each pair of nodes in link prediction model
    total_score_without_edge = 0.0  # the sum of scores of pairs of nodes without edge

    # init.vars
    sim = defaultdict(list)  # the similarity between two nodes
    sim_old = defaultdict(
        list)  # the similarity between two nodes in last recursion
    for n in network.nodes():
        sim[n] = defaultdict(int)
        sim[n][n] = 1
        sim_old[n] = defaultdict(int)
        sim_old[n][n] = 0

    # recursively calculate simrank
    for iter_ctr in range(max_iter):
        if _is_sim_converge(sim, sim_old):
            break
        # calculate the score of each pair of nodes
        sim_old = copy.deepcopy(sim)
        for i, elei in enumerate(list(network.nodes()), 1):
            for j, elej in enumerate(list(network.nodes()), 1):
                if i == j:
                    continue
                try:
                    s_elei_elej = 0.0
                    for u in network.neighbors(elei):
                        for v in network.neighbors(elej):
                            s_elei_elej += sim_old[u][v]
                    sim[elei][elej] = (C * s_elei_elej /
                                       (len(network.neighbors(elei)) *
                                        len(network.neighbors(elej))))
                except:
                    continue

    for i, elei in enumerate(list(network.nodes()), 1):
        for j, elej in enumerate(list(network.nodes()), 1):
            if i >= j:
                continue
            if not network.has_edge(elei, elej):
                try:
                    score = sim[elei][elej]
                except:
                    continue
                total_score_without_edge += score
                nodes_pair_without_edge.append((elei, elej, score))

    for a, b, c in nodes_pair_without_edge:
        probability_add.append(
            c / total_score_without_edge
        )  # calculate the probabilities of edges to be added
    # select edges to be added according to probabilities
    edges_add = calculate_param.prob_select_distinct(nodes_pair_without_edge,
                                                     probability_add, num_add)
    for a, b, c in edges_add:
        network.add_edge(a, b)  # add selected edges
    return True