I am trying to create an Euclidean algorithm (to solve Bezout's Relation) for 2 polynomials in the GF(2^8).
I currently have this code for my different operations
class ReedSolomon:
gfSize = 256
genPoly = 285
log = [0]*gfSize
antilog = [0]*gfSize
def _genLogAntilogArrays(self):
self.antilog[0] = 1
self.log[0] = 0
self.antilog[255] = 1
for i in range(1,255):
self.antilog[i] = self.antilog[i-1] << 1
if self.antilog[i] >= self.gfSize:
self.antilog[i] = self.antilog[i] ^ self.genPoly
self.log[self.antilog[i]] = i
def __init__(self):
self._genLogAntilogArrays()
def _galPolynomialDivision(self,dividend, divisor):
result = dividend.copy()
for i in range(len(dividend) - (len(divisor)-1)):
coef = result[i]
if coef != 0:
for j in range(1, len(divisor)):
if divisor[j] != 0:
result[i + j] ^= self._galMult(divisor[j], coef) # équivalent result[i + j] += -divisor[j] * coef car dans un champ GF(2) addition <=> substraction <=> XOR
remainderIndex = -(len(divisor)-1)
return result[:remainderIndex], result[remainderIndex:]
def _galMultiplicationPolynomiale(self, x,y):
result = [0]*(len(x)+len(y)-1)
for i in range(len(x)):
for j in range(len(y)):
result[i+j] ^= self._galMult(x[i],y[j])
return result
def _galMult(self,x,y):
if ((x == 0) or (y == 0)):
val = 0
else:
val = self.antilog[(self.log[x] + self.log[y])%255]
return val
def _galPolynomialAddition(self, a, b):
polSum = [0] * max(len(a), len(b))
for index in range(0, len(a)):
polSum[index + len(polSum) - len(a)] = a[index]
for index in range(0, len(b)):
polSum[index + len(polSum) - len(b)] ^= b[index]
return (polSum)
And here is my euclidean algorithm :
def _galEuclideanAlgorithm(self,a,b):
r0 = a.copy()
r1 = b.copy()
u0 = [1]
u1 = [0]
v0 = [0]
v1 = [1]
while max(r1) != 0:
print(r1)
q,r = self._galPolynomialDivision(r0,r1)
r0 = self._galPolynomialAddition(self._galMultiplicationPolynomiale(q,r1),r)
r1,r0 = self._galPolynomialAddition(r0,self._galMultiplicationPolynomiale(q,r1)),r1.copy()
u1,u0 = self._galPolynomialAddition(u0,self._galMultiplicationPolynomiale(q,u1)),u1.copy()
v1,v0 = self._galPolynomialAddition(v0,self._galMultiplicationPolynomiale(q,v1)),v1.copy()
return r1,u1,v1
I don't understand my issue where my algorithm is looping, here is my remainder output with my tests:
rs = ReedSolomon()
a = [1,15,7,8,0,11]
b = [1,0,0,0,0,0,0]
print(rs._galEuclideanAlgorithm(b,a))
#Console output
'''
[1, 15, 7, 8, 0, 11]
[0, 0, 82, 37, 120, 11, 105]
[1, 15, 7, 8, 0, 11]
[0, 0, 82, 37, 120, 11, 105]
[1, 15, 7, 8, 0, 11]
[0, 0, 82, 37, 120, 11, 105]
[1, 15, 7, 8, 0, 11]
'''
I know it might seem like I'm throwing some code just expecting an answer, but I'm genuinely searching for the error.
Thanks in advance !
I created a Python package called galois that does this. galois extends NumPy arrays to operate over Galois fields. The code is written in Python but JIT compiled with Numba for speed. In addition to array arithmetic, it also supports polynomials over Galois fields. ...And Reed-Solomon codes are implemented too :)
The Extended Euclidean Algorithm to solve the Bezout identity for two polynomials in GF(2^8) would be solved this way. Below is an abbreviated chunk of source code. You can see my full source code here.
def poly_egcd(a, b):
field = a.field
zero = Poly.Zero(field)
one = Poly.One(field)
r2, r1 = a, b
s2, s1 = one, zero
t2, t1 = zero, one
while r1 != zero:
q = r2 / r1
r2, r1 = r1, r2 - q*r1
s2, s1 = s1, s2 - q*s1
t2, t1 = t1, t2 - q*t1
# Make the GCD polynomial monic
c = r2.coeffs[0] # The leading coefficient
if c > 1:
r2 /= c
s2 /= c
t2 /= c
return r2, s2, t2
And here is a complete example using the galois library and the polynomials from your example. (I'm assuming the highest-degree coefficient is first?)
In [1]: import galois
In [2]: GF = galois.GF(2**8)
In [3]: print(GF.properties)
GF(2^8):
characteristic: 2
degree: 8
order: 256
irreducible_poly: x^8 + x^4 + x^3 + x^2 + 1
is_primitive_poly: True
primitive_element: x
In [4]: a = galois.Poly([1,15,7,8,0,11], field=GF); a
Out[4]: Poly(x^5 + 15x^4 + 7x^3 + 8x^2 + 11, GF(2^8))
In [5]: b = galois.Poly([1,0,0,0,0,0,0], field=GF); b
Out[5]: Poly(x^6, GF(2^8))
In [6]: d, s, t = galois.poly_egcd(a, b); d, s, t
Out[6]:
(Poly(1, GF(2^8)),
Poly(78x^5 + 7x^4 + 247x^3 + 74x^2 + 152, GF(2^8)),
Poly(78x^4 + 186x^3 + 45x^2 + x + 70, GF(2^8)))
In [7]: a*s + b*t == d
Out[7]: True
Related
I am attempting to implement a perceptron. I have loaded a 100x2 array of values between 0 and 100. Each item in the array has a label of either -1 or 1.
I believe the perceptron is working, however I cannot plot decision boundary as shown here: plot decision boundary matplotlib
When I run my code I only see a single color background. I would expect to see two colors, one color for each label in my data set (-1 and 1).
My current output, I expect to see 2 colors for the background (-1 or 1)
An example of what I hope to see, from the sklearn documentation
import numpy as np
from matplotlib import pyplot as plt
def generate_data():
#generate a dataset that is linearly seperable
group_1 = np.random.randint(50, 100, size=(50,2))
group_1_labels = np.full((50,1), 1)
group_2 = np.random.randint(0, 49, size =(50,2))
group_2_labels = np.full((50,1), -1)
#add a bias value of -1
bias = np.full((50,1), -1)
#add labels, upper right quadrant are 1, lower left are -1
group_1_with_bias = np.hstack((group_1, bias))
group_2_with_bias = np.hstack((group_2, bias))
group_1_labeled = np.hstack((group_1_with_bias, group_1_labels))
group_2_labeled = np.hstack((group_2_with_bias, group_2_labels))
#merge our labeled data and shuffle!
merged_data = np.vstack((group_1_labeled, group_2_labeled))
np.random.shuffle(merged_data)
return merged_data
data = generate_data()
#load data, strip labels, add a -1 bias value
X = data[:, :3]
#create labels matrix
l = np.ravel(data[:, 3:])
def perceptron_sgd(X, l, c, epochs):
#initialize weights
w = np.zeros(3)
errors = []
for epoch in range(epochs):
total_error = 0
for i, x in enumerate(X):
if (np.dot(x, w) * l[i]) <= 0:
total_error += (np.dot(x, w) * l[i])
w = w + c * (x * l[i])
errors.append(total_error * -1)
print "epoch " + str(epoch) + ": " + str(w)
return w, errors
def classify(X, l, w):
z = np.dot(X, w)
print z
z[z <= 0] = -1
z[z > 0] = 1
#return a matrix of predicted labels
return z
w, errors = perceptron_sgd(X, l, .001, 36)
# X - some data in 2dimensional np.array
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, .2), np.arange(y_min, y_max, .2))
# here "model" is your model's prediction (classification) function
Z = classify(np.c_[xx.ravel(), yy.ravel()], l, w[:-1]) #strip the bias from weights
# Put the result into a color plot
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)
plt.axis('off')
#Plot also the training points
plt.scatter(X[:, 0], X[:, 1], c=l, cmap=plt.cm.Paired)
I got it to work.
Standardized your X
from sklearn import preprocessing
scaler = preprocessing.StandardScaler().fit(X[:, :-1])
X_trans = np.column_stack((scaler.transform(X[:, :-1]), X[:, -1]))
Better initialization than zero.
#initialize weights
r = np.sqrt(2)
w = np.random.uniform(-r, r, (3,))
Add learned biases during prediction
z = np.dot(X, w[:-1]) + w[-1]
Standardize during prediction as well (using standardization learned from input)
Z = classify(scaler.transform(np.c_[xx.ravel(), yy.ravel()]),
l, w) #strip the bias from weights
Generally, always a good idea to standardize the inputs.
Entire code:
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
def generate_data():
#generate a dataset that is linearly seperable
group_1 = np.random.randint(50, 100, size=(50,2))
group_1_labels = np.full((50,1), 1)
group_2 = np.random.randint(0, 49, size =(50,2))
group_2_labels = np.full((50,1), -1)
#add a bias value of -1
bias = np.full((50,1), -1)
#add labels, upper right quadrant are 1, lower left are -1
group_1_with_bias = np.hstack((group_1, bias))
group_2_with_bias = np.hstack((group_2, bias))
group_1_labeled = np.hstack((group_1_with_bias, group_1_labels))
group_2_labeled = np.hstack((group_2_with_bias, group_2_labels))
#merge our labeled data and shuffle!
merged_data = np.vstack((group_1_labeled, group_2_labeled))
np.random.shuffle(merged_data)
return merged_data
data = generate_data()
#load data, strip labels, add a -1 bias value
X = data[:, :3]
#create labels matrix
l = np.ravel(data[:, 3:])
from sklearn import preprocessing
scaler = preprocessing.StandardScaler().fit(X[:, :-1])
X_trans = np.column_stack((scaler.transform(X[:, :-1]), X[:, -1]))
def perceptron_sgd(X, l, c, epochs):
#initialize weights
r = np.sqrt(2)
w = np.random.uniform(-r, r, (3,))
errors = []
for epoch in range(epochs):
total_error = 0
for i, x in enumerate(X):
if (np.dot(x, w) * l[i]) <= 0:
total_error += (np.dot(x, w) * l[i])
w = w + c * (x * l[i])
errors.append(total_error * -1)
print("epoch " + str(epoch) + ": " + str(w))
return w, errors
def classify(X, l, w):
z = np.dot(X, w[:-1]) + w[-1]
print(z)
z[z <= 0] = -1
z[z > 0] = 1
#return a matrix of predicted labels
return z
w, errors = perceptron_sgd(X_trans, l, .01, 25)
# X - some data in 2dimensional np.array
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, .1), np.arange(y_min, y_max, .1))
# here "model" is your model's prediction (classification) function
Z = classify(scaler.transform(np.c_[xx.ravel(), yy.ravel()]), l, w) #strip the bias from weights
# Put the result into a color plot
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, alpha=0.4)
#plt.axis('off')
#Plot also the training points
plt.scatter(X[:, 0], X[:, 1], c=l, cmap=plt.cm.Paired)
So I wanted to see if I could make fractal flames using matplotlib and figured a good test would be the sierpinski triangle. I modified a working version I had that simply performed the chaos game by normalizing the x range from -2, 2 to 0, 400 and the y range from 0, 2 to 0, 200. I also truncated the x and y coordinates to 2 decimal places and multiplied by 100 so that the coordinates could be put in to a matrix that I could apply a color map to. Here's the code I'm working on right now (please forgive the messiness):
import numpy as np
import matplotlib.pyplot as plt
import math
import random
def f(x, y, n):
N = np.array([[x, y]])
M = np.array([[1/2.0, 0], [0, 1/2.0]])
b = np.array([[.5], [0]])
b2 = np.array([[0], [.5]])
if n == 0:
return np.dot(M, N.T)
elif n == 1:
return np.dot(M, N.T) + 2*b
elif n == 2:
return np.dot(M, N.T) + 2*b2
elif n == 3:
return np.dot(M, N.T) - 2*b
def norm_x(n, minX_1, maxX_1, minX_2, maxX_2):
rng = maxX_1 - minX_1
n = (n - minX_1) / rng
rng_2 = maxX_2 - minX_2
n = (n * rng_2) + minX_2
return n
def norm_y(n, minY_1, maxY_1, minY_2, maxY_2):
rng = maxY_1 - minY_1
n = (n - minY_1) / rng
rng_2 = maxY_2 - minY_2
n = (n * rng_2) + minY_2
return n
# Plot ranges
x_min, x_max = -2.0, 2.0
y_min, y_max = 0, 2.0
# Even intervals for points to compute orbits of
x_range = np.arange(x_min, x_max, (x_max - x_min) / 400.0)
y_range = np.arange(y_min, y_max, (y_max - y_min) / 200.0)
mat = np.zeros((len(x_range) + 1, len(y_range) + 1))
random.seed()
x = 1
y = 1
for i in range(0, 100000):
n = random.randint(0, 3)
V = f(x, y, n)
x = V.item(0)
y = V.item(1)
mat[norm_x(x, -2, 2, 0, 400), norm_y(y, 0, 2, 0, 200)] += 50
plt.xlabel('x0')
plt.ylabel('y')
fig = plt.figure(figsize=(10,10))
plt.imshow(mat, cmap="spectral", extent=[-2,2, 0, 2])
plt.show()
The mathematics seem solid here so I suspect something weird is going on with how I'm handling where things should go into the 'mat' matrix and how the values in there correspond to the colormap.
If I understood your problem correctly, you need to transpose your matrix using the method .T. So just replace
fig = plt.figure(figsize=(10,10))
plt.imshow(mat, cmap="spectral", extent=[-2,2, 0, 2])
plt.show()
by
fig = plt.figure(figsize=(10,10))
ax = gca()
ax.imshow(mat.T, cmap="spectral", extent=[-2,2, 0, 2], origin="bottom")
plt.show()
The argument origin=bottom tells to imshow to have the origin of your matrix at the bottom of the figure.
Hope it helps.
I have the following code to find the only integer in a list which appears only once while all other appear 3 times. The code works fine for positive integers, but have problem with negative integers.
Can anyone help me fix it? Thanks.
class Solution:
# #param A, a list of integer
# #return an integer
def singleNumber(self, A):
if(A==None):
return None
else:
s=[0]*32
ans=0
for i in range(len(s)):
for j in A[:]:
if (j>>i)&1:
s[i] +=1
s[i]=s[i]%3
ans |= (s[i]<<i)
return ans
collections.Counter is useful for this kind of thing and won't choke on negative numbers.
>>> import collections
>>> l = [1, 1, 1, 2, 3, 3, 3, 4, 4, 4]
>>> c = collections.Counter(l).items()
>>> [k for k, v in c if v == 1][0]
2
>>> l = [-i for i in l]
>>> c = collections.Counter(l).items()
>>> [k for k, v in c if v == 1][0]
-2
def getSingle( arr, n):
ones = 0
twos = 0
for i in range(0,n):
twos = twos | (ones & arr[i]);
ones = ones ^ arr[i];
common_bit_mask = ~(ones & twos);
ones = ones & common_bit_mask;
twos = twos & common_bit_mask;
return ones;
Works for negative numbers too.
https://ideone.com/365Iie
My understanding is that (one use of) numpy's vectorize allows me to send an array to a function that normally only takes scalars, instead of using the built in map function (in combination with a lambda function or the like). However, under the following scenario I am getting different results when I use map vs numpy.vectorize and I can't seem to figure out why.
import numpy as np
def basis2(dim, k, x):
y = np.array([-0.2, -0.13, -0.06, 0, 0.02, 0.06, 0.15, 0.3, 0.8,
1.6, 3.1, 6.1, 10.1, 15.1, 23.1, 30.1, 35.0, 40.0, 45.0, 50.0, 55.0])
if x < y[k] or x > y[k + dim + 1]:
return 0
elif dim != 0:
ret = ((x - y[k]) / (y[k + dim] - y[k])) * basis2(dim - 1, k, x) + (
(y[k + dim + 1] - x) / (y[k + dim + 1] - y[k + 1])) * basis2(dim - 1, k + 1, x)
return ret
else:
return 1.0
w = np.array([20.0, 23.1, 30.0])
func = lambda x: basis2(3, 14, x)
vec = map(func, w)
func2 = np.vectorize(basis2)
vec2 = func2(3, 14, w)
print vec # = [0, 0.0, 0.23335417007039491]
print vec2 # = [0 0 0]
As the docstring says:
The data type of the output of vectorized is determined by calling
the function with the first element of the input. This can be avoided
by specifying the otypes argument.
you need to add a otypes argument:
func2 = np.vectorize(basis2, otypes="d")
or change return 0 to return 0.0 in basis2().
I am trying to write a function that determines if a number n is prime or composite using the Lucas pseudoprime test; at the moment, I am working with the standard test, but once I get that working I will then write the strong test. I am reading the paper by Baillie and Wagstaff, and following the implementation by Thomas Nicely in the trn.c file.
I understand that the full test involves several steps: trial division by small primes, checking that n is not a square, performing a strong pseudoprimality test to base 2, then finally the Lucas pseudoprime test. I can handle all the other pieces, but I am having trouble with the Lucas pseudoprime test. Here is my implementation, in Python:
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def jacobi(a, m):
a = a % m; t = 1
while a != 0:
while a % 2 == 0:
a = a / 2
if m % 8 == 3 or m % 8 == 5:
t = -1 * t
a, m = m, a # swap a and m
if a % 4 == 3 and m % 4 == 3:
t = -1 * t
a = a % m
if m == 1:
return t
return 0
def isLucasPrime(n):
dAbs, sign, d = 5, 1, 5
while 1:
if 1 < gcd(d, n) > n:
return False
if jacobi(d, n) == -1:
break
dAbs, sign = dAbs + 2, sign * -1
d = dAbs * sign
p, q = 1, (1 - d) / 4
print "p, q, d =", p, q, d
u, v, u2, v2, q, q2 = 0, 2, 1, p, q, 2 * q
bits = []
t = (n + 1) / 2
while t > 0:
bits.append(t % 2)
t = t // 2
h = -1
while -1 * len(bits) <= h:
print "u, u2, v, v2, q, q2, bits, bits[h] = ",\
u, u2, v, v2, q, q2, bits, bits[h]
u2 = (u2 * v2) % n
v2 = (v2 * v2 - q2) % n
if bits[h] == 1:
u = u2 * v + u * v2
u = u if u % 2 == 0 else u + n
u = (u / 2) % n
v = (v2 * v) + (u2 * u * d)
v = v if v % 2 == 0 else v + n
v = (v / 2) % n
if -1 * len(bits) < h:
q = (q * q) % n
q2 = q + q
h = h - 1
return u == 0
When I run this, isLucasPrime returns False for such primes as 83 and 89, which is incorrect. It also returns False for the composite 111, which is correct. And it returns False for the composite 323, which I know is a Lucas pseudoprime for which isLucasPrime should return True. In fact, isLucasPseudoprime returns False for every n on which I have tested it.
I have several questions:
1) I'm not expert with C/GMP, but it seems to me that Nicely runs through the bits of (n+1)/2 from right-to-left (least significant to most significant) where other authors run through the bits left-to-right. My code shown above runs through the bits left-to-right, but I have also tried running through the bits right-to-left, with the same result. Which order is correct?
2) It looks odd to me that Nicely only updates the u and v variables for a 1-bit. Is this correct? I expected to update all four of the Lucas-chain variables each time through the loop, since the indexes of the chain increase at each step.
3) What have I done wrong?
1) I'm not expert with C/GMP, but it seems to me that Nicely runs through the bits of (n+1)/2 from right-to-left (least significant to most significant) where other authors run through the bits left-to-right. My code shown above runs through the bits left-to-right, but I have also tried running through the bits right-to-left, with the same result. Which order is correct?
Indeed, Nicely goes from least significant to most significant bit. He computes U(2^k) and V(2^k) (and Q^(2^k); all modulo N of course), in the mpzU2m and mpzV2m variables, and has U((N+1) % 2^k) resp V((N+1) % 2^k) stored in mpzU and mpzV. When a 1-bit is encountered, the remainder (N+1) % 2^k changes, and mpzU and mpzV are updated accordingly.
The other way is to compute U(p), U(p+1), V(p) and (optionally) V(p+1) for a prefix p of N+1 and combine those to compute U(2*p+1) and either U(2*p) or U(2*p+2) [ditto for V] depending on whether the next bit after the prefix p is 0 or 1.
Both methods are correct, like you can compute the power x^N going from left to right, having x^p and x^(p+1) as state, or from right to left having x^(2^k) and x^(N % 2^k) as state [and, computing U(n) and U(n+1) is basically computing ζ^n where ζ = (1 + sqrt(D))/2].
I - and others, apparently - find the left-to-right order simpler. I haven't done or read an analysis, it might be that right-to-left is computationally less expensive on average and Nicely chose right-to-left because of that.
2) It looks odd to me that Nicely only updates the u and v variables for a 1-bit. Is this correct? I expected to update all four of the Lucas-chain variables each time through the loop, since the indexes of the chain increase at each step.
Yes, that is correct, because the remainder (N+1) % 2^k == (N+1) % 2^(k-1) if the 2^k bit is 0.
3) What have I done wrong?
A small typo first:
if 1 < gcd(d, n) > n:
should be
if 1 < gcd(d, n) < n:
of course.
More substantially, you use the updates for Nicely's traversal order (right-to-left), but traverse in the other direction. That of course produces wrong results.
Further, when updating v
if bits[h] == 1:
u = u2 * v + u * v2
u = u if u % 2 == 0 else u + n
u = (u / 2) % n
v = (v2 * v) + (u2 * u * d)
v = v if v % 2 == 0 else v + n
v = (v / 2) % n
you use the new value of u, but you ought to use the old value.
def isLucasPrime(n):
dAbs, sign, d = 5, 1, 5
while 1:
if 1 < gcd(d, n) < n:
return False
if jacobi(d, n) == -1:
break
dAbs, sign = dAbs + 2, sign * -1
d = dAbs * sign
p, q = 1, (1 - d) // 4
u, v, u2, v2, q, q2 = 0, 2, 1, p, q, 2 * q
bits = []
t = (n + 1) // 2
while t > 0:
bits.append(t % 2)
t = t // 2
h = 0
while h < len(bits):
u2 = (u2 * v2) % n
v2 = (v2 * v2 - q2) % n
if bits[h] == 1:
uold = u
u = u2 * v + u * v2
u = u if u % 2 == 0 else u + n
u = (u // 2) % n
v = (v2 * v) + (u2 * uold * d)
v = v if v % 2 == 0 else v + n
v = (v // 2) % n
if h < len(bits) - 1:
q = (q * q) % n
q2 = q + q
h = h + 1
return u == 0
works (no guarantees, but I think it is correct, and have done some tests, all of which it passed).