alonso 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- alonso/__init__.py +4 -0
- alonso/algorithm.py +115 -0
- alonso/app.py +98 -0
- alonso/applogger.py +80 -0
- alonso/batch.py +53 -0
- alonso/merge.py +125 -0
- alonso/parser.py +79 -0
- alonso/partition.py +216 -0
- alonso/stable.py +186 -0
- alonso/test.py +118 -0
- alonso/utils.py +257 -0
- alonso-0.0.1.dist-info/METADATA +267 -0
- alonso-0.0.1.dist-info/RECORD +17 -0
- alonso-0.0.1.dist-info/WHEEL +5 -0
- alonso-0.0.1.dist-info/entry_points.txt +4 -0
- alonso-0.0.1.dist-info/licenses/LICENSE +21 -0
- alonso-0.0.1.dist-info/top_level.txt +1 -0
alonso/partition.py
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
import networkx as nx
|
2
|
+
from typing import Tuple, Set, List
|
3
|
+
from collections import defaultdict
|
4
|
+
import itertools
|
5
|
+
import mendive.algorithm as claws
|
6
|
+
|
7
|
+
class BurrErdosLovaszPartitioner:
|
8
|
+
"""
|
9
|
+
Implementation of the Burr-Erdős-Lovász (1976) algorithm for partitioning
|
10
|
+
edges of a graph into two subsets such that each subset induces a k-star-free subgraph.
|
11
|
+
|
12
|
+
For k=3 (claw-free case), we partition edges to avoid 3-stars in each partition.
|
13
|
+
|
14
|
+
The algorithm works by maintaining two edge sets and for each new edge,
|
15
|
+
assigning it to the partition where it creates the fewest violations,
|
16
|
+
then locally repairing any violations that arise.
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(self, graph: nx.Graph, k: int = 3):
|
20
|
+
self.graph = graph.copy()
|
21
|
+
self.k = k # k=3 for claw-free (3-star-free)
|
22
|
+
self.n = len(graph.nodes())
|
23
|
+
|
24
|
+
def partition_edges(self) -> Tuple[Set[Tuple[int, int]], Set[Tuple[int, int]]]:
|
25
|
+
"""
|
26
|
+
Partition edges into two k-star-free subgraphs using BEL algorithm.
|
27
|
+
"""
|
28
|
+
E1 = set()
|
29
|
+
E2 = set()
|
30
|
+
|
31
|
+
# Convert edges to consistent format
|
32
|
+
edges = [(min(u, v), max(u, v)) for u, v in self.graph.edges()]
|
33
|
+
|
34
|
+
# Main algorithm: assign each edge to minimize violations
|
35
|
+
for edge in edges:
|
36
|
+
# Count violations if we add edge to E1
|
37
|
+
violations_E1 = self._count_violations_after_adding(E1, edge)
|
38
|
+
violations_E2 = self._count_violations_after_adding(E2, edge)
|
39
|
+
|
40
|
+
# Add to partition with fewer violations
|
41
|
+
if violations_E1 <= violations_E2:
|
42
|
+
E1.add(edge)
|
43
|
+
# Repair violations in E1
|
44
|
+
E1 = self._repair_violations(E1)
|
45
|
+
else:
|
46
|
+
E2.add(edge)
|
47
|
+
# Repair violations in E2
|
48
|
+
E2 = self._repair_violations(E2)
|
49
|
+
|
50
|
+
return E1, E2
|
51
|
+
|
52
|
+
def _count_violations_after_adding(self, edge_set: Set[Tuple[int, int]],
|
53
|
+
new_edge: Tuple[int, int]) -> int:
|
54
|
+
"""Count number of k-stars that would be created by adding new_edge."""
|
55
|
+
temp_set = edge_set | {new_edge}
|
56
|
+
return self._count_k_stars(temp_set)
|
57
|
+
|
58
|
+
def _is_claw_free(self, edge_set: Set[Tuple[int, int]]) -> bool:
|
59
|
+
"""Count number of k-stars in the edge set."""
|
60
|
+
if not edge_set:
|
61
|
+
return True
|
62
|
+
|
63
|
+
# Build graph from edge set
|
64
|
+
G = nx.Graph()
|
65
|
+
G.add_edges_from(edge_set)
|
66
|
+
|
67
|
+
claw = claws.find_claw_coordinates(G, first_claw=True)
|
68
|
+
if claw is None:
|
69
|
+
return True
|
70
|
+
else:
|
71
|
+
return False
|
72
|
+
|
73
|
+
|
74
|
+
def _count_k_stars(self, edge_set: Set[Tuple[int, int]]) -> int:
|
75
|
+
"""Count number of k-stars in the edge set."""
|
76
|
+
if not edge_set:
|
77
|
+
return 0
|
78
|
+
|
79
|
+
# Build graph from edge set
|
80
|
+
G = nx.Graph()
|
81
|
+
G.add_edges_from(edge_set)
|
82
|
+
|
83
|
+
k_star_count = 0
|
84
|
+
|
85
|
+
if self.k == 3:
|
86
|
+
all_claws = claws.find_claw_coordinates(G, first_claw=False)
|
87
|
+
if all_claws is not None:
|
88
|
+
k_star_count = len(all_claws)
|
89
|
+
else:
|
90
|
+
# Check each vertex as potential center of k-star
|
91
|
+
for center in G.nodes():
|
92
|
+
neighbors = list(G.neighbors(center))
|
93
|
+
if len(neighbors) >= self.k:
|
94
|
+
# Count k-subsets of neighbors that form independent sets
|
95
|
+
for k_subset in itertools.combinations(neighbors, self.k):
|
96
|
+
# Check if this k-subset is independent
|
97
|
+
is_independent = True
|
98
|
+
for i in range(self.k):
|
99
|
+
for j in range(i + 1, self.k):
|
100
|
+
if G.has_edge(k_subset[i], k_subset[j]):
|
101
|
+
is_independent = False
|
102
|
+
break
|
103
|
+
if not is_independent:
|
104
|
+
break
|
105
|
+
|
106
|
+
if is_independent:
|
107
|
+
k_star_count += 1
|
108
|
+
|
109
|
+
return k_star_count
|
110
|
+
|
111
|
+
def _repair_violations(self, edge_set: Set[Tuple[int, int]]) -> Set[Tuple[int, int]]:
|
112
|
+
"""
|
113
|
+
Repair k-star violations in edge_set by removing minimal edges.
|
114
|
+
This is the key part of the BEL algorithm.
|
115
|
+
"""
|
116
|
+
if not edge_set:
|
117
|
+
return edge_set
|
118
|
+
|
119
|
+
current_set = edge_set.copy()
|
120
|
+
|
121
|
+
while True:
|
122
|
+
if self.k == 3:
|
123
|
+
is_claw_free = self._is_claw_free(current_set)
|
124
|
+
if is_claw_free:
|
125
|
+
break # No more violations
|
126
|
+
violations = self._find_k_stars(current_set)
|
127
|
+
else:
|
128
|
+
violations = self._find_k_stars(current_set)
|
129
|
+
if not violations:
|
130
|
+
break # No more violations
|
131
|
+
|
132
|
+
# Find the edge that appears in most violations
|
133
|
+
edge_violation_count = defaultdict(int)
|
134
|
+
for k_star in violations:
|
135
|
+
center, leaves = k_star
|
136
|
+
# Each k-star consists of k edges from center to leaves
|
137
|
+
for leaf in leaves:
|
138
|
+
edge = (min(center, leaf), max(center, leaf))
|
139
|
+
if edge in current_set:
|
140
|
+
edge_violation_count[edge] += 1
|
141
|
+
|
142
|
+
if not edge_violation_count:
|
143
|
+
break
|
144
|
+
|
145
|
+
# Remove the edge that appears in most violations
|
146
|
+
most_violating_edge = max(edge_violation_count.keys(),
|
147
|
+
key=lambda e: edge_violation_count[e])
|
148
|
+
current_set.remove(most_violating_edge)
|
149
|
+
|
150
|
+
return current_set
|
151
|
+
|
152
|
+
def _find_k_stars(self, edge_set: Set[Tuple[int, int]]) -> List[Tuple[int, Tuple]]:
|
153
|
+
"""Find all k-stars in the edge set. Returns list of (center, leaves) tuples."""
|
154
|
+
if not edge_set:
|
155
|
+
return []
|
156
|
+
|
157
|
+
# Build graph from edge set
|
158
|
+
G = nx.Graph()
|
159
|
+
G.add_edges_from(edge_set)
|
160
|
+
|
161
|
+
k_stars = []
|
162
|
+
|
163
|
+
if self.k == 3:
|
164
|
+
all_claws = claws.find_claw_coordinates(G, first_claw=False)
|
165
|
+
if all_claws is not None:
|
166
|
+
for subset in all_claws:
|
167
|
+
subgraph = G.subgraph(subset)
|
168
|
+
sorted_nodes = sorted(list(subset), key=lambda x: subgraph.degree(x))
|
169
|
+
center = sorted_nodes.pop()
|
170
|
+
k_subset = tuple(sorted_nodes)
|
171
|
+
k_stars.append((center, k_subset))
|
172
|
+
else:
|
173
|
+
# Check each vertex as potential center of k-star
|
174
|
+
for center in G.nodes():
|
175
|
+
neighbors = list(G.neighbors(center))
|
176
|
+
if len(neighbors) >= self.k:
|
177
|
+
# Find all k-subsets of neighbors that form independent sets
|
178
|
+
for k_subset in itertools.combinations(neighbors, self.k):
|
179
|
+
# Check if this k-subset is independent
|
180
|
+
is_independent = True
|
181
|
+
for i in range(self.k):
|
182
|
+
for j in range(i + 1, self.k):
|
183
|
+
if G.has_edge(k_subset[i], k_subset[j]):
|
184
|
+
is_independent = False
|
185
|
+
break
|
186
|
+
if not is_independent:
|
187
|
+
break
|
188
|
+
|
189
|
+
if is_independent:
|
190
|
+
k_stars.append((center, k_subset))
|
191
|
+
|
192
|
+
return k_stars
|
193
|
+
|
194
|
+
def verify_partition(self, E1: Set[Tuple[int, int]], E2: Set[Tuple[int, int]]) -> Tuple[bool, bool]:
|
195
|
+
"""Verify that both partitions are k-star-free."""
|
196
|
+
if self.k == 3:
|
197
|
+
return (self._is_claw_free(E1), self._is_claw_free(E2))
|
198
|
+
else:
|
199
|
+
return (self._count_k_stars(E1) == 0, self._count_k_stars(E2) == 0)
|
200
|
+
|
201
|
+
|
202
|
+
def partition_edges_claw_free(G: nx.Graph) -> Tuple[Set[Tuple[int, int]], Set[Tuple[int, int]]]:
|
203
|
+
"""
|
204
|
+
Partition edges of graph G into two sets such that each induces a claw-free subgraph.
|
205
|
+
|
206
|
+
Implementation of Burr, Erdős, Lovász (1976) algorithm for k=3 (claw-free case).
|
207
|
+
|
208
|
+
Args:
|
209
|
+
G: Undirected NetworkX graph
|
210
|
+
|
211
|
+
Returns:
|
212
|
+
(E1, E2): Two edge sets that induce claw-free subgraphs
|
213
|
+
"""
|
214
|
+
partitioner = BurrErdosLovaszPartitioner(G, k=3)
|
215
|
+
return partitioner.partition_edges()
|
216
|
+
|
alonso/stable.py
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
from collections import defaultdict
|
2
|
+
import networkx as nx
|
3
|
+
|
4
|
+
class FaenzaOrioloStaufferAlgorithm:
|
5
|
+
"""
|
6
|
+
Implementation of the Faenza, Oriolo & Stauffer (2011) algorithm
|
7
|
+
for finding maximum weighted stable set in claw-free graphs.
|
8
|
+
"""
|
9
|
+
|
10
|
+
def __init__(self, edges, weights=None):
|
11
|
+
"""
|
12
|
+
Initialize the algorithm with graph edges and optional vertex weights.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
edges: List of tuples representing edges
|
16
|
+
weights: Dictionary mapping vertices to weights (default: all weights = 1)
|
17
|
+
"""
|
18
|
+
self.edges = [(u, v) for u, v in edges]
|
19
|
+
self.vertices = set()
|
20
|
+
for u, v in self.edges:
|
21
|
+
self.vertices.add(u)
|
22
|
+
self.vertices.add(v)
|
23
|
+
self.graph = nx.Graph()
|
24
|
+
self.graph.add_edges_from(self.edges)
|
25
|
+
self.n = len(self.vertices)
|
26
|
+
if weights is None:
|
27
|
+
self.weights = {v: 1 for v in self.vertices}
|
28
|
+
else:
|
29
|
+
self.weights = {k: v for k, v in weights.items()}
|
30
|
+
|
31
|
+
# Build adjacency list
|
32
|
+
self.adj = defaultdict(set)
|
33
|
+
for u, v in self.edges:
|
34
|
+
self.adj[u].add(v)
|
35
|
+
self.adj[v].add(u)
|
36
|
+
|
37
|
+
def find_stable_set_decomposition(self):
|
38
|
+
"""
|
39
|
+
Find a stable set decomposition of the graph.
|
40
|
+
This is a key step in the FOS algorithm.
|
41
|
+
"""
|
42
|
+
# For simplicity, we'll use a greedy approach to find stable sets
|
43
|
+
# In the full algorithm, this would use more sophisticated decomposition
|
44
|
+
remaining_vertices = set(self.vertices)
|
45
|
+
stable_sets = []
|
46
|
+
|
47
|
+
while remaining_vertices:
|
48
|
+
# Greedy maximal stable set
|
49
|
+
current_stable = set()
|
50
|
+
vertices_to_check = list(remaining_vertices)
|
51
|
+
|
52
|
+
for v in vertices_to_check:
|
53
|
+
if v in remaining_vertices:
|
54
|
+
# Check if v can be added to current stable set
|
55
|
+
can_add = True
|
56
|
+
for u in current_stable:
|
57
|
+
if u in self.adj[v]:
|
58
|
+
can_add = False
|
59
|
+
break
|
60
|
+
|
61
|
+
if can_add:
|
62
|
+
current_stable.add(v)
|
63
|
+
remaining_vertices.remove(v)
|
64
|
+
|
65
|
+
if current_stable:
|
66
|
+
stable_sets.append(current_stable)
|
67
|
+
|
68
|
+
return stable_sets
|
69
|
+
|
70
|
+
def solve_weighted_stable_set_on_clique(self, clique_vertices):
|
71
|
+
"""
|
72
|
+
Solve maximum weighted stable set on a clique (trivial: pick heaviest vertex).
|
73
|
+
"""
|
74
|
+
if not clique_vertices:
|
75
|
+
return set(), 0
|
76
|
+
|
77
|
+
best_vertex = max(clique_vertices, key=lambda v: self.weights[v])
|
78
|
+
return {best_vertex}, self.weights[best_vertex]
|
79
|
+
|
80
|
+
def is_clique(self, vertices):
|
81
|
+
"""Check if given vertices form a clique."""
|
82
|
+
G = self.graph.subgraph(vertices)
|
83
|
+
n = G.number_of_nodes()
|
84
|
+
if n < 2:
|
85
|
+
return True
|
86
|
+
e = G.number_of_edges()
|
87
|
+
max_edges = (n * (n - 1)) / 2
|
88
|
+
return e == max_edges
|
89
|
+
|
90
|
+
def find_maximum_weighted_stable_set(self):
|
91
|
+
"""
|
92
|
+
Main algorithm to find maximum weighted stable set.
|
93
|
+
This implements the core FOS algorithm structure.
|
94
|
+
"""
|
95
|
+
# Base cases
|
96
|
+
if not self.vertices:
|
97
|
+
return set(), 0
|
98
|
+
|
99
|
+
if len(self.vertices) == 1:
|
100
|
+
v = next(iter(self.vertices))
|
101
|
+
return {v}, self.weights[v]
|
102
|
+
|
103
|
+
# Check if graph is a clique
|
104
|
+
if self.is_clique(self.vertices):
|
105
|
+
return self.solve_weighted_stable_set_on_clique(self.vertices)
|
106
|
+
|
107
|
+
# For claw-free graphs, we use dynamic programming approach
|
108
|
+
# This is a simplified version of the full FOS algorithm
|
109
|
+
return self._dp_solve()
|
110
|
+
|
111
|
+
def _dp_solve(self):
|
112
|
+
"""
|
113
|
+
Dynamic programming solution for claw-free graphs.
|
114
|
+
This implements the polynomial-time algorithm structure from FOS.
|
115
|
+
"""
|
116
|
+
# Convert to networkx for easier manipulation
|
117
|
+
G = nx.Graph()
|
118
|
+
G.add_nodes_from(self.vertices)
|
119
|
+
G.add_edges_from(self.edges)
|
120
|
+
|
121
|
+
# Use complement graph approach for stable set = clique in complement
|
122
|
+
G_complement = nx.complement(G)
|
123
|
+
|
124
|
+
# Find all maximal cliques in complement (these are maximal stable sets in original)
|
125
|
+
maximal_stable_sets = list(nx.find_cliques(G_complement))
|
126
|
+
|
127
|
+
# Find the one with maximum weight
|
128
|
+
best_stable_set = set()
|
129
|
+
best_weight = 0
|
130
|
+
|
131
|
+
for stable_set in maximal_stable_sets:
|
132
|
+
weight = sum(self.weights[v] for v in stable_set)
|
133
|
+
if weight > best_weight:
|
134
|
+
best_weight = weight
|
135
|
+
best_stable_set = set(stable_set)
|
136
|
+
|
137
|
+
# Also check individual vertices
|
138
|
+
for v in self.vertices:
|
139
|
+
if self.weights[v] > best_weight:
|
140
|
+
best_weight = self.weights[v]
|
141
|
+
best_stable_set = {v}
|
142
|
+
|
143
|
+
return best_stable_set, best_weight
|
144
|
+
|
145
|
+
def verify_stable_set(self, stable_set):
|
146
|
+
"""Verify that the given set is indeed a stable set."""
|
147
|
+
stable_list = list(stable_set)
|
148
|
+
for i in range(len(stable_list)):
|
149
|
+
for j in range(i + 1, len(stable_list)):
|
150
|
+
if stable_list[j] in self.adj[stable_list[i]]:
|
151
|
+
return False, f"Vertices {stable_list[i]} and {stable_list[j]} are adjacent"
|
152
|
+
return True, "Valid stable set"
|
153
|
+
|
154
|
+
|
155
|
+
def solve_maximum_weighted_stable_set(edges, weights=None):
|
156
|
+
"""
|
157
|
+
Solve maximum weighted stable set problem using FOS algorithm.
|
158
|
+
|
159
|
+
Args:
|
160
|
+
edges: List of edges as tuples
|
161
|
+
weights: Dictionary of vertex weights (optional, defaults to 1 for all)
|
162
|
+
|
163
|
+
Returns:
|
164
|
+
tuple: (stable_set, weight)
|
165
|
+
"""
|
166
|
+
algorithm = FaenzaOrioloStaufferAlgorithm(edges, weights)
|
167
|
+
return algorithm.find_maximum_weighted_stable_set()
|
168
|
+
|
169
|
+
def minimum_vertex_cover_claw_free(edges, weights=None):
|
170
|
+
"""
|
171
|
+
Solve minimum vertex cover problem using FOS algorithm.
|
172
|
+
|
173
|
+
Args:
|
174
|
+
edges: List of edges as tuples
|
175
|
+
weights: Dictionary of vertex weights (optional, defaults to 1 for all)
|
176
|
+
|
177
|
+
Returns:
|
178
|
+
- A minimum vertex cover
|
179
|
+
"""
|
180
|
+
algorithm = FaenzaOrioloStaufferAlgorithm(edges, weights)
|
181
|
+
stable_set, _ = algorithm.find_maximum_weighted_stable_set()
|
182
|
+
G = nx.Graph()
|
183
|
+
G.add_edges_from(edges)
|
184
|
+
minimum_vertex_cover = set(G.nodes) - stable_set
|
185
|
+
return minimum_vertex_cover
|
186
|
+
|
alonso/test.py
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# Created on 21/05/2025
|
2
|
+
# Author: Frank Vega
|
3
|
+
|
4
|
+
import time
|
5
|
+
import argparse
|
6
|
+
import math
|
7
|
+
import networkx as nx
|
8
|
+
|
9
|
+
from . import algorithm
|
10
|
+
from . import applogger
|
11
|
+
from . import parser
|
12
|
+
from . import utils
|
13
|
+
|
14
|
+
def restricted_float(x):
|
15
|
+
try:
|
16
|
+
x = float(x)
|
17
|
+
except ValueError:
|
18
|
+
raise argparse.ArgumentTypeError("%r not a floating-point literal" % (x,))
|
19
|
+
|
20
|
+
if x < 0.0 or x > 1.0:
|
21
|
+
raise argparse.ArgumentTypeError("%r not in range [0.0, 1.0]"%(x,))
|
22
|
+
return x
|
23
|
+
|
24
|
+
def main():
|
25
|
+
|
26
|
+
# Define the parameters
|
27
|
+
helper = argparse.ArgumentParser(prog="test_mvc", description="The Alonso Testing Application using randomly generated, large sparse matrices.")
|
28
|
+
helper.add_argument('-d', '--dimension', type=int, help="an integer specifying the dimensions of the square matrices", required=True)
|
29
|
+
helper.add_argument('-n', '--num_tests', type=int, default=5, help="an integer specifying the number of tests to run")
|
30
|
+
helper.add_argument('-s', '--sparsity', type=restricted_float, default=0.95, help="sparsity of the matrices (0.0 for dense, close to 1.0 for very sparse)")
|
31
|
+
helper.add_argument('-a', '--approximation', action='store_true', help='enable comparison with a polynomial-time approximation approach within a factor of at most 2')
|
32
|
+
helper.add_argument('-b', '--bruteForce', action='store_true', help='enable comparison with the exponential-time brute-force approach')
|
33
|
+
helper.add_argument('-c', '--count', action='store_true', help='calculate the size of the vertex cover')
|
34
|
+
helper.add_argument('-w', '--write', action='store_true', help='write the generated random matrix to a file in the current directory')
|
35
|
+
helper.add_argument('-v', '--verbose', action='store_true', help='anable verbose output')
|
36
|
+
helper.add_argument('-l', '--log', action='store_true', help='enable file logging')
|
37
|
+
helper.add_argument('--version', action='version', version='%(prog)s 0.0.1')
|
38
|
+
|
39
|
+
# Initialize the parameters
|
40
|
+
args = helper.parse_args()
|
41
|
+
num_tests = args.num_tests
|
42
|
+
matrix_shape = (args.dimension, args.dimension)
|
43
|
+
sparsity = args.sparsity
|
44
|
+
logger = applogger.Logger(applogger.FileLogger() if (args.log) else applogger.ConsoleLogger(args.verbose))
|
45
|
+
hash_string = utils.generate_short_hash(6 + math.ceil(math.log2(num_tests))) if args.write else None
|
46
|
+
count = args.count
|
47
|
+
bruteForce = args.bruteForce
|
48
|
+
approximation = args.approximation
|
49
|
+
# Perform the tests
|
50
|
+
for i in range(num_tests):
|
51
|
+
|
52
|
+
logger.info(f"Creating Matrix {i + 1}")
|
53
|
+
|
54
|
+
sparse_matrix = utils.random_matrix_tests(matrix_shape, sparsity)
|
55
|
+
|
56
|
+
if sparse_matrix is None:
|
57
|
+
continue
|
58
|
+
|
59
|
+
graph = utils.sparse_matrix_to_graph(sparse_matrix)
|
60
|
+
logger.info(f"Matrix shape: {sparse_matrix.shape}")
|
61
|
+
logger.info(f"Number of non-zero elements: {sparse_matrix.nnz}")
|
62
|
+
logger.info(f"Sparsity: {1 - (sparse_matrix.nnz / (sparse_matrix.shape[0] * sparse_matrix.shape[1]))}")
|
63
|
+
|
64
|
+
if approximation:
|
65
|
+
logger.info("An approximate Solution with an approximation ratio of at most 2 started")
|
66
|
+
started = time.time()
|
67
|
+
|
68
|
+
approximate_result = algorithm.find_vertex_cover_approximation(graph)
|
69
|
+
|
70
|
+
logger.info(f"An approximate Solution with an approximation ratio of at most 2 done in: {(time.time() - started) * 1000.0} milliseconds")
|
71
|
+
|
72
|
+
answer = utils.string_result_format(approximate_result, count)
|
73
|
+
output = f"{i + 1}-approximation Test: {answer}"
|
74
|
+
utils.println(output, logger, args.log)
|
75
|
+
|
76
|
+
if bruteForce:
|
77
|
+
logger.info("A solution with an exponential-time complexity started")
|
78
|
+
started = time.time()
|
79
|
+
|
80
|
+
brute_force_result = algorithm.find_vertex_cover_brute_force(graph)
|
81
|
+
|
82
|
+
logger.info(f"A solution with an exponential-time complexity done in: {(time.time() - started) * 1000.0} milliseconds")
|
83
|
+
|
84
|
+
answer = utils.string_result_format(brute_force_result, count)
|
85
|
+
output = f"{i + 1}-Brute Force Test: {answer}"
|
86
|
+
utils.println(output, logger, args.log)
|
87
|
+
|
88
|
+
|
89
|
+
logger.info("Our Algorithm with an approximate solution started")
|
90
|
+
started = time.time()
|
91
|
+
|
92
|
+
novel_result = algorithm.find_vertex_cover(graph)
|
93
|
+
|
94
|
+
logger.info(f"Our Algorithm with an approximate solution done in: {(time.time() - started) * 1000.0} milliseconds")
|
95
|
+
|
96
|
+
answer = utils.string_result_format(novel_result, count)
|
97
|
+
output = f"{i + 1}-Alonso Test: {answer}"
|
98
|
+
utils.println(output, logger, args.log)
|
99
|
+
|
100
|
+
if novel_result and (bruteForce or approximation):
|
101
|
+
if bruteForce:
|
102
|
+
output = f"Exact Ratio (Alonso/Optimal): {len(novel_result)/len(brute_force_result)}"
|
103
|
+
elif approximation:
|
104
|
+
output = f"Upper Bound for Ratio (Alonso/Optimal): {2 * len(novel_result)/len(approximate_result)}"
|
105
|
+
utils.println(output, logger, args.log)
|
106
|
+
|
107
|
+
|
108
|
+
if args.write:
|
109
|
+
output = f"Saving Matrix Test {i + 1}"
|
110
|
+
utils.println(output, logger, args.log)
|
111
|
+
|
112
|
+
filename = f"sparse_matrix_{i + 1}_{hash_string}"
|
113
|
+
parser.save_sparse_matrix_to_file(sparse_matrix, filename)
|
114
|
+
output = f"Matrix Test {i + 1} written to file {filename}."
|
115
|
+
utils.println(output, logger, args.log)
|
116
|
+
|
117
|
+
if __name__ == "__main__":
|
118
|
+
main()
|