Repository navigation
Expand file tree
/
Copy pathottoeplitz.py
More file actions
181 lines (157 loc) · 5.81 KB
/
Copy pathottoeplitz.py
File metadata and controls
181 lines (157 loc) · 5.81 KB
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
"""
ottoeplitz
==========
This module contains the main ``Toeplitz`` class. This is where
the toeplitz hashing takes place.
"""
from typing import Callable
import numpy as np
import pickle
from scipy.constants import *
from scipy.linalg import toeplitz
class Toeplitz:
"""
The ``Toeplitz`` class executes the Toeplitz hashing. It
requires a large set of random data and the resolution of your
ADC as input.
Parameters
----------
data : list
Input data to be hashed.
bits : int
Resolution of your ADC or how many bits you want to represent each random number with.
Returns
-------
hashed_data : list
Data after Toeplitz hashed.
"""
def __init__(self, data, bits):
self.data = data
self.bits = bits
def _calculate_N(self):
"""
Calculates a power of 2 closest to, but under, the size
of the original input data. We call this power, N. Resizes
data by taking first 2^N data points and deleting the rest.
Returns
-------
N : int
Power of 2 just under size of input data.
data : list
Resized input data.
"""
N = 0
while (len(self.data) - 2**N) >= 0:
N += 1
N -= 1
indices = []
for i in range(2**N, len(self.data)):
indices.append(i)
data = np.delete(self.data, indices)
return N, data
def _min_entropy(self):
"""
Calculates the minimum entropy of the data.
Returns
-------
min_ent : float
Minimum entropy of the input data.
"""
binned_data, bins = np.histogram(self.data, bins=2**self.bits-1)
N, data = self._calculate_N()
pmax = np.max(binned_data)/2**N
min_ent = -np.log2(pmax)
return min_ent
def _output_length(self):
"""
Calculates length of the output data using min-entropy.
Returns
-------
out_len : int
Length of the output data.
"""
min_ent = self._min_entropy()
out_len = 2**self.bits * (min_ent/self.bits)
out_len = round(out_len)
return out_len
def _toep_mat(self):
"""
Constructs a random n x m binary Toeplitz matrix.
Returns
-------
toep_mat : 2D array
A random n x m binary Toeplitz matrix.
"""
out_len = self._output_length(self.bits)
row = np.random.randint(2, size=out_len)
col = np.random.randint(2, size=2**self.bits)
toep_mat = toeplitz(row, col)
return toep_mat
def _dec_num_to_bin(self, data_pt, depth, bin_pts):
"""
General function converting decimal number to binary number.
Parameters
----------
data_pt : int
Number you want to convert to binary.
depth : int
How many bits you want the number represented with.
bin_pts : list
Binary number of size 'bits' converted from decimal. Recursive part of function.
Returns
-------
bin_pts : list
Binary number of size 'bits' converted from decimal.
"""
if data_pt >= 1:
bin_pts = self._dec_num_to_bin(data_pt // 2, depth - 1, bin_pts)
bin_pts[depth] = data_pt % 2
return bin_pts
def _dec_list_to_bin(self):
"""
Converts data from decimal to binary.
Returns
-------
bin_data_flat : array
Data converted from decimal to binary and flattened.
"""
N, data = self._calculate_N()
binned_data, bins = np.histogram(self.data, bins=2**self.bits-1)
data_digital = np.digitize(data, bins, right=True)
binary_data = []
for i in range(2**N):
zeros = np.zeros(self.bits)
binary_data.append(self._dec_num_to_bin(data_digital[i], self.bits - 1, zeros))
binary_data = np.reshape(binary_data, (2**N, self.bits))
bin_data_flat = binary_data.flatten()
return bin_data_flat
def hash(self):
"""
Performs the Toeplitz hashing.
Returns
-------
hashed_data : array
Digitized hashed data.
"""
N, data = self._calculate_N()
out_len = self._output_length(self.bits)
data_flat = self._dec_list_to_bin()
toep_mat = self._toep_mat(self.bits)
split = np.array_split(data_flat, self.bits * 2**(N-self.bits))
data_hashed = np.dot(toep_mat, split[0]) % 2
for index, data in enumerate(split[1:-1]):
sample_hashed = np.dot(toep_mat, data) % 2
data_hashed = np.append(data_hashed, sample_hashed)
data_hashed = np.array_split(data_hashed, out_len * 2**(N-self.bits))
decimal = []
for index, sample in enumerate(data_hashed):
x = ''.join([str(int(elem)) for elem in sample])
decimal = np.append(decimal, int(x, 2))
hashed_data = decimal[decimal != 254]
return hashed_data
# if __name__ == "__main__":
# time_stamp = "2021_7_6_10_52"
# z_measur = f"C:/Users/sarah/Box/CamachoLab/Christian/QRNG/data/{time_stamp}_data.p"
# z_data = pickle.load(open(z_measur, "rb"))
# data = np.array(z_data["z_powmeas"])[-1]
# t = Toeplitz(data, 8)