Ejemplo n.º 1
0
def bansal(signed_graph):
    # start of the algorithm
    execution_time = ExecutionTime()

    # initialize the solution as empty
    solution_x = None
    solution_objective_function = np.finfo(float).min

    # get the best clustering from the neighborhood of each node
    for node, neighbors in enumerate(signed_graph.adjacency_list):
        x = np.zeros(signed_graph.number_of_nodes)
        x[node] = 1
        for neighbor in neighbors[0]:
            x[neighbor] = 1
        for neighbor in neighbors[1]:
            x[neighbor] = -1

        # update the solution if needed
        objective_function = evaluate_objective_function(signed_graph, x)
        if objective_function > solution_objective_function:
            solution_x = x
            solution_objective_function = objective_function

    # build the solution
    solution = build_solution(solution_x)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds, solution_x, signed_graph)

    # return the solution
    return solution, solution_x
Ejemplo n.º 2
0
def union_core(core_decomposition_file_name, multilayer_graph, gammas, min_sup,
               min_size, print_file):
    # start of the algorithm
    execution_time = ExecutionTime()

    # obtain a restricted set of nodes from core decomposition
    nodes = compute_union_core(core_decomposition_file_name, gammas, min_sup,
                               min_size)

    # execute crochet+
    fcgqc = crochet_plus(multilayer_graph,
                         gammas,
                         min_sup,
                         min_size,
                         None,
                         nodes=nodes,
                         print_end_algorithm=False)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm_fcgqc(gammas, min_sup,
                              min_size, execution_time.execution_time_seconds,
                              len(fcgqc), len(nodes))

    # print the resulting fcgqc to file
    if print_file is not None:
        print_fcgqc(print_file, fcgqc)

    return fcgqc
Ejemplo n.º 3
0
def naive_decomposition(temporal_graph, print_file):
    # measures
    number_of_cores = [0]
    processed_nodes = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # cores
    cores = {}

    # initialize the queue of intervals
    intervals_queue = deque()
    # initialize the set of intervals in the queue
    intervals = set()
    # add each singleton interval to the queue
    for timestamp in temporal_graph.timestamps_iterator:
        interval = get_interval(timestamp)
        intervals_queue.append(interval)
        intervals.add(interval)

    # while the queue is not empty
    while len(intervals_queue) > 0:
        # remove an interval from the queue
        interval = intervals_queue.popleft()
        intervals.remove(interval)

        # store the results of the subroutine to cores
        processed_nodes += temporal_graph.number_of_nodes
        cores[interval] = subroutine(temporal_graph,
                                     set(temporal_graph.nodes_iterator),
                                     interval,
                                     print_file=print_file,
                                     number_of_cores=number_of_cores)[0]

        # if there are cores in the interval
        if len(cores[interval]) > 0:
            # get its descendant intervals
            descendant_intervals = get_descendant_intervals(
                interval, temporal_graph)
            # for each descendant interval
            for descendant_interval in descendant_intervals:
                # if the descendant interval has not already been found
                if descendant_interval not in intervals:
                    # add the descendant interval to the queue
                    intervals_queue.append(descendant_interval)
                    intervals.add(descendant_interval)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds,
                        number_of_cores[0], processed_nodes)
Ejemplo n.º 4
0
def eigensign(signed_graph):
    # start of the algorithm
    execution_time = ExecutionTime()

    # initialize the solution as empty
    solution_x = None
    solution_objective_function = np.finfo(float).min
    solution_threshold = None

    # obtain the adjacency matrix
    a = signed_graph.get_adjacency_matrix()

    # get the eigenvector corresponding to the maximum eigenvalue
    maximum_eigenvector = np.squeeze(eigsh(a, k=1, which='LA')[1])

    # get the thresholds from the eigenvector
    thresholds = {
        int(np.abs(element) * 1000) / 1000.0
        for element in maximum_eigenvector
    }

    # compute x for all the values of the threshold
    for threshold in thresholds:
        x = np.array([
            np.sign(element) if np.abs(element) >= threshold else 0
            for element in maximum_eigenvector
        ])

        # update the solution if needed
        objective_function = evaluate_objective_function(signed_graph, x)
        if objective_function > solution_objective_function:
            solution_x = x
            solution_objective_function = objective_function
            solution_threshold = threshold

    # build the solution
    solution = build_solution(solution_x)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds,
                        solution_x,
                        signed_graph,
                        threshold=solution_threshold)

    # return the solution
    return solution, solution_x
Ejemplo n.º 5
0
def random_eigensign(signed_graph,
                     beta,
                     maximum_eigenvector=None,
                     execution_time_seconds=None):
    # start of the algorithm
    execution_time = ExecutionTime()

    if maximum_eigenvector is None:
        # obtain the adjacency matrix
        a = signed_graph.get_adjacency_matrix()

        # get the eigenvector corresponding to the maximum eigenvalue
        maximum_eigenvector = np.squeeze(eigsh(a, k=1, which='LA')[1])

        # consolidate beta
        if beta == 'l1':
            beta = np.linalg.norm(maximum_eigenvector, ord=1)
        elif beta == 'sqrt':
            beta = np.sqrt(signed_graph.number_of_nodes)
        else:
            beta = float(beta)

        # multiply the maximum eigenvector by beta
        maximum_eigenvector *= beta

    # compute x
    x = np.array([0 for _ in signed_graph.nodes_iterator])
    for node, element in enumerate(maximum_eigenvector):
        # check the probability for a certain number of times
        if np.random.choice((True, False),
                            p=(min(np.abs(element),
                                   1), max(1 - np.abs(element), 0))):
            x[node] = np.sign(element)

    # build the solution
    solution = build_solution(x)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    if execution_time_seconds is None:
        execution_time_seconds = execution_time.execution_time_seconds
    print_end_algorithm(execution_time_seconds, x, signed_graph, beta=beta)

    # return the solution
    return solution, x, maximum_eigenvector, execution_time_seconds, beta
