-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathinstance_loader.py
140 lines (115 loc) · 4.67 KB
/
instance_loader.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
import os, sys
import random
import numpy as np
from functools import reduce
class InstanceLoader(object):
def __init__(self,path):
self.path = path
self.filenames = [ path + '/' + x for x in os.listdir(path) ]
random.shuffle(self.filenames)
self.reset()
#end
def get_instances(self, n_instances):
for i in range(n_instances):
# Read graph from file
Ma,chrom_number,diff_edge = read_graph(self.filenames[self.index])
f = self.filenames[self.index]
Ma1 = Ma
Ma2 = Ma.copy()
if diff_edge is not None:
# Create a (UNSAT/SAT) pair of instances with one edge of difference
# The second instance has one edge more (diff_edge) which renders it SAT
Ma2[diff_edge[0],diff_edge[1]] = Ma2[diff_edge[1],diff_edge[0]] =1
#end
# Yield both instances
yield Ma1,chrom_number,f
yield Ma2,chrom_number,f
if self.index + 1 < len(self.filenames):
self.index += 1
else:
self.reset()
#end
#end
def create_batch(instances):
# n_instances: number of instances
n_instances = len(instances)
# n_vertices[i]: number of vertices in the i-th instance
n_vertices = np.array([ x[0].shape[0] for x in instances ])
# n_edges[i]: number of edges in the i-th instance
n_edges = np.array([ len(np.nonzero(x[0])[0]) for x in instances ])
# n_colors[i]: number of colors in the i-th instance
n_colors = np.array( [x[1] for x in instances])
# total_vertices: total number of vertices among all instances
total_vertices = sum(n_vertices)
# total_edges: total number of edges among all instances
total_edges = sum(n_edges)
# total_colors: total number of colors among all instances
total_colors = sum(n_colors)
# Compute matrices M, MC
# M is the adjacency matrix
M = np.zeros((total_vertices,total_vertices))
# MC is a matrix connecting each problem nodes to its colors candidates
MC = np.zeros((total_vertices, total_colors))
# Even index instances are SAT, odd are UNSAT
cn_exists = np.array([ 1-(i%2) for i in range(n_instances) ])
for (i,(Ma,chrom_number,f)) in enumerate(instances):
# Get the number of vertices (n) and edges (m) in this graph
n, m, c = n_vertices[i], n_edges[i], n_colors[i]
# Get the number of vertices (n_acc) and edges (m_acc) up until the i-th graph
n_acc = sum(n_vertices[0:i])
m_acc = sum(n_edges[0:i])
c_acc = sum(n_colors[0:i])
#Populate MC
MC[n_acc:n_acc+n,c_acc:c_acc+c] = 1
# Get the list of edges in this graph
edges = list(zip(np.nonzero(Ma)[0], np.nonzero(Ma)[1]))
# Populate M
for e,(x,y) in enumerate(edges):
if Ma[x,y] == 1:
M[n_acc+x,n_acc+y] = M[n_acc+y,n_acc+x] = 1
#end if
#end for
#end for
return M, n_colors, MC, cn_exists, n_vertices, n_edges, f
#end
def get_batches(self, batch_size):
for i in range( len(self.filenames) // batch_size ):
instances = list(self.get_instances(batch_size))
yield InstanceLoader.create_batch(instances)
#end
#end
def get_test_batches(self, batch_size, total_instances):
for i in range( total_instances ):
instances = list(self.get_instances(batch_size))
yield InstanceLoader.create_batch(instances)
#end
#end
def reset(self):
random.shuffle(self.filenames)
self.index = 0
#end
#end
def read_graph(filepath):
with open(filepath,"r") as f:
line = ''
# Parse number of vertices
while 'DIMENSION' not in line: line = f.readline();
n = int(line.split()[1])
Ma = np.zeros((n,n),dtype=int)
# Parse edges
while 'EDGE_DATA_SECTION' not in line: line = f.readline();
line = f.readline()
while '-1' not in line:
i,j = [ int(x) for x in line.split() ]
Ma[i,j] = 1
line = f.readline()
#end while
# Parse diff edge
while 'DIFF_EDGE' not in line: line = f.readline();
diff_edge = [ int(x) for x in f.readline().split() ]
# Parse target cost
while 'CHROM_NUMBER' not in line: line = f.readline();
chrom_number = int(f.readline().strip())
#end
return Ma,chrom_number,diff_edge
#end