So I was wondering (or don't understand the docs right) how to cast a string to be interpreted as Polynomial of a given ring.
So I know how to build the string in python for given definition but I have no idea how to cast that to the polynomial ring
So I figured it out. I needed to unterstand the ring.gens() so that I can use them as variables
def build(alpha, beta, gamma):
ring = PolynomialRing(GF(q, 'a'), 'x', 6)
poly = alpha
x = ring.gens()
for j in range(0, self.v):
for k in range(0, self.n):
if j is k:
poly += gamma[j, k] * x[j]
else:
poly += gamma[j, k] * x[j] * x[k]
for k in range(0, self.n):
poly += beta[k] * x[k]
return poly
Related
I am trying to bring something from an R package by Lotze & Loecher into python as all of the rest of the project is.
Here is the python code:
def dbeta(x,shape1,shape2):
from scipy.stats import beta
result=beta.pdf(x=x,a=shape1,b=shape2,loc=0,scale=1)
return result
def pbeta(q,shape1,shape2):
from scipy.stats import beta
result=beta.cdf(x=q,a=shape1,b=shape2,loc=0,scale=1)
return result
def combinations(array, tuple_length, prev_array=[]):
if len(prev_array) == tuple_length:
return [prev_array]
combs = []
for f, val in enumerate(array):
prev_array_extended = prev_array.copy()
prev_array_extended.append(val)
combs += combinations(array[f+1:], tuple_length, prev_array_extended)
return combs
After defining these functions here I have the problem with too many iterations in the function I think:
from scipy.integrate import quad
def best_binominal_bandit(x, n, alpha=1, beta=1):
ans = []
# x = vector of number of successes
# n = vector of number of tries
k = len(x)
l = list(range(0,k))
b = combinations(l, k-1)
for i in l:
indx = b[i]
def f(z):
r = dbeta(z, x[i] + alpha, n[i] - x[i] + beta)
for j in indx:
r = r*pbeta(z, x[j] + alpha, n[j] - x[j] + beta)
return r
a = quad(f, 0, 1)[0]
ans.append(a)
return ans
So when calling
x = [10,20,30,50]
n = [100,102,120,130]
best_binominal_bandit(x, n)
I do not receive similar results as they do in their specification. I have the feeling that there are just more iterations in the f function. After all, the bottom line should add up to 1.
I came up with a solution. I will post it here and then close the question. Seems like I misread something and made an easy mistake (that kept vexing me however).
The combination function is not necessary for what I intended, rather the ith element of the list simply needs to be excluded.
def dbeta(x,shape1,shape2):
from scipy.stats import beta
result=beta.pdf(x=x,a=shape1,b=shape2,loc=0,scale=1)
return result
def pbeta(q,shape1,shape2):
from scipy.stats import beta
result=beta.cdf(x=q,a=shape1,b=shape2,loc=0,scale=1)
return result
from scipy.integrate import quad
def best_binominal_bandit(x, n, alpha=1, beta=1):
ans = []
k = len(x)
l = list(range(0,k))
for i in l:
excluded_index = i
indx = l[:excluded_index] + l[excluded_index+1:]
def f(z):
r = dbeta(z, x[i] + alpha, n[i] - x[i] + beta)
print(z)
for j in indx:
r = r*pbeta(z, x[j] + alpha, n[j] - x[j] + beta)
return r
a = quad(f, 0, 1)[0]
ans.append(a)
return ans
All in all this seems to work for a python translation of: p. 648 in
Scott, S. L. (2010). A modern Bayesian look at the multi-armed bandit. Applied Stochastic Models in Business and Industry, 26(6), 639–658. doi:10.1002/asmb.874
O = self.feedback_df_normalised.to_numpy() # original matrix
K = self.latent_feature_count
P = np.random.rand(len(O), K) # user embeddings
Q = np.random.rand(len(O[0]), K) # show embeddings
Q_T = np.transpose(Q)
for i in range(len(O)):
print("i:", i)
for j in range(len(O[0])):
print("j:", j)
A_ij = np.dot(P[i,:], Q_T[:,j])
dif_ij = O[i, j] - A_ij
dif_sqd += dif_ij ** 2
for k in range(K):
P[i, k] = P[i, k] + alpha * (2 * dif_ij * Q_T[k, j] - beta * P[i, k])
Q_T[k, j] = Q_T[k, j] + alpha * (2 * dif_ij * P[i, k] - beta * Q_T[k, j])
print("dif_sqd:", dif_sqd)
if dif_sqd < accepted_deviation:
A = P # Q_T
break
have this algorithm implementing matrix factorisation via gradient based on this one:
https://towardsdatascience.com/recommendation-system-matrix-factorization-d61978660b4b#:~:text=Collaborative%20filtering%20is%20the%20application,items'%20and%20users'%20entities.&text=Hence%2C%20from%20the%20matrix%20factorization,in%20user's%20preferences%20and%20interactions.
Iterative relationship the algorithm aims to implement
The general format of O is something like this:
O = [
[5,3,0,1],
[4,0,0,1],
[1,1,0,5],
[1,0,0,4],
[0,1,5,4],
[2,1,3,0],
]
When O becomes large this becomes veerrrrryyyy slow to execute though. I've been banging my head trying to think about how to do this sans looping, but I'm not good enough with matrices to figure it out. Any help would be appreciated.
I'm trying to write a python code for a higher order (d=4) factorization machine that returns the scalar result y of
Where x is a vector of some length n, v is a vector of length n, w is an upper triangular matrix of size n by n, and t is a rank 4 tensor of size n by n by n by n. The easiest implementation is just for loops over each index:
for i in range(0,len(x)):
for j in range(0,len(x)):
for k in range(0,len(x)):
for l in range(0,len(x)):
y += t[i,j,k,l] * x[i] * x[j] * x[k] * x[l]
The first two terms are easily calculated:
y = u # x + x # v # x.T
My question- is there a better way of calculating the sum over the tensor than a nested for-loop? (currently looking at possible solutions in pytorch)
This seems like a perfect fit for torch.einsum:
>>> torch.einsum('ijkl,i,j,k,l->', t, *(x,)*4)
In expanded form, this looks like torch.einsum('ijkl,i,j,k,l->', t, x, x, x, x) and computes the value defined by your four for loops:
for i, j, k, l in cartesian_prod:
y += t[i,j,k,l] * x[i] * x[j] * x[k] * x[l]
Where cartesian_prod is the cartesian product: range(len(x))^4
Thank you swag2198
(c * x[:, None, None, None] * x[None, :, None, None] * x[None, None, :, None] * x[None, None, None, :]).sum()
Returns the same result as the for-loops when test on dummy values of x and t
RuntimeWarning: divide by zero encountered in double_scalars
While trying to insert array to an function
import numpy as np
import random
def lagrange(x, y, x_int):
n = x.size
y_int = 0
for i in range(0, n):
p = y[i]
for j in range(0, n):
if i != j:
p = p * (x_int - x[j]) / (x[i] - x[j])
y_int = y_int + p
return [y_int]
x = []
y = []
for i in range(1000):
x.append(random.randint(0,100))
y.append(random.randint(0,100))
fx = 3.5
print(lagrange(np.array(x),np.array(y),fx))
i expected to have 1000 iteration of output of an output, any solution to these problems?
Your error message refers to a function not mentioned in your code. But I assume the issue is because x[i] and x[j] could be the same number, and therefore you are dividing by zero on your p = p * (x_int - x[j]) / (x[i] - x[j]) line, which is not possible. You will need to add an exemption to do something different in the case x[i] equals x[j].
Since you're generating your x array randomly from a range of (0,100), and the array size is 1000, it's guranteed that x[i] = x[j] for some i,j. You need to ensure elements in x are unique.
See: How do I create a list of random numbers without duplicates?
In your nested loop could it be that you meant to do if x[i] != x[j]:
Those would be the values you wouldn't want to be the same in your division.
The Wikipedia entry for the Arnoldi method provides a Python example that produces basis of the Krylov subspace of a matrix A. Supposedly, if A is Hermitian (i.e. if A == A.conj().T) then the Hessenberg matrix h generated by this algorithm is tridiagonal (source). However, when I use the Wikipedia code on a real-world Hermitian matrix, the Hessenberg matrix is not at all tridiagonal. When I perform the computation on the real part of A (so that A == A.T) then I do get a tridiagonal Hessenberg matrix, so there seems to be a problem with the imaginary components of A. Does anybody know why the Wikipedia code doesn't produce the expected results?
Working example:
import numpy as np
import matplotlib.pyplot as plt
from scipy.linalg import circulant
def arnoldi_iteration(A, b, n):
m = A.shape[0]
h = np.zeros((n + 1, n), dtype=np.complex)
Q = np.zeros((m, n + 1), dtype=np.complex)
q = b / np.linalg.norm(b) # Normalize the input vector
Q[:, 0] = q # Use it as the first Krylov vector
for k in range(n):
v = A.dot(q) # Generate a new candidate vector
for j in range(k + 1): # Subtract the projections on previous vectors
h[j, k] = np.dot(Q[:, j], v)
v = v - h[j, k] * Q[:, j]
h[k + 1, k] = np.linalg.norm(v)
eps = 1e-12 # If v is shorter than this threshold it is the zero vector
if h[k + 1, k] > eps: # Add the produced vector to the list, unless
q = v / h[k + 1, k] # the zero vector is produced.
Q[:, k + 1] = q
else: # If that happens, stop iterating.
return Q, h
return Q, h
# Construct matrix A
N = 2**4
I = np.eye(N)
k = np.fft.fftfreq(N, 1.0 / N) + 0.5
alpha = np.linspace(0.1, 1.0, N)*2e2
c = np.fft.fft(alpha) / N
C = circulant(c)
A = np.einsum("i, ij, j->ij", k, C, k)
# Show that A is Hermitian
print(np.allclose(A, A.conj().T))
# Arbitrary (random) initial vector
np.random.seed(0)
v = np.random.rand(N)
# Perform Arnoldi iteration with complex A
_, h = arnoldi_iteration(A, v, N)
# Perform Arnoldi iteration with real A
_, h2 = arnoldi_iteration(np.real(A), v, N)
# Plot results
plt.subplot(121)
plt.imshow(np.abs(h))
plt.title("Complex A")
plt.subplot(122)
plt.imshow(np.abs(h2))
plt.title("Real A")
plt.tight_layout()
plt.show()
Result:
After browsing through some conference presentation slides, I realised that at some point Q had to be conjugated when A is complex. The correct algorithm is posted below for reference, with the code change marked (note that this correction has also been submitted to the Wikipedia entry):
import numpy as np
def arnoldi_iteration(A, b, n):
m = A.shape[0]
h = np.zeros((n + 1, n), dtype=np.complex)
Q = np.zeros((m, n + 1), dtype=np.complex)
q = b / np.linalg.norm(b)
Q[:, 0] = q
for k in range(n):
v = A.dot(q)
for j in range(k + 1):
h[j, k] = np.dot(Q[:, j].conj(), v) # <-- Q needs conjugation!
v = v - h[j, k] * Q[:, j]
h[k + 1, k] = np.linalg.norm(v)
eps = 1e-12
if h[k + 1, k] > eps:
q = v / h[k + 1, k]
Q[:, k + 1] = q
else:
return Q, h
return Q, h