Ejemplo n.º 6
0
def decomposition(temporal_graph, print_file):
    # measures
    number_of_cores = [0]
    processed_nodes = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # cores
    cores = {}

    # initialize the queue of intervals
    intervals_queue = deque()
    # initialize the dict of ancestors
    ancestors = {}
    # add each singleton interval to the queue
    for timestamp in temporal_graph.timestamps_iterator:
        intervals_queue.append(get_interval(timestamp))

    # dict counting the number of descendants in the queue
    descendants_count = {}

    # while the queue is not empty
    while len(intervals_queue) > 0:
        # remove an interval from the queue
        interval = intervals_queue.popleft()

        # get the nodes from which start the computation
        nodes = get_ancestors_intersection(interval, ancestors, cores, temporal_graph, descendants_count)

        # if nodes is not empty
        if len(nodes) > 0:
            # store the results of the subroutine to cores
            processed_nodes += len(nodes)
            cores[interval] = subroutine(temporal_graph, nodes, interval, print_file=print_file, number_of_cores=number_of_cores)[0]

            # if there are cores in the interval
            if len(cores[interval]) > 0:
                # add its descendant intervals to the queue
                add_descendants_to_queue(interval, temporal_graph, intervals_queue, ancestors, descendants_count)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds, number_of_cores[0], processed_nodes)
Ejemplo n.º 7
0
def inner_most(multilayer_graph, print_file):
    # start of the algorithm
    execution_time = ExecutionTime()

    # create the data structure
    m = {}

    # create the vector of zeros and the set of nodes
    vector = tuple([0] * multilayer_graph.number_of_layers)
    nodes = array('i', multilayer_graph.nodes_iterator)

    # call the subroutine
    number_of_inner_most_cores, number_of_computed_cores = right_inner_most_cores(
        multilayer_graph, vector, 0, nodes, m, print_file)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds,
                        number_of_inner_most_cores, number_of_computed_cores)
def crochet_plus(multilayer_graph, gammas, min_sup, min_size, print_file, nodes=None, print_end_algorithm=True):
    # start of the algorithm
    execution_time = ExecutionTime()

    # if the subset of nodes is not provided
    if nodes is None:
        # consider every node
        nodes = set(multilayer_graph.nodes_iterator)

    # solution list of frequent cross-graph quasi-cliques
    fcgqc = []

    # order the nodes by Heuristic 1
    nodes_order = order_nodes(multilayer_graph, gammas, nodes, set(multilayer_graph.layers_iterator))

    # for each node (except the last in the ordering)
    for index, node in enumerate(nodes_order[:-1]):
        # create the starting node of the enumeration tree
        tree_node = {node}

        # call the recursive subroutine
        recursive_mine(tree_node, set(nodes_order[index + 1:]), set(multilayer_graph.layers_iterator), multilayer_graph,
                       gammas, min_sup, min_size, fcgqc, nodes_order)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    if print_end_algorithm:
        print_end_algorithm_fcgqc(gammas, min_sup, min_size, execution_time.execution_time_seconds, len(fcgqc), None)

    # print the resulting fcgqc to file
    if print_file is not None:
        print_fcgqc(print_file, fcgqc)

    return fcgqc
Ejemplo n.º 9
0
def maximal(temporal_graph, print_file):
    # measures
    number_of_maximal_cores = 0
    processed_nodes = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # structures for the maximal cores
    j_maximal_index = [0 for _ in temporal_graph.timestamps_iterator
                       ]  # end of interval, maximum k

    # for each timestamp i
    for i in temporal_graph.timestamps_iterator:
        # edges intersection and differences
        intersection = set(temporal_graph.edge_sets[i])
        differences = []

        # while the interval exists
        j = i + 1
        while j < temporal_graph.number_of_timestamps:
            # compute the new intersection
            temp_intersection = intersection & set(temporal_graph.edge_sets[j])

            # break if it is empty
            if len(temp_intersection) == 0:
                break

            # update the structures
            differences.append(tuple(intersection - temp_intersection))
            intersection = temp_intersection
            j += 1
        differences.append(tuple(intersection))

        # adjacency list and nodes divided by degree
        adjacency_list = defaultdict(list)
        nodes_by_degree = [[]]

        # minimum and maximal indexes
        minimum_index = 1
        maximal_index = 0

        # for every interval starting from timestamp i
        j -= 1
        while j >= i:
            # get the [i, j] interval
            interval = get_interval(i, j)

            # add the edges
            for edge in differences[j - i]:
                adjacency_list[edge[0]].append(edge[1])
                adjacency_list[edge[1]].append(edge[0])
                try:
                    nodes_by_degree[len(adjacency_list[edge[0]])].append(
                        edge[0])
                except IndexError:
                    nodes_by_degree.append([edge[0]])
                try:
                    nodes_by_degree[len(adjacency_list[edge[1]])].append(
                        edge[1])
                except IndexError:
                    nodes_by_degree.append([edge[1]])

            # compute the core decomposition for [i, j]
            if len(nodes_by_degree) > minimum_index and len(
                    nodes_by_degree[minimum_index]) > minimum_index:
                processed_nodes += len(nodes_by_degree[minimum_index])
                subroutine_result = subroutine(
                    adjacency_list, set(nodes_by_degree[minimum_index]))
                new_maximal_index = subroutine_result[0]
                new_maximal_core = subroutine_result[1]

                # add the new maximal core to the solution
                if new_maximal_index > maximal_index:
                    maximal_index = new_maximal_index
                    if new_maximal_index > j_maximal_index[j]:
                        minimum_index = new_maximal_index + 1
                        number_of_maximal_cores += 1
                        j_maximal_index[j] = new_maximal_index
                        if print_file is not None:
                            print_file.print_core(interval, new_maximal_index,
                                                  new_maximal_core)

            # decrement j
            j -= 1

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm results
    print_end_algorithm(execution_time.execution_time_seconds,
                        number_of_maximal_cores, processed_nodes)
