-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
137 lines (111 loc) · 5.21 KB
/
main.py
File metadata and controls
137 lines (111 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import time
import warnings
# Import modules from our project
from core import calculate_loop_modulus_rho_preprocessed
from plotting import plot_initial_cycles, plot_final_rho
from utils import create_weighted_graph, check_louvain_availability
# Suppress warnings
warnings.filterwarnings("ignore", category=RuntimeWarning)
def main():
"""
Demonstrate the usage of loop modulus calculation with a sample graph.
Uses Karate Club as an example.
"""
print("=== Network Loop Modulus Demo ===")
# Check if louvain is available for later community detection example
has_louvain = check_louvain_availability()
if not has_louvain:
print("Warning: 'python-louvain' not installed. Louvain community detection will be skipped.")
print("Install it via: pip install python-louvain")
# --- Create or load a graph ---
print("\n--- Creating Sample Graph ---")
G = nx.karate_club_graph()
print(f"Sample Graph: Karate Club")
print(f" Nodes: {G.number_of_nodes()}")
print(f" Edges: {G.number_of_edges()}")
# --- Set Parameters ---
print("\n--- Setting Parameters ---")
TOLERANCE = 1e-4
MAX_ITER = 500 # Max iterations after initial solve
INITIAL_SET_SIZE = 20 # Target number of cycles from preprocessing
OVERLAP_ALPHA = 0.1 # Penalty for overlap in preprocessing
OSQP_ABS_TOL = 1e-5
OSQP_REL_TOL = 1e-5
CYCLES_PER_ITER = 5 # Add top 5 new violated cycles each outer iteration
PARALLEL_SEEDS = 4 # Parallel Dijkstra runs per iteration
PRINT_INTERVAL = 10 # Print progress every 10 iterations
print(f" Tolerance: {TOLERANCE}")
print(f" Max Iterations: {MAX_ITER}")
print(f" Initial Set Size: {INITIAL_SET_SIZE}")
print(f" Cycles per Iter: {CYCLES_PER_ITER}")
print(f" Parallel Seeds: {PARALLEL_SEEDS}")
# --- Run the Calculation ---
print("\n--- Running Loop Modulus Calculation ---")
start_time = time.time()
final_rho_star_map, edge_list, added_cycles, final_modulus, qp_solves_count, alg_time = \
calculate_loop_modulus_rho_preprocessed(
graph=G,
tolerance=TOLERANCE,
max_iterations=MAX_ITER,
initial_set_target_size=INITIAL_SET_SIZE,
overlap_penalty_alpha=OVERLAP_ALPHA,
osqp_eps_abs=OSQP_ABS_TOL,
osqp_eps_rel=OSQP_REL_TOL,
cycles_to_add_per_iter=CYCLES_PER_ITER,
parallel_seeds=PARALLEL_SEEDS,
print_interval=PRINT_INTERVAL
)
end_time = time.time()
total_time = end_time - start_time
# --- Display Results ---
print("\n=== Final Results ===")
print(f"QP Solves: {qp_solves_count}")
print(f"Algorithm Time (s): {alg_time:.2f}")
print(f"Total Runtime (s): {total_time:.2f}")
print(f"Final Modulus: {final_modulus:.6f}")
print(f"Total Constraints Added: {len(added_cycles)}")
# --- Create weighted graph for further analysis ---
G_weighted = create_weighted_graph(G, final_rho_star_map)
print(f"Created weighted graph with {G_weighted.number_of_edges()} edges")
# --- Community Detection example with weighted graph ---
if has_louvain:
try:
import community.community_louvain as community_louvain
print("\n--- Running Community Detection with Rho* Weights ---")
print("Using Louvain algorithm on original graph vs. rho*-weighted graph")
# Detect communities on the original graph
partition_orig = community_louvain.best_partition(G)
orig_communities = len(set(partition_orig.values()))
print(f"Original Graph Communities: {orig_communities}")
# Detect communities on the rho*-weighted graph
partition_weighted = community_louvain.best_partition(G_weighted)
weighted_communities = len(set(partition_weighted.values()))
print(f"Rho*-Weighted Graph Communities: {weighted_communities}")
except Exception as e:
print(f"Error in community detection: {e}")
# --- Visualization ---
try:
# Create a layout for the graph
pos = nx.spring_layout(G, seed=42)
print("\n--- Creating Visualizations ---")
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 8))
# Plot initial cycles
initial_cycles = added_cycles[:INITIAL_SET_SIZE] # First cycles are the initial ones
plot_initial_cycles(G, pos, initial_cycles, ax=ax1,
title=f"Initial Cycle Set (n={len(initial_cycles)})")
# Plot final rho* values
plot_final_rho(G, pos, final_rho_star_map, edge_list, ax=ax2,
title=f"Final Rho* Values (Mod2≈{final_modulus:.2f})")
plt.tight_layout()
plt.savefig("loop_modulus_results.png", dpi=300, bbox_inches='tight')
print("Saved visualization to 'loop_modulus_results.png'")
# Optional: Show plot
# plt.show()
except Exception as e:
print(f"Error in visualization: {e}")
print("\nDemo complete!")
if __name__ == "__main__":
main()