alonso 0.0.1__tar.gz
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-0.0.1/LICENSE +21 -0
- alonso-0.0.1/PKG-INFO +267 -0
- alonso-0.0.1/README.md +229 -0
- alonso-0.0.1/alonso/__init__.py +4 -0
- alonso-0.0.1/alonso/algorithm.py +115 -0
- alonso-0.0.1/alonso/app.py +98 -0
- alonso-0.0.1/alonso/applogger.py +80 -0
- alonso-0.0.1/alonso/batch.py +53 -0
- alonso-0.0.1/alonso/merge.py +125 -0
- alonso-0.0.1/alonso/parser.py +79 -0
- alonso-0.0.1/alonso/partition.py +216 -0
- alonso-0.0.1/alonso/stable.py +186 -0
- alonso-0.0.1/alonso/test.py +118 -0
- alonso-0.0.1/alonso/utils.py +257 -0
- alonso-0.0.1/alonso.egg-info/PKG-INFO +267 -0
- alonso-0.0.1/alonso.egg-info/SOURCES.txt +21 -0
- alonso-0.0.1/alonso.egg-info/dependency_links.txt +1 -0
- alonso-0.0.1/alonso.egg-info/entry_points.txt +4 -0
- alonso-0.0.1/alonso.egg-info/requires.txt +1 -0
- alonso-0.0.1/alonso.egg-info/top_level.txt +1 -0
- alonso-0.0.1/pyproject.toml +26 -0
- alonso-0.0.1/setup.cfg +4 -0
- alonso-0.0.1/setup.py +51 -0
alonso-0.0.1/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Frank Vega
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
alonso-0.0.1/PKG-INFO
ADDED
@@ -0,0 +1,267 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: alonso
|
3
|
+
Version: 0.0.1
|
4
|
+
Summary: Compute an Approximate Vertex Cover for undirected graph encoded in DIMACS format.
|
5
|
+
Home-page: https://github.com/frankvegadelgado/alonso
|
6
|
+
Author: Frank Vega
|
7
|
+
Author-email: vega.frank@gmail.com
|
8
|
+
License: MIT License
|
9
|
+
Project-URL: Source Code, https://github.com/frankvegadelgado/alonso
|
10
|
+
Project-URL: Documentation Research, https://dev.to/frank_vega_987689489099bf/challenging-the-unique-games-conjecture-12mi
|
11
|
+
Classifier: Topic :: Scientific/Engineering
|
12
|
+
Classifier: Topic :: Software Development
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
16
|
+
Classifier: Environment :: Console
|
17
|
+
Classifier: Intended Audience :: Developers
|
18
|
+
Classifier: Intended Audience :: Education
|
19
|
+
Classifier: Intended Audience :: Information Technology
|
20
|
+
Classifier: Intended Audience :: Science/Research
|
21
|
+
Classifier: Natural Language :: English
|
22
|
+
Requires-Python: >=3.10
|
23
|
+
Description-Content-Type: text/markdown
|
24
|
+
License-File: LICENSE
|
25
|
+
Requires-Dist: mendive>=0.0.4
|
26
|
+
Dynamic: author
|
27
|
+
Dynamic: author-email
|
28
|
+
Dynamic: classifier
|
29
|
+
Dynamic: description
|
30
|
+
Dynamic: description-content-type
|
31
|
+
Dynamic: home-page
|
32
|
+
Dynamic: license
|
33
|
+
Dynamic: license-file
|
34
|
+
Dynamic: project-url
|
35
|
+
Dynamic: requires-dist
|
36
|
+
Dynamic: requires-python
|
37
|
+
Dynamic: summary
|
38
|
+
|
39
|
+
# Alonso: Approximate Vertex Cover Solver
|
40
|
+
|
41
|
+