def hybrid(multilayer_graph, print_file, distinct_flag):
    # measures
    number_of_cores = 0
    number_of_computed_cores = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # create the vector of zeros from which start the computation
    start_vector = tuple([0] * multilayer_graph.number_of_layers)

    # dict of cores
    cores = {}

    # core [0]
    if print_file is not None and not distinct_flag:
        print_file.print_core(start_vector,
                              array('i', multilayer_graph.get_nodes()))
    elif distinct_flag:
        cores[start_vector] = array('i', multilayer_graph.get_nodes())
        number_of_computed_cores -= 1
    number_of_cores += 1

    # initialize the queue of vectors with the descendants of start_vector and the structure that for each vector saves its ancestor vectors
    vectors_queue = deque()
    ancestors = {}
    for index in multilayer_graph.layers_iterator:
        descendant_vector = build_descendant_vector(start_vector, index)
        vectors_queue.append(descendant_vector)
        ancestors[descendant_vector] = [start_vector]

    # initialize the dictionary that for each vector counts the number of descendants in the queue
    descendants_count = defaultdict(int)

    # compute the core decomposition layer by layer
    for layer in multilayer_graph.layers_iterator:
        cores.update(
            pure_core_decomposition(multilayer_graph,
                                    start_vector,
                                    layer,
                                    print_file=print_file,
                                    distinct_flag=distinct_flag)[0])
    number_of_computed_cores += len(cores) + multilayer_graph.number_of_layers

    # while vectors_queue is not empty
    while len(vectors_queue) > 0:
        # remove a vector from vectors_queue (FIFO policy)
        vector = vectors_queue.popleft()

        # if the number of non zero indexes of vector is equal to the number of its ancestors and is more than 1, build the intersection of its ancestor cores
        number_of_non_zero_indexes = len(
            [index for index in vector if index > 0])
        number_of_ancestors = len(ancestors[vector])
        if number_of_non_zero_indexes == number_of_ancestors and number_of_non_zero_indexes > 1 and vector not in cores:
            ancestors_intersection = build_ancestors_intersection(
                ancestors[vector], cores, descendants_count, distinct_flag)

            # if the intersection of its ancestor cores is not empty
            if len(ancestors_intersection) > 0:
                # compute the core from it
                k_core, minimum_degrees_vector = core(multilayer_graph,
                                                      vector,
                                                      ancestors_intersection,
                                                      algorithm='h')
                number_of_computed_cores += 1

                # if the core is not empty
                if len(k_core) > 0:
                    # add the core to the dict of cores
                    cores[vector] = k_core
                    if print_file is not None and not distinct_flag:
                        print_file.print_core(vector, k_core)

                    # if the vector of the minimum degrees is not equal to vector
                    if minimum_degrees_vector != vector:
                        # fill the cores that are equals
                        bottom_up_visit(multilayer_graph,
                                        minimum_degrees_vector, vector, cores,
                                        print_file, distinct_flag)
        else:
            # for each ancestor of vector
            for ancestor in ancestors[vector]:
                # decrement its number of descendants
                decrement_descendants_count(ancestor, cores, descendants_count,
                                            distinct_flag)

        # if the core corresponding to the vector is in the dict of cores
        if vector in cores:
            # increment the number of cores
            number_of_cores += 1

            # compute its descendant vectors
            for index in multilayer_graph.layers_iterator:
                descendant_vector = build_descendant_vector(vector, index)

                try:
                    # update the list of the ancestors of the descendant vector
                    ancestors[descendant_vector].append(vector)

                # if the descendant vector has not already been found
                except KeyError:
                    # add the descendant vector to the queue
                    vectors_queue.append(descendant_vector)
                    ancestors[descendant_vector] = [vector]

                # increment descendants_count
                descendants_count[vector] += 1

        # delete vector's entry from ancestors
        del ancestors[vector]

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds, number_of_cores,
                        number_of_computed_cores)

    # execute the post processing
    post_processing(cores, distinct_flag, print_file)
