Implementation and benchmarking of algorithms for the Maximum Common Edge Subgraph (MCES) problem with interactive web visualizer.
The Maximum Common Edge Subgraph (MCES) problem is a fundamental problem in graph theory: given two graphs
- NP-complete for general graphs
- APX-hard: difficult to approximate within a constant factor
- Generalizes well-known problems such as maximum clique and subgraph isomorphism
Practical applications:
- Computational chemistry: Comparison of molecular structures and similarity between compounds
- Biology: Network alignment for protein networks across species
- Pattern recognition: Object recognition in images
- Social network analysis: Study of common structures in social networks
The project includes six algorithms covering the entire spectrum of approaches:
- Brute Force - Complete enumeration (baseline)
- Brute Force with Pruning + Backtracking - With intelligent pruning
- Connected MCES - Guarantees connected subgraphs
- Greedy Path - Fast constructive heuristic based on paths
- ILP R2 - Integer Linear Programming with PuLP solver
- Simulated Annealing - Metaheuristic for large graphs
Each algorithm returns:
- Node mapping between the two graphs
- Preserved edges in the common subgraph
- Detailed statistics (time, explored space, optimality, memory)
The benchmark systematically compares all algorithms on graphs of varying sizes:
# Install dependencies
pip install -r requirements.txt
# Run the benchmark
python benchmark.pyConfigurable parameters (modifiable at the top of benchmark.py):
N_MIN,N_MAX: Node range (default: 7-12)EDGE_MULTIPLIERS: Edge density (default: [1.2, 1.5, 2.0])REPEATS: Repetitions per configuration (default: 5)PER_CALL_TIMEOUT: Timeout per algorithm in seconds (default: 300)RANDOM_SEED: Seed for reproducibility (default: 9871)
The benchmark generates:
results/YYYYMMDD-HHMMSS/benchmark_results.csv- Detailed resultsresults/YYYYMMDD-HHMMSS/metadata.json- Exact execution configuration
After running the benchmark, generate analysis plots:
python plot.py results/YYYYMMDD-HHMMSS/benchmark_results.csvReplace YYYYMMDD-HHMMSS with your actual results timestamp folder. This creates SVG plots in the results/YYYYMMDD-HHMMSS/graphs/ folder:
performance_summary.svg- Overall performance comparisontime_vs_graph_size.svg- Scalability with number of nodestime_vs_edges.svg- Effect of graph densityheatmap_time_by_size.svg- Heatmap of execution timessolution_quality.svg- Quality of solutions foundsearch_space_exploration.svg- Search space exploredtimeout_analysis.svg- Timeout analysis per algorithm
- Parallelization: 5 worker threads for concurrent executions
- Robust timeouts: Each algorithm executed in separate process with forced termination
- Reproducibility: Fixed seed, complete metadata, Docker support
- Complete metrics: Time, memory, explored space, optimality
- Incremental output: CSV written in real-time with file locking
The project also includes a web interface to generate and visualize graphs interactively.
docker compose upAccess at:
- Frontend: http://localhost:8000
- Backend API: http://localhost:5001
Backend:
cd backend
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txt
python app.pyFrontend:
cd frontend
python -m http.server 8000Open http://localhost:8000 in your browser.
- Random graph generation with configurable parameters
- Side-by-side visualization with force-directed layout
- Real-time MCES algorithm execution (for small graphs)
- Mapping and preserved edges visualization
- Performance statistics
The project follows the Conventional Commits specification. Install git hooks:
pre-commit install
pre-commit install --hook-type commit-msgRequest:
{
"num_nodes": 8,
"num_edges": 12,
"algorithm": "bruteforce_pruning"
}Available algorithms:
"none"- Graph generation only"bruteforce"- Complete brute force"bruteforce_pruning"- With pruning"connected_mces"- Connected subgraphs"greedy_path_mces"- Greedy heuristic"ilp_r2"- Integer Linear Programming"simulated_annealing"- Simulated Annealing
Response:
{
"graph1": {
"nodes": [{"id": "1"}, {"id": "2"}],
"edges": [{"source": "1", "target": "2"}]
},
"graph2": { "nodes": [...], "edges": [...] },
"mces": {
"algorithm": "bruteforce_pruning",
"result": {
"mapping": {"1": "3", "2": "4"},
"preserved_edges": [["1", "2"]],
"stats": {
"time_ms": 1.2,
"mappings_explored": 120,
"recursive_calls": 45,
"pruned_branches": 30,
"memory_usage_mb": 2.5,
"solution_optimality": true
}
}
}
}Notes:
- Undirected graphs with string node IDs
- Nessun self-loop o archi duplicati
- Con
num_nodes > 1, ogni nodo ha almeno un arco
cd backend
pytestApache 2.0 - See LICENSE for details.
- Bahiense, L., et al. (2012). "The maximum common edge subgraph problem: A polyhedral investigation"
- Larsen, S. J., et al. (2016). "A Simulated Annealing Algorithm for Maximum Common Edge Subgraph Detection"
- Akutsu, T., & Tamura, T. (2013). "A Polynomial-Time Algorithm for Computing the Maximum Common Connected Edge Subgraph"
Contributions are welcome! See CONTRIBUTING.md for guidelines.