forked from lducas/CodeRed
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmiddleware.py
134 lines (94 loc) · 3.66 KB
/
middleware.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
from numpy import zeros, float64, int64, array, random
import ctypes
import _ctypes
from math import ceil, floor
import sys
if sys.version_info[0] < 3:
raise Exception("Must be using Python 3")
def c_char_ptr(x):
return x.ctypes.data_as(ctypes.POINTER(ctypes.c_char))
def c_long_ptr(x):
return x.ctypes.data_as(ctypes.POINTER(ctypes.c_long))
def ham(v):
return sum(v)
# CodeRedLib: a python wrapper for the c++ coreredlib.cpp
# coreredlib is compiled many time with various value of maxn
# make sure the value you want to use are listed in compile_cpp_core.sh
# Functions names match with the paper. They all act on the internal state:
# self.B : the basis
# self.E : The epipodal matrix
# self.P : The cumulative projector matrix P[i] = &_{j<i} ~ B[j] (has length k+1)
# (P[i] is the boolean complement of s_i from the paper)
# self.l : Epipodal length
class CodeRedLib(object):
def __init__(self, B, seed=None):
k, n = B.shape
self.k, self.n = k, n
if seed is None:
seed = random.randint(0,2**63)
nmax = 256 * int(ceil(n/256.))
self.lib = ctypes.cdll.LoadLibrary("./bin/coderedlib-%d.so"%nmax)
self.lib._setup(k, n, c_char_ptr(B), ctypes.c_long(seed))
self.B = zeros((k , n), dtype='bool')
self.E = zeros((k , n), dtype='bool')
self.P = zeros((k+1, n), dtype='bool')
self.l = zeros( k, dtype='int64')
self.update()
def update(self):
self.lib._export_all(c_char_ptr(self.B),
c_char_ptr(self.E),
c_char_ptr(self.P),
c_long_ptr(self.l))
# Check that the code is of full length
assert(sum(self.l)==self.n)
def LLL(self):
self.lib._LLL()
self.update()
def Randomize(self, light=True):
self.lib._Randomize(light)
self.update()
def Systematize(self):
self.lib._Systematize()
self.update()
def EpiSort(self):
self.lib._EpiSort()
self.update()
def SizeRedBasis(self):
self.lib._SizeRedBasis()
self.update()
def SemiSystematize(self):
self.lib._SemiSystematize()
self.update()
for k1 in range(self.k)[::-1]:
if self.l[k1] > 1:
return k1+1
return 0
def KillTwos(self):
self.lib._KillTwos()
self.update()
# Used to speed up LB/LBB experiments in large dimension by only
# vistining a (1+skip)^{1-w2} fraction of the enumerated space.
def set_skip(self, skip):
return self.lib._set_skip(int(floor(skip)))
def SizeRed(self, t):
return self.lib._SizeRed(c_char_ptr(t))
def LB(self, w2, goal_w=None, t=None, stats=False):
tt = zeros(self.n, dtype='bool') if t is None else 1 * t
_stats = zeros(self.n+1, dtype='int64') if stats else None
success = self.lib._LB(c_char_ptr(tt), w2,
0 if goal_w is None else goal_w,
c_long_ptr(_stats) if stats else None)
if stats:
return _stats
if success or goal_w is None:
return tt
def LBB(self, k1, w2, goal_w=None, t=None, stats=False):
tt = zeros(self.n, dtype='bool') if t is None else 1 * t
_stats = zeros(self.n+1, dtype='int64') if stats else None
success = self.lib._LBB(c_char_ptr(tt), k1, w2,
0 if goal_w is None else goal_w,
c_long_ptr(_stats) if stats else None)
if stats:
return _stats
if success or goal_w is None:
return tt