Ejemplo n.º 11
0
def breadth_first(multilayer_graph, print_file, distinct_flag):
    # measures
    number_of_cores = 0
    number_of_computed_cores = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # create the vector of zeros from which start the computation
    start_vector = tuple([0] * multilayer_graph.number_of_layers)

    # dict of cores
    cores = {}

    # core [0]
    if print_file is not None and not distinct_flag:
        print_file.print_core(start_vector,
                              array('i', multilayer_graph.get_nodes()))
    elif distinct_flag:
        cores[start_vector] = array('i', multilayer_graph.get_nodes())
    number_of_cores += 1

    # initialize the queue of vectors with the descendants of start_vector and the structure that for each vector saves its ancestor vectors
    vectors_queue = deque()
    ancestors = {}
    for index in multilayer_graph.layers_iterator:
        descendant_vector = build_descendant_vector(start_vector, index)
        vectors_queue.append(descendant_vector)
        ancestors[descendant_vector] = [start_vector]

    # initialize the dictionary that for each vector counts the number of descendants in the queue
    descendants_count = defaultdict(int)

    # while vectors_queue is not empty
    while len(vectors_queue) > 0:
        # remove a vector from vectors_queue (FIFO policy)
        vector = vectors_queue.popleft()

        # if the number of non zero indexes of vector is equal to the number of its ancestors, build the intersection of its ancestor cores
        number_of_non_zero_indexes = len(
            [index for index in vector if index > 0])
        number_of_ancestors = len(ancestors[vector])
        if number_of_non_zero_indexes == number_of_ancestors:
            ancestors_intersection = build_ancestors_intersection(
                ancestors[vector],
                cores,
                descendants_count,
                distinct_flag,
                multilayer_graph=multilayer_graph)

            # if the intersection of its ancestor cores is not empty
            if len(ancestors_intersection) > 0:
                # compute the core from it
                k_core = core(multilayer_graph, vector, ancestors_intersection)
                number_of_computed_cores += 1
            # otherwise
            else:
                # delete its entry from ancestors and continue
                del ancestors[vector]
                continue

            # if the core is not empty
            if len(k_core) > 0:
                # add the core to the dict of cores and increment the number of cores
                cores[vector] = k_core
                number_of_cores += 1
                if print_file is not None and not distinct_flag:
                    print_file.print_core(vector, k_core)

                # compute its descendant vectors
                for index in multilayer_graph.layers_iterator:
                    descendant_vector = build_descendant_vector(vector, index)

                    try:
                        # update the list of the ancestors of the descendant vector
                        ancestors[descendant_vector].append(vector)

                    # if the descendant vector has not already been found
                    except KeyError:
                        # add the descendant vector to the queue
                        vectors_queue.append(descendant_vector)
                        ancestors[descendant_vector] = [vector]

                    # increment descendants_count
                    descendants_count[vector] += 1
        else:
            # for each ancestor of vector
            for ancestor in ancestors[vector]:
                # decrement its number of descendants
                decrement_descendants_count(ancestor, cores, descendants_count,
                                            distinct_flag)

        # delete vector's entry from ancestors
        del ancestors[vector]

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds, number_of_cores,
                        number_of_computed_cores)

    # execute the post processing
    post_processing(cores, distinct_flag, print_file)
def naive_maximal(temporal_graph, print_file):
    # start of the algorithm
    execution_time = ExecutionTime()
    processed_nodes = 0

    # cores
    cores = {}
    maximal_cores = {}

    # initialize the queue of intervals
    intervals_queue = deque()
    # initialize the dict of ancestors
    ancestors = {}
    # add each singleton interval to the queue
    for timestamp in temporal_graph.timestamps_iterator:
        intervals_queue.append(get_interval(timestamp))

    # dict counting the number of descendants in the queue
    descendants_count = {}

    # while the queue is not empty
    while len(intervals_queue) > 0:
        # remove an interval from the queue
        interval = intervals_queue.popleft()

        # get the nodes from which start the computation
        nodes = get_ancestors_intersection(interval, ancestors, cores,
                                           temporal_graph, descendants_count)

        # if nodes is not empty
        if len(nodes) > 0:
            # store the results of the subroutine to interval_cores
            processed_nodes += len(nodes)
            interval_cores = subroutine(temporal_graph,
                                        nodes,
                                        interval,
                                        in_memory=True)

            # if there are cores in the interval
            if len(interval_cores[0]) > 0:
                # store the first to cores
                cores[interval] = {1: interval_cores[0][1]}
                # add its descendant intervals to the queue
                add_descendants_to_queue(interval, temporal_graph,
                                         intervals_queue, ancestors,
                                         descendants_count)

                # add the maximal core to maximal
                maximal_cores[interval] = (
                    interval_cores[1], interval_cores[0][interval_cores[1]])
                # delete the maximal cores of the ancestor intervals if needed
                try:
                    for ancestor_interval in ancestors[interval]:
                        if ancestor_interval in maximal_cores and maximal_cores[
                                ancestor_interval][0] == interval_cores[1]:
                            maximal_cores.pop(ancestor_interval)
                except KeyError:
                    pass
            else:
                cores[interval] = interval_cores[0]

    # print the output file
    if print_file is not None:
        print_file.print_maximal_cores(maximal_cores)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds,
                        len(maximal_cores), processed_nodes)
Ejemplo n.º 13
0
def breadth_first_community_search(multilayer_graph, query_nodes, beta):
    # measures
    number_of_computed_cores = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # create the vector of zeros from which start the computation
    start_vector = tuple([0] * multilayer_graph.number_of_layers)

    # dict of cores
    cores = {}

    # solution initialized with the whole input graph
    community_search_density = 0.0
    community_search_nodes = array('i', multilayer_graph.get_nodes())
    community_search_layers = set(multilayer_graph.layers_iterator)
    community_search_vector = start_vector

    # initialize the queue of vectors with the descendants of start_vector and the structure that for each vector saves its ancestor vectors
    vectors_queue = deque()
    ancestors = {}
    for index in multilayer_graph.layers_iterator:
        descendant_vector = build_descendant_vector(start_vector, index)
        vectors_queue.append(descendant_vector)
        ancestors[descendant_vector] = [start_vector]

    # initialize the dictionary that for each vector counts the number of descendants in the queue
    descendants_count = defaultdict(int)

    # while vectors_queue is not empty
    while len(vectors_queue) > 0:
        # remove a vector from vectors_queue (FIFO policy)
        vector = vectors_queue.popleft()

        # if the number of non zero indexes of vector is equal to the number of its ancestors, build the intersection of its ancestor cores
        number_of_non_zero_indexes = len(
            [index for index in vector if index > 0])
        number_of_ancestors = len(ancestors[vector])
        if number_of_non_zero_indexes == number_of_ancestors:
            ancestors_intersection = build_ancestors_intersection(
                ancestors[vector],
                cores,
                descendants_count,
                False,
                multilayer_graph=multilayer_graph)

            # if the intersection of its ancestor contains the query nodes
            if query_nodes <= ancestors_intersection:
                # compute the core from it
                k_core = core(multilayer_graph, vector, ancestors_intersection)
                number_of_computed_cores += 1
            # otherwise
            else:
                # delete its entry from ancestors and continue
                del ancestors[vector]
                continue

            # if the core contains the query nodes
            if query_nodes <= set(k_core):
                # add the core to the dict of cores
                cores[vector] = k_core

                # update the community search solution if needed
                core_density, core_layers = objective_function(vector, beta)
                if core_density >= community_search_density:
                    community_search_density = core_density
                    community_search_nodes = k_core
                    community_search_layers = core_layers
                    community_search_vector = vector

                # compute its descendant vectors
                for index in multilayer_graph.layers_iterator:
                    descendant_vector = build_descendant_vector(vector, index)

                    try:
                        # update the list of the ancestors of the descendant vector
                        ancestors[descendant_vector].append(vector)

                    # if the descendant vector has not already been found
                    except KeyError:
                        # add the descendant vector to the queue
                        vectors_queue.append(descendant_vector)
                        ancestors[descendant_vector] = [vector]

                    # increment descendants_count
                    descendants_count[vector] += 1
        else:
            # for each ancestor of vector
            for ancestor in ancestors[vector]:
                # decrement its number of descendants
                decrement_descendants_count(ancestor, cores, descendants_count,
                                            False)

        # delete vector's entry from ancestors
        del ancestors[vector]

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm_community_search(execution_time.execution_time_seconds,
                                         number_of_computed_cores)
    print_community_search(query_nodes, beta, community_search_density,
                           community_search_nodes, community_search_layers,
                           community_search_vector)
