From 5e68ace30db1af414eb211d84c9dae40d31fcfe8 Mon Sep 17 00:00:00 2001 From: Trutnev Aleksei Date: Sun, 1 Oct 2023 14:43:14 +0300 Subject: [PATCH] [MERGE] Multiprocessing max clique solver [MERGE] Multiprocessing max clique solver --- README.md | 4 +- benchmark_coloring.py | 4 +- heurograph/clique/greedy_randomized_clique.py | 45 +++++++++++++------ 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 8b51c80..512ecbe 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # HeuroGraph Library -![GitHub stars](https://img.shields.io/github/stars/alexgiving/HeuroGraph-Library?style=social) + Welcome to the HeuroGraph-Library! This is a Python library designed for solving graph-related problems using heuristic algorithms. Whether you're working on graph coloring, maximum clique, or other graph optimization problems, this library provides a set of powerful heuristic algorithms to assist you in finding efficient solutions. diff --git a/benchmark_coloring.py b/benchmark_coloring.py index 0fb2e78..08d236b 100644 --- a/benchmark_coloring.py +++ b/benchmark_coloring.py @@ -8,8 +8,8 @@ from heurograph import Graph from heurograph.coloring import (color_graph_greedy_randomized_sorted, - color_graph_greedy_sorted, - color_graph_greedy_sorted_shuffled) + color_graph_greedy_sorted, + color_graph_greedy_sorted_shuffled) class ResultColumns(Enum): diff --git a/heurograph/clique/greedy_randomized_clique.py b/heurograph/clique/greedy_randomized_clique.py index dc322fa..63b0e5e 100644 --- a/heurograph/clique/greedy_randomized_clique.py +++ b/heurograph/clique/greedy_randomized_clique.py @@ -1,4 +1,6 @@ import random +from functools import partial +from multiprocessing import Pool, cpu_count import networkx as nx import numpy as np @@ -15,6 +17,22 @@ def nx_clique(graph: Graph) -> list[int]: return best_clique +def _get_clique(start_vertex: int, graph: Graph) -> list[int]: + clique = [start_vertex] + vertices_candidates = graph.neighbors(start_vertex) + np.random.shuffle(vertices_candidates) + + for vertex in vertices_candidates: + is_connected = True + for clique_vertex in clique: + if clique_vertex not in graph.neighbors(vertex): + is_connected = False + break + if is_connected: + clique.append(vertex) + return clique + + def greedy_randomized_clique(graph: Graph, iterations: int = 10) -> list[int]: best_clique = [] vertices = graph.vertexes @@ -22,20 +40,21 @@ def greedy_randomized_clique(graph: Graph, iterations: int = 10) -> list[int]: for _ in range(iterations): clique = [] random_vertex = random.choice(vertices) + clique = _get_clique(random_vertex, graph) + if len(clique) > len(best_clique): + best_clique = clique + return best_clique - clique.append(random_vertex) - vertices_candidates = graph.neighbors(random_vertex) - np.random.shuffle(vertices_candidates) +def greedy_randomized_mp_clique(graph: Graph, iterations: int = 10, num_proc: int = -1) -> list[int]: + best_clique = [] + vertices = graph.vertexes - for vertex in vertices_candidates: - is_connected = True - for clique_vertex in clique: - if clique_vertex not in graph.neighbors(vertex): - is_connected = False - break - if is_connected: - clique.append(vertex) - if len(clique) > len(best_clique): - best_clique = clique + random_vertices = np.random.choice(vertices, iterations) + num_process = num_proc if num_proc > 1 else cpu_count() + + partial_get_clique = partial(_get_clique, graph=graph) + with Pool(num_process) as pool: + cliques = pool.map(partial_get_clique, random_vertices) + best_clique = max(cliques, key=len) return best_clique