-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplanes.py
136 lines (122 loc) · 4.81 KB
/
planes.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
import numpy as np
import quantum_query_optimizer as qqo
def get_boolean_labels(p):
labels = list(range(p)) + [np.inf]
for row_index in range(p):
for col_index in range(p):
labels += [(row_index, col_index)]
return labels
def points_on_line_with_slope(p, slope, y_intercept):
''' Returns a list of points on the line with the given slope and y-intercept. '''
current = (0, y_intercept) # Start from bottom row
points_on_line = [slope, current] # Include slope and first point
for _ in range(p-1):
# Move to next point on line
# One to the right, slope up
current = ((current[0] + slope) % p, (current[1]+1) % p)
points_on_line += [current]
return points_on_line
def points_on_vertical_line(p, x_intercept):
''' Returns a list of points on the vertical line with the given x-intercept. '''
points_on_line = [np.inf]
for y_intercept in range(p):
points_on_line += [(x_intercept, y_intercept)]
return points_on_line
def points_on_horizontal_line(p, y_intercept):
''' Returns a list of points on the horizontal line with the given y-intercept. '''
points_on_line = [0]
for x_intercept in range(p):
points_on_line += [(x_intercept, y_intercept)]
return points_on_line
def check_all_present(points_on_line, instance):
''' Returns True if all points on the line are present in the instance. '''
#print('Checking points_on_line=', points_on_line)
is_present = [instance[point] == '1' for point in points_on_line]
#print(is_present)
return all(is_present)
def is_line_present(p, instance):
# Check horizontal lines
for y_intercept in range(p):
points_on_line = points_on_horizontal_line(p, y_intercept)
if check_all_present(points_on_line, instance):
return '1'
# Check slopes between 1 and p-1
for slope in range(1, p):
for y_intercept in range(p):
points_on_line = points_on_line_with_slope(p, slope, y_intercept)
if check_all_present(points_on_line, instance):
return '1'
# Check vertical lines
for x_intercept in range(p):
points_on_line = points_on_vertical_line(p, x_intercept)
if check_all_present(points_on_line, instance):
return '1'
# Check line at infinity
points_on_line = [np.inf]
for point in range(p):
points_on_line += [point]
if check_all_present(points_on_line, instance):
return '1'
return '0'
def build_single_hard(p, points_on_line, correspondance):
''' Returns a list of p+1 instances, one positive and p negatives. '''
num_points = p**2 + p + 1
x = '0' * num_points
for point in points_on_line:
index = correspondance[point]
x = x[:index] + '1' + x[index+1:]
xs = [x]
#print(x)
# Perturb each point on the line for a negative instance
for point in points_on_line:
index = correspondance[point]
new_x = x[:index] + '0' + x[index+1:]
xs += [new_x]
return xs
def build_hard_instances(p, correspondance):
xs = []
# Check horizontal lines
for y_intercept in range(p):
points_on_line = points_on_horizontal_line(p, y_intercept)
xs += build_single_hard(p, points_on_line, correspondance)
# Check slopes between 1 and p-1
for slope in range(1, p):
for y_intercept in range(p):
points_on_line = points_on_line_with_slope(p, slope, y_intercept)
xs += build_single_hard(p, points_on_line, correspondance)
# Check vertical lines
for x_intercept in range(p):
points_on_line = points_on_vertical_line(p, x_intercept)
xs += build_single_hard(p, points_on_line, correspondance)
# Check line at infinity
points_on_line = [np.inf]
for point in range(p):
points_on_line += [point]
xs += build_single_hard(p, points_on_line, correspondance)
return xs
def build_hard_input_and_output(p):
labels = get_boolean_labels(p)
n = len(labels)
print('Number of bits:', n)
correspondance = dict(zip(labels, range(n)))
xs = build_hard_instances(p, correspondance)
# Negate each bit
negated_xs = []
for x in xs:
negated_x = ''.join(['1' if x[index] == '0' else '0' for index in range(n)])
negated_xs += [negated_x]
D = xs + negated_xs
print('Number of inputs/outputs:', len(D))
E = [is_line_present(p, dict(zip(labels, x))) for x in D]
return D, E
def build_all_input_and_output(p):
labels = get_boolean_labels(p)
n = len(labels)
print('Number of bits:', n)
D = qqo.getDAll(n)
print('Number of inputs/outputs:', len(D))
E = [is_line_present(p, dict(zip(labels, x))) for x in D]
return D, E
D, E = build_all_input_and_output(p=3)
#D, E = build_hard_input_and_output(p=3)
solutions = qqo.runSDP(D=D, E=E, verbose=True)