Ejemplo n.º 14
0
    parser.add_argument('cd', help='core decomposition file')

    # read the arguments
    args = parser.parse_args()

    # create the new file for distinct cores only
    distinct_cores_file = open(
        dirname(dirname(getcwd())) + '/output/' + args.cd + '_distinct.txt',
        'w')

    # print the name of the input graph
    print_dataset_name(args.cd.split('_')[0])
    print '---------- Distinct Cores ---------'

    # start of the algorithm
    execution_time = ExecutionTime()

    # dict of cores
    cores = {}

    # open the file
    with open(dirname(dirname(getcwd())) + '/output/' + args.cd +
              '.txt') as cores_file:
        # for each line
        for line in cores_file:
            # remove the \n from the line
            line = line.replace('\n', '')

            # split the line
            split_line = line.split('\t')
            vector = literal_eval(split_line[0])
def depth_first_community_search(multilayer_graph, query_nodes, beta):
    # measures
    number_of_computed_cores = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # create the vector of zeros from which start the computation
    start_vector = tuple([0] * multilayer_graph.number_of_layers)

    # solution initialized with the whole input graph
    community_search_density = 0.0
    community_search_nodes = array('i', multilayer_graph.get_nodes())
    community_search_layers = set(multilayer_graph.layers_iterator)
    community_search_vector = start_vector

    # initialize the set of layers
    layers = set(multilayer_graph.layers_iterator)

    # initialize the base of layers
    base_layers = set(layers)

    # initialize the base of cores
    base_cores = {start_vector: array('i', multilayer_graph.nodes_iterator)}

    # set of the vectors corresponding to the computed cores
    computed_core_vectors = set()
    computed_core_vectors.add(start_vector)

    # for each layer
    while len(base_layers) > 0:
        # delete a layer from base_layers
        base_layers.pop()

        # set of the temporary base of cores
        temp_base_cores = {}

        # for each core in the base
        for vector, nodes in base_cores.iteritems():
            # for each layer in the base
            for base_layer in base_layers:
                # compute its core decomposition and store it in temp_base_cores
                if vector[base_layer] == 0:
                    new_cores, new_cores_order = core_decomposition(
                        multilayer_graph,
                        vector,
                        base_layer,
                        nodes,
                        query_nodes=query_nodes)
                    temp_base_cores.update(new_cores)
                    number_of_computed_cores += len(new_cores) + 1

                    # update the community search solution if needed
                    try:
                        core_density, core_layers = objective_function(
                            new_cores_order[-1], beta)
                        if core_density >= community_search_density and [
                                1 if i > j else -1 if i < j else 0
                                for i, j in zip(new_cores_order[-1],
                                                community_search_vector)
                        ].count(1) > 0:
                            community_search_density = core_density
                            community_search_nodes = new_cores[
                                new_cores_order[-1]]
                            community_search_layers = core_layers
                            community_search_vector = new_cores_order[-1]
                    except IndexError:
                        pass

                    # add the new cores to computed_core_vectors
                    computed_core_vectors |= set(new_cores)

            # for each layer not in base_layers
            for layer in layers - base_layers:
                # compute its core decomposition
                if vector[layer] == 0:
                    new_cores, new_cores_order = core_decomposition(
                        multilayer_graph,
                        vector,
                        layer,
                        nodes,
                        query_nodes=query_nodes)
                    number_of_computed_cores += len(new_cores) + 1

                    # update the community search solution if needed
                    try:
                        core_density, core_layers = objective_function(
                            new_cores_order[-1], beta)
                        if core_density >= community_search_density and [
                                1 if i > j else -1 if i < j else 0
                                for i, j in zip(new_cores_order[-1],
                                                community_search_vector)
                        ].count(1) > 0:
                            community_search_density = core_density
                            community_search_nodes = new_cores[
                                new_cores_order[-1]]
                            community_search_layers = core_layers
                            community_search_vector = new_cores_order[-1]
                    except IndexError:
                        pass

                    # add the new cores to computed_core_vectors
                    computed_core_vectors |= set(new_cores)

            # remove every node from the processed core to save memory
            base_cores[vector] = array('i')

        # update the base
        base_cores = temp_base_cores

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm_community_search(execution_time.execution_time_seconds,
                                         number_of_computed_cores)
    print_community_search(query_nodes, beta, community_search_density,
                           community_search_nodes, community_search_layers,
                           community_search_vector)
