Пример #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
Пример #2
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)
Пример #3
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
Пример #4
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
Пример #5
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)
Пример #6
0
        # 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])
            nodes = array('i', map(int, split_line[2].strip().split(', ')))

            # add the core
            cores[vector] = nodes

    # filter distinct cores
    filter_distinct_cores(cores)

    # print cores to file
    for vector, nodes in cores.iteritems():
        sorted_nodes = list(nodes)
        sorted_nodes.sort()
        distinct_cores_file.write(
            str(vector) + '\t' + str(len(nodes)) + '\t' +
            str(sorted_nodes).replace('[', '').replace(']', '') + '\n')

    # end of the algorithm
    execution_time.end_algorithm()

    # print algorithm's results
    print_end_algorithm(execution_time.execution_time_seconds, len(cores),
                        None)
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 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)
Пример #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 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