forked from jtan-gh/multi-agent-path-finder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mvc.py
167 lines (126 loc) · 4.96 KB
/
mvc.py
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# Graph source from https://www.geeksforgeeks.org/vertex-cover-problem-set-1-introduction-approximate-algorithm-2/
# Weighted Graph source from https://www.bogotobogo.com/python/python_graph_data_structures.php
# Python3 program to print Vertex Cover
# of a given undirected graph
from collections import defaultdict
import math
from pulp import LpMaximize, LpProblem, LpStatus, lpSum, LpVariable, LpMinimize, value
# This class represents a directed graph
# using adjacency list representation
class Graph:
def __init__(self, vertices):
# No. of vertices
self.V = vertices
# Default dictionary to store graph
self.graph = defaultdict(list)
# Function to add an edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)
# The function to print vertex cover
def getVertexCover(self):
# Initialize all vertices as not visited.
visited = [False] * (self.V)
# Consider all edges one by one
for u in range(self.V):
# An edge is only picked when
# both visited[u] and visited[v]
# are false
if not visited[u]:
# Go through all adjacents of u and
# pick the first not yet visited
# vertex (We are basically picking
# an edge (u, v) from remaining edges.
for v in self.graph[u]:
if not visited[v]:
# Add the vertices (u, v) to the
# result set. We make the vertex
# u and v visited so that all
# edges from/to them would
# be ignored
visited[v] = True
visited[u] = True
break
# Print the vertex cover
mvc_set = []
for j in range(self.V):
if visited[j]:
mvc_set.append(j)
# print("VC set", mvc_set)
# print("MVC size lower bound", math.ceil(len(mvc_set)/2))
return mvc_set
class Vertex:
def __init__(self, node):
self.id = node
self.adjacent = {}
def __str__(self):
return str(self.id) + ' adjacent: ' + str([x.id for x in self.adjacent])
def add_neighbor(self, neighbor, weight=0):
self.adjacent[neighbor] = weight
def get_connections(self):
return self.adjacent.keys()
def get_id(self):
return self.id
def get_weight(self, neighbor):
return self.adjacent[neighbor]
class WeightedGraph:
def __init__(self, vertices):
self.vert_dict = {}
self.num_vertices = 0
for vertex in vertices:
self.add_vertex(vertex)
def __iter__(self):
return iter(self.vert_dict.values())
def add_vertex(self, node):
self.num_vertices = self.num_vertices + 1
new_vertex = Vertex(node)
self.vert_dict[node] = new_vertex
def get_vertex(self, n):
if n in self.vert_dict:
return self.vert_dict[n]
else:
return None
def add_edge(self, frm, to, cost = 0):
if frm not in self.vert_dict:
self.add_vertex(frm)
if to not in self.vert_dict:
self.add_vertex(to)
self.vert_dict[frm].add_neighbor(self.vert_dict[to], cost)
self.vert_dict[to].add_neighbor(self.vert_dict[frm], cost)
def get_vertices(self):
return self.vert_dict.keys()
if __name__ == '__main__':
g = WeightedGraph(['a1','a2','a3','a4','a5','a6','a7'])
g.add_edge('a1', 'a2', 1)
g.add_edge('a7', 'a5', 1)
g.add_edge('a6', 'a5', 4)
g.add_edge('a6', 'a7', 4)
g.add_edge('a3', 'a4', 1)
# one variable for each vertex
model = LpProblem("edge weighted minimum vertex cover", LpMinimize)
a1 = LpVariable('a1', lowBound=0, cat="Integer", e=None)
a2 = LpVariable('a2', lowBound=0, cat="Integer", e=None)
a3 = LpVariable('a3', lowBound=0, cat="Integer", e=None)
a4 = LpVariable('a4', lowBound=0, cat="Integer", e=None)
a5 = LpVariable('a5', lowBound=0, cat="Integer", e=None)
a6 = LpVariable('a6', lowBound=0, cat="Integer", e=None)
a7 = LpVariable('a7', lowBound=0, cat="Integer", e=None)
# objective function
model += a1 + a2 + a3 + a4 + a5 + a6 + a7
# constraints for each edge
model += a1 + a2 >= 1
model += a6 + a7 >= 4
model += a6 + a5 >= 4
model += a7 + a5 >= 1
model += a3 + a4 >= 1
res = model.solve()
# Solution
for v in model.variables():
print(v.name, "=", v.varValue)
print("WDG heuristic = ", value(model.objective))
# for v in g:
# for w in v.get_connections():
# vid = v.get_id()
# wid = w.get_id()
# print('( %s , %s, %3d)' % ( vid, wid, v.get_weight(w)))
# for v in g:
# print('g.vert_dict[%s]=%s' %(v.get_id(), g.vert_dict[v.get_id()]))