def densest_subgraph(multilayer_graph, beta):
    # start of the algorithm
    execution_time = ExecutionTime()

    # create the vector of zeros from which start the computation
    start_vector = tuple([0] * multilayer_graph.number_of_layers)

    # dict of cores
    cores = {}

    # solution initialized with the objective function of the whole input graph
    densest_subgraph = array('i', multilayer_graph.get_nodes())
    maximum_density, maximum_layers, maximum_average_degrees = objective_function(
        multilayer_graph.number_of_nodes,
        multilayer_graph.get_number_of_edges_layer_by_layer(), beta)
    densest_subgraph_vector = start_vector

    # initialize the queue of vectors with the descendants of start_vector and the structure that for each vector saves its ancestor vectors
    vectors_queue = deque()
    ancestors = {}
    for index in multilayer_graph.layers_iterator:
        descendant_vector = build_descendant_vector(start_vector, index)
        vectors_queue.append(descendant_vector)
        ancestors[descendant_vector] = [start_vector]

    # initialize the dictionary that for each vector counts the number of descendants in the queue
    descendants_count = defaultdict(int)

    # while vectors_queue is not empty
    while len(vectors_queue) > 0:
        # remove a vector from vectors_queue (FIFO policy)
        vector = vectors_queue.popleft()

        # if the number of non zero indexes of vector is equal to the number of its ancestors, build the intersection of its ancestor cores
        number_of_non_zero_indexes = len(
            [index for index in vector if index > 0])
        number_of_ancestors = len(ancestors[vector])
        if number_of_non_zero_indexes == number_of_ancestors:
            ancestors_intersection = build_ancestors_intersection(
                ancestors[vector],
                cores,
                descendants_count,
                False,
                multilayer_graph=multilayer_graph)

            # if the intersection of its ancestor cores is not empty
            if len(ancestors_intersection) > 0:
                # compute the core from it
                core_result = core(multilayer_graph, beta, vector,
                                   ancestors_intersection)
                k_core = core_result[0]
            # otherwise
            else:
                # delete its entry from ancestors and continue
                del ancestors[vector]
                continue

            # if the core is not empty
            if len(k_core) > 0:
                # add the core to the dict of cores and increment the number of cores
                cores[vector] = k_core

                # update the densest subgraph if needed
                current_objective_function = core_result[1]
                if current_objective_function[0] >= maximum_density:
                    densest_subgraph = k_core
                    maximum_density = current_objective_function[0]
                    maximum_layers = current_objective_function[1]
                    maximum_average_degrees = current_objective_function[2]
                    densest_subgraph_vector = vector

                # compute its descendant vectors
                for index in multilayer_graph.layers_iterator:
                    descendant_vector = build_descendant_vector(vector, index)

                    try:
                        # update the list of the ancestors of the descendant vector
                        ancestors[descendant_vector].append(vector)

                    # if the descendant vector has not already been found
                    except KeyError:
                        # add the descendant vector to the queue
                        vectors_queue.append(descendant_vector)
                        ancestors[descendant_vector] = [vector]

                    # increment descendants_count
                    descendants_count[vector] += 1
        else:
            # for each ancestor of vector
            for ancestor in ancestors[vector]:
                # decrement its number of descendants
                decrement_descendants_count(ancestor, cores, descendants_count,
                                            False)

        # delete vector's entry from ancestors
        del ancestors[vector]

    # end of the algorithm
    execution_time.end_algorithm()

    # print the densest subgraph
    print_densest_subgraph(beta, maximum_density, densest_subgraph,
                           maximum_layers, densest_subgraph_vector,
                           maximum_average_degrees)
Ejemplo n.º 17
0
def depth_first(multilayer_graph, print_file, distinct_flag):
    # measures
    number_of_computed_cores = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # create the vector of zeros from which start the computation
    start_vector = tuple([0] * multilayer_graph.number_of_layers)

    # dict of cores
    cores = {}

    # core [0]
    if print_file is not None and not distinct_flag:
        print_file.print_core(start_vector,
                              array('i', multilayer_graph.get_nodes()))
    elif distinct_flag:
        cores[start_vector] = array('i', multilayer_graph.get_nodes())

    # initialize the set of layers
    layers = set(multilayer_graph.layers_iterator)

    # initialize the base of layers
    base_layers = set(layers)

    # initialize the base of cores
    base_cores = {start_vector: array('i', multilayer_graph.nodes_iterator)}

    # set of the vectors corresponding to the computed cores
    computed_core_vectors = set()
    computed_core_vectors.add(start_vector)

    # for each layer
    while len(base_layers) > 0:
        # delete a layer from base_layers
        base_layers.pop()

        # set of the temporary base of cores
        temp_base_cores = {}

        # for each core in the base
        for vector, nodes in base_cores.iteritems():
            # for each layer in the base
            for base_layer in base_layers:
                # compute its core decomposition and store it in temp_base_cores
                if vector[base_layer] == 0:
                    new_cores, _ = core_decomposition(multilayer_graph, vector,
                                                      base_layer, nodes)
                    temp_base_cores.update(new_cores)
                    number_of_computed_cores += len(new_cores) + 1

                    new_cores_set = set(new_cores)
                    if print_file is not None and not distinct_flag:
                        for new_core in new_cores_set - computed_core_vectors:
                            print_file.print_core(new_core,
                                                  new_cores[new_core])
                    elif distinct_flag:
                        for new_core in new_cores_set - computed_core_vectors:
                            cores[new_core] = new_cores[new_core]
                    # add the new cores to computed_core_vectors
                    computed_core_vectors |= new_cores_set

            # for each layer not in base_layers
            for layer in layers - base_layers:
                # compute its core decomposition
                if vector[layer] == 0:
                    new_cores, _ = core_decomposition(multilayer_graph, vector,
                                                      layer, nodes)
                    number_of_computed_cores += len(new_cores) + 1

                    new_cores_set = set(new_cores)
                    if print_file is not None and not distinct_flag:
                        for new_core in new_cores_set - computed_core_vectors:
                            print_file.print_core(new_core,
                                                  new_cores[new_core])
                    elif distinct_flag:
                        for new_core in new_cores_set - computed_core_vectors:
                            cores[new_core] = new_cores[new_core]
                    # add the new cores to computed_core_vectors
                    computed_core_vectors |= new_cores_set

            # remove every node from the processed core to save memory
            base_cores[vector] = array('i')

        # update the base
        base_cores = temp_base_cores

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds,
                        len(computed_core_vectors), number_of_computed_cores)

    # execute the post processing
    post_processing(cores, distinct_flag, print_file)