|
42
|
+
|
43
|
+
This work builds upon [Challenging the Unique Games Conjecture](https://dev.to/frank_vega_987689489099bf/challenging-the-unique-games-conjecture-12mi).
|
44
|
+
|
45
|
+
---
|
46
|
+
|
47
|
+
# The Minimum Vertex Cover Problem
|
48
|
+
|
49
|
+
The **Minimum Vertex Cover (MVC)** problem is a classic optimization problem in computer science and graph theory. It involves finding the smallest set of vertices in a graph that **covers** all edges, meaning at least one endpoint of every edge is included in the set.
|
50
|
+
|
51
|
+
## Formal Definition
|
52
|
+
|
53
|
+
Given an undirected graph $G = (V, E)$, a **vertex cover** is a subset $V' \subseteq V$ such that for every edge $(u, v) \in E$, at least one of $u$ or $v$ belongs to $V'$. The MVC problem seeks the vertex cover with the smallest cardinality.
|
54
|
+
|
55
|
+
## Importance and Applications
|
56
|
+
|
57
|
+
- **Theoretical Significance:** MVC is a well-known NP-hard problem, central to complexity theory.
|
58
|
+
- **Practical Applications:**
|
59
|
+
- **Network Security:** Identifying critical nodes to disrupt connections.
|
60
|
+
- **Bioinformatics:** Analyzing gene regulatory networks.
|
61
|
+
- **Wireless Sensor Networks:** Optimizing sensor coverage.
|
62
|
+
|
63
|
+
## Related Problems
|
64
|
+
|
65
|
+
- **Maximum Independent Set:** The complement of a vertex cover.
|
66
|
+
- **Set Cover Problem:** A generalization of MVC.
|
67
|
+
|
68
|
+
---
|
69
|
+
|
70
|
+
# Overview of the Algorithm and Its Running Time
|
71
|
+
|
72
|
+
The `find_vertex_cover` algorithm approximates a minimum vertex cover for an undirected graph $G = (V, E)$ by partitioning its edges into two claw-free subgraphs using the Burr-Erdős-Lovász (1976) method, computing exact vertex covers for these subgraphs with the Faenza, Oriolo, and Stauffer (2011) approach, and recursively refining the solution on residual edges. This process prevents the ratio from reaching 2, leveraging overlap between subgraphs and minimal additions in recursion. The algorithm begins by cleaning the graph (removing self-loops and isolates in $\mathcal{O}(n + m)$), partitions edges in $\mathcal{O}(m \cdot (m \cdot \Delta \cdot C + C^2))$ where $\Delta$ is the maximum degree and $C$ is the number of claws, computes vertex covers in $\mathcal{O}(n^3)$ per subgraph (total $\mathcal{O}(n^3)$), merges covers in $\mathcal{O}(n)$, and constructs the residual graph in $\mathcal{O}(m)$. The recursive nature, with a worst-case depth of $\mathcal{O}(m)$ if each step covers one edge, yields a total runtime of $\mathcal{O}(n^3 m)$, dominated by the cubic cost across levels. For sparse graphs ($m = \mathcal{O}(n)$), this simplifies to $\mathcal{O}(n^4)$.
|
73
|
+
|
74
|
+
---
|
75
|
+
|
76
|
+
## Problem Statement
|
77
|
+
|
78
|
+
Input: A Boolean Adjacency Matrix $M$.
|
79
|
+
|
80
|
+
Answer: Find a Minimum Vertex Cover.
|
81
|
+
|
82
|
+
### Example Instance: 5 x 5 matrix
|
83
|
+
|
84
|
+
| | c1 | c2 | c3 | c4 | c5 |
|
85
|
+
| ------ | --- | --- | --- | --- | --- |
|
86
|
+
| **r1** | 0 | 0 | 1 | 0 | 1 |
|
87
|
+
| **r2** | 0 | 0 | 0 | 1 | 0 |
|
88
|
+
| **r3** | 1 | 0 | 0 | 0 | 1 |
|
89
|
+
| **r4** | 0 | 1 | 0 | 0 | 0 |
|
90
|
+
| **r5** | 1 | 0 | 1 | 0 | 0 |
|
91
|
+
|
92
|
+
The input for undirected graph is typically provided in [DIMACS](http://dimacs.rutgers.edu/Challenges) format. In this way, the previous adjacency matrix is represented in a text file using the following string representation:
|
93
|
+
|
94
|
+
```
|
95
|
+
p edge 5 4
|
96
|
+
e 1 3
|
97
|
+
e 1 5
|
98
|
+
e 2 4
|
99
|
+
e 3 5
|
100
|
+
```
|
101
|
+
|
102
|
+
This represents a 5x5 matrix in DIMACS format such that each edge $(v,w)$ appears exactly once in the input file and is not repeated as $(w,v)$. In this format, every edge appears in the form of
|
103
|
+
|
104
|
+
```
|
105
|
+
e W V
|
106
|
+
```
|
107
|
+
|
108
|
+
where the fields W and V specify the endpoints of the edge while the lower-case character `e` signifies that this is an edge descriptor line.
|
109
|
+
|
110
|
+
_Example Solution:_
|
111
|
+
|
112
|
+
Vertex Cover Found `3, 4, 5`: Nodes `3`, `4`, and `5` constitute an optimal solution.
|
113
|
+
|
114
|
+
---
|
115
|
+
|
116
|
+
# Compile and Environment
|
117
|
+
|
118
|
+
## Prerequisites
|
119
|
+
|
120
|
+
- Python ≥ 3.10
|
121
|
+
|
122
|
+
## Installation
|
123
|
+
|
124
|
+
```bash
|
125
|
+
pip install alonso
|
126
|
+
```
|
127
|
+
|
128
|
+
## Execution
|
129
|
+
|
130
|
+
1. Clone the repository:
|
131
|
+
|
132
|
+
```bash
|
133
|
+
git clone https://github.com/frankvegadelgado/alonso.git
|
134
|
+
cd alonso
|
135
|
+
```
|
136
|
+
|
137
|
+
2. Run the script:
|
138
|
+
|
139
|
+
```bash
|
140
|
+
mvc -i ./benchmarks/testMatrix1
|
141
|
+
```
|
142
|
+
|
143
|
+
utilizing the `mvc` command provided by Alonso's Library to execute the Boolean adjacency matrix `alonso\benchmarks\testMatrix1`. The file `testMatrix1` represents the example described herein. We also support `.xz`, `.lzma`, `.bz2`, and `.bzip2` compressed text files.
|
144
|
+
|
145
|
+
**Example Output:**
|
146
|
+
|
147
|
+
```
|
148
|
+
testMatrix1: Vertex Cover Found 3, 4, 5
|
149
|
+
```
|
150
|
+
|
151
|
+
This indicates nodes `3, 4, 5` form a vertex cover.
|
152
|
+
|
153
|
+
---
|
154
|
+
|
155
|
+
## Vertex Cover Size
|
156
|
+
|
157
|
+
Use the `-c` flag to count the nodes in the vertex cover:
|
158
|
+
|
159
|
+
```bash
|
160
|
+
mvc -i ./benchmarks/testMatrix2 -c
|
161
|
+
```
|
162
|
+
|
163
|
+
**Output:**
|
164
|
+
|
165
|
+
```
|
166
|
+
testMatrix2: Vertex Cover Size 5
|
167
|
+
```
|
168
|
+
|
169
|
+
---
|
170
|
+
|
171
|
+
# Command Options
|
172
|
+
|
173
|
+
Display help and options:
|
174
|
+
|
175
|
+
```bash
|
176
|
+
mvc -h
|
177
|
+
```
|
178
|
+
|
179
|
+
**Output:**
|
180
|
+
|
181
|
+
```bash
|
182
|
+
usage: mvc [-h] -i INPUTFILE [-a] [-b] [-c] [-v] [-l] [--version]
|
183
|
+
|
184
|
+
Compute an Approximate Vertex Cover for undirected graph encoded in DIMACS format.
|
185
|
+
|
186
|
+
options:
|
187
|
+
-h, --help show this help message and exit
|
188
|
+
-i INPUTFILE, --inputFile INPUTFILE
|
189
|
+
input file path
|
190
|
+
-a, --approximation enable comparison with a polynomial-time approximation approach within a factor of at most 2
|
191
|
+
-b, --bruteForce enable comparison with the exponential-time brute-force approach
|
192
|
+
-c, --count calculate the size of the vertex cover
|
193
|
+
-v, --verbose anable verbose output
|
194
|
+
-l, --log enable file logging
|
195
|
+
--version show program's version number and exit
|
196
|
+
```
|
197
|
+
|
198
|
+
---
|
199
|
+
|
200
|
+
# Batch Execution
|
201
|
+
|
202
|
+
Batch execution allows you to solve multiple graphs within a directory consecutively.
|
203
|
+
|
204
|
+
To view available command-line options for the `batch_mvc` command, use the following in your terminal or command prompt:
|
205
|
+
|
206
|
+
```bash
|
207
|
+
batch_mvc -h
|
208
|
+
```
|
209
|
+
|
210
|
+
This will display the following help information:
|
211
|
+
|
212
|
+
```bash
|
213
|
+
usage: batch_mvc [-h] -i INPUTDIRECTORY [-a] [-b] [-c] [-v] [-l] [--version]
|
214
|
+
|
215
|
+
Compute an Approximate Vertex Cover for all undirected graphs encoded in DIMACS format and stored in a directory.
|
216
|
+
|
217
|
+
options:
|
218
|
+
-h, --help show this help message and exit
|
219
|
+
-i INPUTDIRECTORY, --inputDirectory INPUTDIRECTORY
|
220
|
+
Input directory path
|
221
|
+
-a, --approximation enable comparison with a polynomial-time approximation approach within a factor of at most 2
|
222
|
+
-b, --bruteForce enable comparison with the exponential-time brute-force approach
|
223
|
+
-c, --count calculate the size of the vertex cover
|
224
|
+
-v, --verbose anable verbose output
|
225
|
+
-l, --log enable file logging
|
226
|
+
--version show program's version number and exit
|
227
|
+
```
|
228
|
+
|
229
|
+
---
|
230
|
+
|
231
|
+
# Testing Application
|
232
|
+
|
233
|
+
A command-line utility named `test_mvc` is provided for evaluating the Algorithm using randomly generated, large sparse matrices. It supports the following options:
|
234
|
+
|
235
|
+
```bash
|
236
|
+
usage: test_mvc [-h] -d DIMENSION [-n NUM_TESTS] [-s SPARSITY] [-a] [-b] [-c] [-w] [-v] [-l] [--version]
|
237
|
+
|
238
|
+
The Alonso Testing Application using randomly generated, large sparse matrices.
|
239
|
+
|
240
|
+
options:
|
241
|
+
-h, --help show this help message and exit
|
242
|
+
-d DIMENSION, --dimension DIMENSION
|
243
|
+
an integer specifying the dimensions of the square matrices
|
244
|
+
-n NUM_TESTS, --num_tests NUM_TESTS
|
245
|
+
an integer specifying the number of tests to run
|
246
|
+
-s SPARSITY, --sparsity SPARSITY
|
247
|
+
sparsity of the matrices (0.0 for dense, close to 1.0 for very sparse)
|
248
|
+
-a, --approximation enable comparison with a polynomial-time approximation approach within a factor of at most 2
|
249
|
+
-b, --bruteForce enable comparison with the exponential-time brute-force approach
|
250
|
+
-c, --count calculate the size of the vertex cover
|
251
|
+
-w, --write write the generated random matrix to a file in the current directory
|
252
|
+
-v, --verbose anable verbose output
|
253
|
+
-l, --log enable file logging
|
254
|
+
--version show program's version number and exit
|
255
|
+
```
|
256
|
+
|
257
|
+
---
|
258
|
+
|
259
|
+
# Code
|
260
|
+
|
261
|
+
- Python implementation by **Frank Vega**.
|
262
|
+
|
263
|
+
---
|
264
|
+
|
265
|
+
# License
|
266
|
+
|
267
|
+
- MIT License.
|
alonso-0.0.1/README.md
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
# Alonso: Approximate Vertex Cover Solver
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
This work builds upon [Challenging the Unique Games Conjecture](https://dev.to/frank_vega_987689489099bf/challenging-the-unique-games-conjecture-12mi).
|
6
|
+
|
7
|
+
---
|
8
|
+
|
9
|
+
# The Minimum Vertex Cover Problem
|
10
|
+
|
11
|
+
The **Minimum Vertex Cover (MVC)** problem is a classic optimization problem in computer science and graph theory. It involves finding the smallest set of vertices in a graph that **covers** all edges, meaning at least one endpoint of every edge is included in the set.
|
12
|
+
|
13
|
+
## Formal Definition
|
14
|
+
|
15
|
+
Given an undirected graph $G = (V, E)$, a **vertex cover** is a subset $V' \subseteq V$ such that for every edge $(u, v) \in E$, at least one of $u$ or $v$ belongs to $V'$. The MVC problem seeks the vertex cover with the smallest cardinality.
|
16
|
+
|
17
|
+
## Importance and Applications
|
18
|
+
|
19
|
+
- **Theoretical Significance:** MVC is a well-known NP-hard problem, central to complexity theory.
|
20
|
+
- **Practical Applications:**
|
21
|
+
- **Network Security:** Identifying critical nodes to disrupt connections.
|
22
|
+
- **Bioinformatics:** Analyzing gene regulatory networks.
|
23
|
+
- **Wireless Sensor Networks:** Optimizing sensor coverage.
|
24
|
+
|
25
|
+
## Related Problems
|
26
|
+
|
27
|
+
- **Maximum Independent Set:** The complement of a vertex cover.
|
28
|
+
- **Set Cover Problem:** A generalization of MVC.
|
29
|
+
|
30
|
+
---
|
31
|
+
|
32
|
+
# Overview of the Algorithm and Its Running Time
|
33
|
+
|
34
|
+
The `find_vertex_cover` algorithm approximates a minimum vertex cover for an undirected graph $G = (V, E)$ by partitioning its edges into two claw-free subgraphs using the Burr-Erdős-Lovász (1976) method, computing exact vertex covers for these subgraphs with the Faenza, Oriolo, and Stauffer (2011) approach, and recursively refining the solution on residual edges. This process prevents the ratio from reaching 2, leveraging overlap between subgraphs and minimal additions in recursion. The algorithm begins by cleaning the graph (removing self-loops and isolates in $\mathcal{O}(n + m)$), partitions edges in $\mathcal{O}(m \cdot (m \cdot \Delta \cdot C + C^2))$ where $\Delta$ is the maximum degree and $C$ is the number of claws, computes vertex covers in $\mathcal{O}(n^3)$ per subgraph (total $\mathcal{O}(n^3)$), merges covers in $\mathcal{O}(n)$, and constructs the residual graph in $\mathcal{O}(m)$. The recursive nature, with a worst-case depth of $\mathcal{O}(m)$ if each step covers one edge, yields a total runtime of $\mathcal{O}(n^3 m)$, dominated by the cubic cost across levels. For sparse graphs ($m = \mathcal{O}(n)$), this simplifies to $\mathcal{O}(n^4)$.
|
35
|
+
|
36
|
+
---
|
37
|
+
|
38
|
+
## Problem Statement
|
39
|
+
|
40
|
+
Input: A Boolean Adjacency Matrix $M$.
|
41
|
+
|
42
|
+
Answer: Find a Minimum Vertex Cover.
|
43
|
+
|
44
|
+
### Example Instance: 5 x 5 matrix
|
45
|
+
|
46
|
+
| | c1 | c2 | c3 | c4 | c5 |
|
47
|
+
| ------ | --- | --- | --- | --- | --- |
|
48
|
+
| **r1** | 0 | 0 | 1 | 0 | 1 |
|
49
|
+
| **r2** | 0 | 0 | 0 | 1 | 0 |
|
50
|
+
| **r3** | 1 | 0 | 0 | 0 | 1 |
|
51
|
+
| **r4** | 0 | 1 | 0 | 0 | 0 |
|
52
|
+
| **r5** | 1 | 0 | 1 | 0 | 0 |
|
53
|
+
|
54
|
+
The input for undirected graph is typically provided in [DIMACS](http://dimacs.rutgers.edu/Challenges) format. In this way, the previous adjacency matrix is represented in a text file using the following string representation:
|
55
|
+
|
56
|
+
```
|
57
|
+
p edge 5 4
|
58
|
+
e 1 3
|
59
|
+
e 1 5
|
60
|
+
e 2 4
|
61
|
+
e 3 5
|
62
|
+
```
|
63
|
+
|
64
|
+
This represents a 5x5 matrix in DIMACS format such that each edge $(v,w)$ appears exactly once in the input file and is not repeated as $(w,v)$. In this format, every edge appears in the form of
|
65
|
+
|
66
|
+
```
|
67
|
+
e W V
|
68
|
+
```
|
69
|
+
|
70
|
+
where the fields W and V specify the endpoints of the edge while the lower-case character `e` signifies that this is an edge descriptor line.
|
71
|
+
|
72
|
+
_Example Solution:_
|
73
|
+
|
74
|
+
Vertex Cover Found `3, 4, 5`: Nodes `3`, `4`, and `5` constitute an optimal solution.
|
75
|
+
|
76
|
+
---
|
77
|
+
|
78
|
+
# Compile and Environment
|
79
|
+
|
80
|
+
## Prerequisites
|
81
|
+
|
82
|
+
- Python ≥ 3.10
|
83
|
+
|
84
|
+
## Installation
|
85
|
+
|
86
|
+
```bash
|
87
|
+
pip install alonso
|
88
|
+
```
|
89
|
+
|
90
|
+
## Execution
|
91
|
+
|
92
|
+
1. Clone the repository:
|
93
|
+
|
94
|
+
```bash
|
95
|
+
git clone https://github.com/frankvegadelgado/alonso.git
|
96
|
+
cd alonso
|
97
|
+
```
|
98
|
+
|
99
|
+
2. Run the script:
|
100
|
+
|
101
|
+
```bash
|
102
|
+
mvc -i ./benchmarks/testMatrix1
|
103
|
+
```
|
104
|
+
|
105
|
+
utilizing the `mvc` command provided by Alonso's Library to execute the Boolean adjacency matrix `alonso\benchmarks\testMatrix1`. The file `testMatrix1` represents the example described herein. We also support `.xz`, `.lzma`, `.bz2`, and `.bzip2` compressed text files.
|
106
|
+
|
107
|
+
**Example Output:**
|
108
|
+
|
109
|
+
```
|
110
|
+
testMatrix1: Vertex Cover Found 3, 4, 5
|
111
|
+
```
|
112
|
+
|
113
|
+
This indicates nodes `3, 4, 5` form a vertex cover.
|
114
|
+
|
115
|
+
---
|
116
|
+
|
117
|
+
## Vertex Cover Size
|
118
|
+
|
119
|
+
Use the `-c` flag to count the nodes in the vertex cover:
|
120
|
+
|
121
|
+
```bash
|
122
|
+
mvc -i ./benchmarks/testMatrix2 -c
|
123
|
+
```
|
124
|
+
|
125
|
+
**Output:**
|
126
|
+
|
127
|
+
```
|
128
|
+
testMatrix2: Vertex Cover Size 5
|
129
|
+
```
|
130
|
+
|
131
|
+
---
|
132
|
+
|
133
|
+
# Command Options
|
134
|
+
|
135
|
+
Display help and options:
|
136
|
+
|
137
|
+
```bash
|
138
|
+
mvc -h
|
139
|
+
```
|
140
|
+
|
141
|
+
**Output:**
|
142
|
+
|
143
|
+
```bash
|
144
|
+
usage: mvc [-h] -i INPUTFILE [-a] [-b] [-c] [-v] [-l] [--version]
|
145
|
+
|
146
|
+
Compute an Approximate Vertex Cover for undirected graph encoded in DIMACS format.
|
147
|
+
|
148
|
+
options:
|
149
|
+
-h, --help show this help message and exit
|
150
|
+
-i INPUTFILE, --inputFile INPUTFILE
|
151
|
+
input file path
|
152
|
+
-a, --approximation enable comparison with a polynomial-time approximation approach within a factor of at most 2
|
153
|
+
-b, --bruteForce enable comparison with the exponential-time brute-force approach
|
154
|
+
-c, --count calculate the size of the vertex cover
|
155
|
+
-v, --verbose anable verbose output
|
156
|
+
-l, --log enable file logging
|
157
|
+
--version show program's version number and exit
|
158
|
+
```
|
159
|
+
|
160
|
+
---
|
161
|
+
|
162
|
+
# Batch Execution
|
163
|
+
|
164
|
+
Batch execution allows you to solve multiple graphs within a directory consecutively.
|
165
|
+
|
166
|
+
To view available command-line options for the `batch_mvc` command, use the following in your terminal or command prompt:
|
167
|
+
|
168
|
+
```bash
|
169
|
+
batch_mvc -h
|
170
|
+
```
|
171
|
+
|
172
|
+
This will display the following help information:
|
173
|
+
|
174
|
+
```bash
|
175
|
+
usage: batch_mvc [-h] -i INPUTDIRECTORY [-a] [-b] [-c] [-v] [-l] [--version]
|
176
|
+
|
177
|
+
Compute an Approximate Vertex Cover for all undirected graphs encoded in DIMACS format and stored in a directory.
|
178
|
+
|
179
|
+
options:
|
180
|
+
-h, --help show this help message and exit
|
181
|
+
-i INPUTDIRECTORY, --inputDirectory INPUTDIRECTORY
|
182
|
+
Input directory path
|
183
|
+
-a, --approximation enable comparison with a polynomial-time approximation approach within a factor of at most 2
|
184
|
+
-b, --bruteForce enable comparison with the exponential-time brute-force approach
|
185
|
+
-c, --count calculate the size of the vertex cover
|
186
|
+
-v, --verbose anable verbose output
|
187
|
+
-l, --log enable file logging
|
188
|
+
--version show program's version number and exit
|
189
|
+
```
|
190
|
+
|
191
|
+
---
|
192
|
+
|
193
|
+
# Testing Application
|
194
|
+
|
195
|
+
A command-line utility named `test_mvc` is provided for evaluating the Algorithm using randomly generated, large sparse matrices. It supports the following options:
|
196
|
+
|
197
|
+
```bash
|
198
|
+
usage: test_mvc [-h] -d DIMENSION [-n NUM_TESTS] [-s SPARSITY] [-a] [-b] [-c] [-w] [-v] [-l] [--version]
|
199
|
+
|
200
|
+
The Alonso Testing Application using randomly generated, large sparse matrices.
|
201
|
+
|
202
|
+
options:
|
203
|
+
-h, --help show this help message and exit
|
204
|
+
-d DIMENSION, --dimension DIMENSION
|
205
|
+
an integer specifying the dimensions of the square matrices
|
206
|
+
-n NUM_TESTS, --num_tests NUM_TESTS
|
207
|
+
an integer specifying the number of tests to run
|
208
|
+
-s SPARSITY, --sparsity SPARSITY
|
209
|
+
sparsity of the matrices (0.0 for dense, close to 1.0 for very sparse)
|
210
|
+
-a, --approximation enable comparison with a polynomial-time approximation approach within a factor of at most 2
|
211
|
+
-b, --bruteForce enable comparison with the exponential-time brute-force approach
|
212
|
+
-c, --count calculate the size of the vertex cover
|
213
|
+
-w, --write write the generated random matrix to a file in the current directory
|
214
|
+
-v, --verbose anable verbose output
|
215
|
+
-l, --log enable file logging
|
216
|
+
--version show program's version number and exit
|
217
|
+
```
|
218
|
+
|
219
|
+
---
|
220
|
+
|
221
|
+
# Code
|
222
|
+
|
223
|
+
- Python implementation by **Frank Vega**.
|
224
|
+
|
225
|
+
---
|
226
|
+
|
227
|
+
# License
|
228
|
+
|
229
|
+
- MIT License.
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Created on 21/05/2025
|
2
|
+
# Author: Frank Vega
|
3
|
+
|
4
|
+
import itertools
|
5
|
+
from . import utils
|
6
|
+
|
7
|
+
import networkx as nx
|
8
|
+
from . import partition
|
9
|
+
from . import stable
|
10
|
+
from . import merge
|
11
|
+
|
12
|
+
def find_vertex_cover(graph):
|
13
|
+
"""
|
14
|
+
Compute an approximate minimum vertex cover set for an undirected graph by transforming it into a chordal graph.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
graph (nx.Graph): A NetworkX Graph object representing the input graph.
|
18
|
+
|
19
|
+
Returns:
|
20
|
+
set: A set of vertex indices representing the approximate minimum vertex cover set.
|
21
|
+
Returns an empty set if the graph is empty or has no edges.
|
22
|
+
"""
|
23
|
+
# Validate that the input is a valid undirected NetworkX graph
|
24
|
+
if not isinstance(graph, nx.Graph):
|
25
|
+
raise ValueError("Input must be an undirected NetworkX Graph.")
|
26
|
+
|
27
|
+
# Handle trivial cases: return empty set for graphs with no nodes or no edges
|
28
|
+
if graph.number_of_nodes() == 0 or graph.number_of_edges() == 0:
|
29
|
+
return set() # No vertices or edges mean no cover is needed
|
30
|
+
|
31
|
+
# Create a working copy to avoid modifying the original graph
|
32
|
+
working_graph = graph.copy()
|
33
|
+
|
34
|
+
# Remove self-loops as they are irrelevant for vertex cover computation
|
35
|
+
working_graph.remove_edges_from(list(nx.selfloop_edges(working_graph)))
|
36
|
+
|
37
|
+
# Remove isolated nodes (degree 0) since they don't contribute to the vertex cover
|
38
|
+
working_graph.remove_nodes_from(list(nx.isolates(working_graph)))
|
39
|
+
|
40
|
+
# Return empty set if the cleaned graph has no nodes after removals
|
41
|
+
if working_graph.number_of_nodes() == 0:
|
42
|
+
return set()
|
43
|
+
|
44
|
+
# Partition edges into two subsets (E1, E2) using the Burr-Erdős-Lovász (1976) algorithm
|
45
|
+
# This step divides the graph into two claw-free subgraphs
|
46
|
+
# Complexity: O(m * (m * Δ * C + C^2)), where m is edges, Δ is maximum degree, C is number of claws
|
47
|
+
E1, E2 = partition.partition_edges_claw_free(working_graph)
|
48
|
+
|
49
|
+
# Compute minimum vertex cover for E1 using the Faenza, Oriolo & Stauffer (2011) algorithm
|
50
|
+
# This finds the maximum weighted stable set in the claw-free graph E1, whose complement is the vertex cover
|
51
|
+
# Complexity: O(n^3), where n is the number of nodes in the subgraph induced by E1
|
52
|
+
vertex_cover_1 = stable.minimum_vertex_cover_claw_free(E1)
|
53
|
+
|
54
|
+
# Compute minimum vertex cover for E2 using the same Faenza, Oriolo & Stauffer (2011) algorithm
|
55
|
+
# Complexity: O(n^3) for the subgraph induced by E2
|
56
|
+
vertex_cover_2 = stable.minimum_vertex_cover_claw_free(E2)
|
57
|
+
|
58
|
+
# Merge the two vertex covers from E1 and E2 to approximate the minimum vertex cover of the original graph
|
59
|
+
approximate_vertex_cover = merge.merge_vertex_covers(E1, E2, vertex_cover_1, vertex_cover_2)
|
60
|
+
|
61
|
+
# Create a residual graph containing edges not covered by the current vertex cover
|
62
|
+
residual_graph = nx.Graph()
|
63
|
+
for u, v in working_graph.edges():
|
64
|
+
if u not in approximate_vertex_cover and v not in approximate_vertex_cover:
|
65
|
+
residual_graph.add_edge(u, v) # Add edge if neither endpoint is in the cover
|
66
|
+
|
67
|
+
# Recursively find vertex cover for the residual graph to handle uncovered edges
|
68
|
+
residual_vertex_cover = find_vertex_cover(residual_graph)
|
69
|
+
|
70
|
+
# Combine the approximate vertex cover with the residual cover to ensure all edges are covered
|
71
|
+
return approximate_vertex_cover.union(residual_vertex_cover)
|
72
|
+
|
73
|
+
def find_vertex_cover_brute_force(graph):
|
74
|
+
"""
|
75
|
+
Computes an exact minimum vertex cover in exponential time.
|
76
|
+
|
77
|
+
Args:
|
78
|
+
graph: A NetworkX Graph.
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
A set of vertex indices representing the exact vertex cover, or None if the graph is empty.
|
82
|
+
"""
|
83
|
+
|
84
|
+
if graph.number_of_nodes() == 0 or graph.number_of_edges() == 0:
|
85
|
+
return None
|
86
|
+
|
87
|
+
n_vertices = len(graph.nodes())
|
88
|
+
|
89
|
+
for k in range(1, n_vertices + 1): # Iterate through all possible sizes of the cover
|
90
|
+
for candidate in itertools.combinations(graph.nodes(), k):
|
91
|
+
cover_candidate = set(candidate)
|
92
|
+
if utils.is_vertex_cover(graph, cover_candidate):
|
93
|
+
return cover_candidate
|
94
|
+
|
95
|
+
return None
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
def find_vertex_cover_approximation(graph):
|
100
|
+
"""
|
101
|
+
Computes an approximate vertex cover in polynomial time with an approximation ratio of at most 2 for undirected graphs.
|
102
|
+
|
103
|
+
Args:
|
104
|
+
graph: A NetworkX Graph.
|
105
|
+
|
106
|
+
Returns:
|
107
|
+
A set of vertex indices representing the approximate vertex cover, or None if the graph is empty.
|
108
|
+
"""
|
109
|
+
|
110
|
+
if graph.number_of_nodes() == 0 or graph.number_of_edges() == 0:
|
111
|
+
return None
|
112
|
+
|
113
|
+
#networkx doesn't have a guaranteed minimum vertex cover function, so we use approximation
|
114
|
+
vertex_cover = nx.approximation.vertex_cover.min_weighted_vertex_cover(graph)
|
115
|
+
return vertex_cover
|