Ejemplo n.º 18
0
def naive(multilayer_graph, print_file, distinct_flag):
    # measures
    number_of_cores = 0
    number_of_computed_cores = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # create the vector of zeros from which start the computation
    start_vector = tuple([0] * multilayer_graph.number_of_layers)

    # dict of cores
    cores = {}

    # core [0]
    if print_file is not None and not distinct_flag:
        print_file.print_core(start_vector,
                              array('i', multilayer_graph.get_nodes()))
    elif distinct_flag:
        cores[start_vector] = array('i', multilayer_graph.get_nodes())
    number_of_cores += 1

    # initialize the queue of vectors with the descendants of start_vector
    vectors_queue = deque()
    computed_vectors = set()
    for index in multilayer_graph.layers_iterator:
        descendant_vector = build_descendant_vector(start_vector, index)
        vectors_queue.append(descendant_vector)
        computed_vectors.add(descendant_vector)

    # set of the nodes of the input graph
    nodes = set(multilayer_graph.nodes_iterator)

    # while vectors_queue is not empty
    while len(vectors_queue) > 0:
        # remove a vector from vectors_queue (FIFO policy)
        vector = vectors_queue.popleft()

        # compute the corresponding core
        k_core = core(multilayer_graph, vector, nodes)
        number_of_computed_cores += 1

        # if the core is not empty
        if len(k_core) > 0:
            # add the core to the dict of cores and increment the number of cores
            if print_file is not None and not distinct_flag:
                print_file.print_core(vector, k_core)
            elif distinct_flag:
                cores[vector] = k_core
            number_of_cores += 1

            # compute its descendant vectors
            for index in multilayer_graph.layers_iterator:
                descendant_vector = build_descendant_vector(vector, index)

                # if the descendant vector has not already been added to the queue
                if descendant_vector not in computed_vectors:
                    # add the descendant vector to the queue
                    vectors_queue.append(descendant_vector)
                    computed_vectors.add(descendant_vector)

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds, number_of_cores,
                        number_of_computed_cores)

    # execute the post processing
    post_processing(cores, distinct_flag, print_file)
def greedy_degree_removal(signed_graph, signed_degree=True):
    # start of the algorithm
    execution_time = ExecutionTime()

    # initialize the solution with all nodes
    solution = set(signed_graph.nodes_iterator)
    solution_x = build_x(signed_graph, solution)
    solution_objective_function = evaluate_objective_function(
        signed_graph, solution_x)

    # compute the degree of each node and divide them in sets
    degree = {}
    degree_sets = sorteddict()

    for node, neighbors in enumerate(signed_graph.adjacency_list):
        degree[node] = len(neighbors[0])
        if signed_degree:
            degree[node] -= len(neighbors[1])

        try:
            degree_sets[degree[node]].add(node)
        except KeyError:
            degree_sets[degree[node]] = {node}

    # pick a lowest degree node
    nodes = solution.copy()
    x = solution_x.copy()
    while len(degree_sets) > 0:
        lowest_degree = degree_sets.keys()[0]
        while len(degree_sets[lowest_degree]) > 0:
            node = degree_sets[lowest_degree].pop()

            # update the degree of its neighbors
            for neighbor in signed_graph.adjacency_list[node][0]:
                if neighbor in nodes:
                    degree_sets[degree[neighbor]].remove(neighbor)
                    degree[neighbor] -= 1
                    try:
                        degree_sets[degree[neighbor]].add(neighbor)
                    except KeyError:
                        degree_sets[degree[neighbor]] = {neighbor}
                        if degree[neighbor] < lowest_degree:
                            lowest_degree = degree[neighbor]

            if signed_degree:
                for neighbor in signed_graph.adjacency_list[node][1]:
                    if neighbor in nodes:
                        degree_sets[degree[neighbor]].remove(neighbor)
                        degree[neighbor] += 1
                        try:
                            degree_sets[degree[neighbor]].add(neighbor)
                        except KeyError:
                            degree_sets[degree[neighbor]] = {neighbor}

            # remove the node from the current set of nodes
            nodes.remove(node)

            # update the solution if needed
            x[node] = 0
            objective_function = evaluate_objective_function(signed_graph, x)
            if objective_function > solution_objective_function:
                solution = nodes.copy()
                solution_x = x.copy()
                solution_objective_function = objective_function

        # remove the empty set from the dict
        del degree_sets[lowest_degree]

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds, solution_x,
                        signed_graph)

    # return the solution
    return solution, solution_x
def local_search(signed_graph,
                 maximum_changes,
                 convergence_threshold,
                 partial_solution='r'):
    # start of the algorithm
    execution_time = ExecutionTime()

    # solution and value of the objective function
    if partial_solution == 'b':
        solution, _, original_x = bansal(signed_graph, verbose=False)
    else:
        solution = random_solution(signed_graph)
        original_x = build_x(signed_graph, set(signed_graph.nodes_iterator))
    solution_x = build_x(signed_graph, solution, eigenvector=original_x)
    solution_objective_function = evaluate_objective_function(
        signed_graph, solution_x)

    # while there might be improvements to the solution
    improvable = True
    changes = 0
    while improvable and (maximum_changes is None
                          or changes < maximum_changes):
        # find the node of highest gain
        best_node = None
        best_gain = .0

        # move each node in or out the solution
        for node in signed_graph.nodes_iterator:
            if node in solution:
                solution.remove(node)
                solution_x[node] = 0

                objective_function = evaluate_objective_function(
                    signed_graph, solution_x)

                solution.add(node)
                solution_x[node] = original_x[node]
            else:
                solution.add(node)
                solution_x[node] = original_x[node]

                objective_function = evaluate_objective_function(
                    signed_graph, solution_x)

                solution.remove(node)
                solution_x[node] = 0

            # update the node of highest gain
            gain = objective_function - solution_objective_function
            if gain > best_gain:
                best_node = node
                best_gain = gain

        # update the solution if there is a considerable gain
        if best_gain >= convergence_threshold:
            if best_node in solution:
                solution.remove(best_node)
                solution_x[best_node] = 0
            else:
                solution.add(best_node)
                solution_x[best_node] = original_x[best_node]

            solution_objective_function = evaluate_objective_function(
                signed_graph, solution_x)
            changes += 1
        else:
            # stop the algorithm otherwise
            improvable = False

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds, solution_x,
                        signed_graph)

    # return the solution
    return solution, solution_x
def hybrid_community_search(multilayer_graph, query_nodes, beta):
    # measures
    number_of_computed_cores = 0

    # start of the algorithm
    execution_time = ExecutionTime()

    # create the vector of zeros from which start the computation
    start_vector = tuple([0] * multilayer_graph.number_of_layers)

    # dict of cores
    cores = {}

    # solution initialized with the whole input graph
    community_search_density = 0.0
    community_search_nodes = array('i', multilayer_graph.get_nodes())
    community_search_layers = set(multilayer_graph.layers_iterator)
    community_search_vector = start_vector

    # initialize the queue of vectors with the descendants of start_vector and the structure that for each vector saves its ancestor vectors
    vectors_queue = deque()
    ancestors = {}
    for index in multilayer_graph.layers_iterator:
        descendant_vector = build_descendant_vector(start_vector, index)
        vectors_queue.append(descendant_vector)
        ancestors[descendant_vector] = [start_vector]

    # initialize the dictionary that for each vector counts the number of descendants in the queue
    descendants_count = defaultdict(int)

    # compute the core decomposition layer by layer
    for layer in multilayer_graph.layers_iterator:
        layer_cores, layer_cores_order = pure_core_decomposition(multilayer_graph, start_vector, layer, query_nodes=query_nodes)
        cores.update(layer_cores)

        # update the community search solution if needed
        try:
            core_density, core_layers = objective_function(layer_cores_order[-1], beta)
            if core_density >= community_search_density:
                community_search_density = core_density
                community_search_nodes = layer_cores[layer_cores_order[-1]]
                community_search_layers = core_layers
                community_search_vector = layer_cores_order[-1]
        except IndexError:
            pass
    number_of_computed_cores += len(cores) + multilayer_graph.number_of_layers

    # while vectors_queue is not empty
    while len(vectors_queue) > 0:
        # remove a vector from vectors_queue (FIFO policy)
        vector = vectors_queue.popleft()

        # if the number of non zero indexes of vector is equal to the number of its ancestors and is more than 1, build the intersection of its ancestor cores
        number_of_non_zero_indexes = len([index for index in vector if index > 0])
        number_of_ancestors = len(ancestors[vector])
        if number_of_non_zero_indexes == number_of_ancestors and number_of_non_zero_indexes > 1 and vector not in cores:
            ancestors_intersection = build_ancestors_intersection(ancestors[vector], cores, descendants_count, False)

            # if the intersection of its ancestor contains the query nodes
            if query_nodes <= set(ancestors_intersection):
                # compute the core from it
                k_core, minimum_degrees_vector = core(multilayer_graph, vector, ancestors_intersection, algorithm='h')
                number_of_computed_cores += 1

                # if the core contains the query nodes
                if query_nodes <= set(k_core):
                    # add the core to the dict of cores
                    cores[vector] = k_core

                    # if the vector of the minimum degrees is not equal to vector
                    if minimum_degrees_vector != vector:
                        # fill the cores that are equals
                        bottom_up_visit(multilayer_graph, minimum_degrees_vector, vector, cores, None, False)

                    # update the community search solution if needed
                    core_density, core_layers = objective_function(minimum_degrees_vector, beta)
                    if core_density >= community_search_density:
                        community_search_density = core_density
                        community_search_nodes = k_core
                        community_search_layers = core_layers
                        community_search_vector = minimum_degrees_vector
        else:
            # for each ancestor of vector
            for ancestor in ancestors[vector]:
                # decrement its number of descendants
                decrement_descendants_count(ancestor, cores, descendants_count, False)

        # if the core corresponding to the vector is in the dict of cores
        if vector in cores:
            # compute its descendant vectors
            for index in multilayer_graph.layers_iterator:
                descendant_vector = build_descendant_vector(vector, index)

                try:
                    # update the list of the ancestors of the descendant vector
                    ancestors[descendant_vector].append(vector)

                # if the descendant vector has not already been found
                except KeyError:
                    # add the descendant vector to the queue
                    vectors_queue.append(descendant_vector)
                    ancestors[descendant_vector] = [vector]

                # increment descendants_count
                descendants_count[vector] += 1

        # delete vector's entry from ancestors
        del ancestors[vector]

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm_community_search(execution_time.execution_time_seconds, number_of_computed_cores)
    print_community_search(query_nodes, beta, community_search_density, community_search_nodes, community_search_layers, community_search_vector)