Levi-Civita tensor in numpy - numpy

I am looking for compact numpy code to produce the Levi-Civita tensor in any user-selected number of dimensions. Any ideas?

From the sympy tensor functions:
In [13]: tensor_functions.eval_levicivita(x,y,z)
Out[13]:
(-x + y)⋅(-x + z)⋅(-y + z)
──────────────────────────
2
def eval_levicivita(*args):
"""Evaluate Levi-Civita symbol."""
from sympy import factorial
n = len(args)
return prod(
prod(args[j] - args[i] for j in range(i + 1, n))
/ factorial(i) for i in range(n))
File: /usr/local/lib/python3.6/dist-packages/sympy/functions/special/tensor_functions.py
Type: function
For a reasonable number of dimensions the tensor size isn't that big, so I wouldn't worry about efficiency. For a start I'd try an iterative solution; it doesn't need to be fancy.

Using itertools
import numpy as np
import itertools
def levi_cevita_tensor(dim):
arr=np.zeros(tuple([dim for _ in range(dim)]))
for x in itertools.permutations(tuple(range(dim))):
mat = np.zeros((dim, dim), dtype=np.int32)
for i, j in zip(range(dim), x):
mat[i, j] = 1
arr[x]=int(np.linalg.det(mat))
return arr
https://en.wikipedia.org/wiki/Levi-Civita_symbol#Product

Related

How do I avoid using insert for a dictionary to increase performance?

My code looks like this:
import pandas as pd
import numpy as np
from skimage.io import imread
df = pd.DataFrame()
for i in range(1000):
try:
image = imread(f"Images/{i}.jpg")
featureMatrix = np.zeros((image.shape[0], image.shape[1]))
for j in range(0, image.shape[0]):
for k in range(0, image.shape[1]):
featureMatrix[j][k] = ((int(image[j, k, 0]) + int(image[j, k, 1]) + int(image[j, k, 2])) / 3)
features = pd.Series(np.reshape(featureMatrix, (image.shape[0] * image.shape[1])))
df[f"{i}"] = features
except:
pass
df.to_csv("Features.csv")
And when I run it I get a PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling frame.insert many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use newframe = frame.copy() when 'df[f"{i}"] = features' is run
I have tried using pd.concat but I am cannot get it to work. Any ideas on how I should replace the line?
To improve performance and optimize processing avoid inserting a new Series into a dataframe on each of 1000 iterations.
Instead yield all series (with setting their name) with a generator function and concat them at once with pd.concat:
def collect_features():
for i in range(1000):
try:
image = imread(f"Images/{i}.jpg")
featureMatrix = np.zeros((image.shape[0], image.shape[1]))
for j in range(0, image.shape[0]):
for k in range(0, image.shape[1]):
featureMatrix[j][k] = ((int(image[j, k, 0]) + int(image[j, k, 1]) + int(image[j, k, 2])) / 3)
yield pd.Series(np.reshape(featureMatrix, (image.shape[0] * image.shape[1])), name=f"{i}")
except:
pass
pd.concat(list(collect_features()), axis=1).to_csv("Features.csv")
what about this alternative approach ?
import pandas as pd
import numpy as np
from skimage.io import imread
df_list = []
for i in range(1000):
try:
image = imread(f"Images/{i}.jpg")
featureMatrix = np.zeros((image.shape[0], image.shape[1]))
for j in range(0, image.shape[0]):
for k in range(0, image.shape[1]):
featureMatrix[j][k] = ((int(image[j, k, 0]) + int(image[j, k, 1]) + int(image[j, k, 2])) / 3)
features = pd.Series(np.reshape(featureMatrix, (image.shape[0] * image.shape[1])))
df_list.append(features)
except:
pass
df = pd.concat(df_list, axis=1)
df.to_csv("Features.csv")

plotting a graph of a sequence and get a dimension error

I'm trying to create a plot in Python to illustrate how my sequence changes as n grows. I get a dimension error. How can I fix this?
My code:
import matplotlib.pyplot as plt
import numpy as np
x = np.zeros(101)
x[0] = 0
for n in range(0, 101):
x[n] = x[n-1] - n
if x[n] < 0:
x[n] = x[n-1] + n
y = set(x)
print(y)
i = np.linspace(0, 100)
plt.plot(y, i, 'g')
Error:
ValueError: x and y must have same first dimension, but have shapes (1,) and (50,)
The problem is you are using plt.plot with a set and because of that its saying first dimension has shape (1,). The x-argument in plt.plot should be a array-like or scalar you can read more in the documentation so you can convert it to a list:
y = list(set(x))
Also you need to make sure that the for each value in y there is a corresponding value in i (y and i need to be the same shape). So you need to set np.linspace to return len(y) values:
i = np.linspace(0, 100, len(y))
The code:
import matplotlib.pyplot as plt
import numpy as np
x = np.zeros(101)
x[0] = 0
for n in range(0,101):
x[n] = x[n-1] - n
if x[n]<0:
x[n] = x[n-1] + n
y = list(set(x))
i = np.linspace(0, 100, len(y))
plt.plot(y, i,'g')
plt.show()
Output:

How do I vectorize a function in numpy with some fixed parameters?

I have written a code for approximating a function with the Bernstein polynomials ( https://en.wikipedia.org/wiki/Bernstein_polynomial )
at
https://github.com/pdenapo/metodos-numericos/blob/master/python/bernstein.py
I have a function that gives the polynomial approximating f as bernstein(f, n, p) (where f is the function that I want to approximate, n is the degree and p the point where it is evaluated.
def bernstein(f, n, p):
return np.sum(
[f(k / n) * st.binom.pmf(k, n, p) for k in np.arange(0, n + 1)])
Now I want to generate a plot of this function where f and n es fixed, and p runs though a vector generated by np.arrange
So I am vectorizing the function in the following way:
bernstein3 = lambda x: bernstein(f, 3, x)
bernstein3 = np.vectorize(bernstein3)
y3 = bernstein3(x)
plt.plot(x, y3, 'green', label='$B_3$')
It works. But I guess there must be some more elegant, or perhaps more pythonic way of doing this. Any suggestions? Many thanks
Since SciPy statistic functions are vectorized, your bernstein function can be modified in a straightforward manner to work that way:
import numpy as np
import scipy.stats
def bernstein(f, n, p):
# Vector of k values
k = np.arange(n + 1)
# Add a broadcasting dimension to p
pd = np.expand_dims(p, -1)
# Compute approximation
return np.sum(f(k / n) * scipy.stats.binom.pmf(k, n, pd), -1)
It would be used simply as this:
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return np.abs(1 / 2 - x)
x = np.linspace(0, 1, 100)
y = f(x)
plt.plot(x, y, 'blue', label='f(x)')
y_approx = bernstein(f, 10, x)
plt.plot(x, y_approx, 'orange', label='f_approx(x)')
plt.show()

how to calculate the gradient in python numpy

i have to implement the Stochastic Gradient Descent in Numpy. So I've to define the gradient of this function E:
In which also f and g are defined in the image.
I've no idea of how to do this, I tried with Sympy and numdifftools but these libraries give me some errors.
How could I write the gradient of the function E?
Thank you
you mean this?
import numpy as np
# G function
def g(x):
return np.tanh(x/2)
# F function
def f(x, N, n, v, g):
sumf = 0
for j in range(1, N):
sumi = 0
for i in range(1, n):
sumi += w[j, i]*x[i] - b[j]
sumf += v[j]*g(sumi)
return sumf

array of neighbor averages

What is the function func which computes n-1-sized array of averages of consequent elements of an array of size n (i.e. moving average with window width 2)?
func(numpy.array([1,2,3,4,5]))
# return numpy.array([1.5, 2.5, 3.5, 4.5])
No need for a function here:
import numpy as np
x = np.array([1,2,3,4,5])
x_f2 = 0.5*(x[1:] + x[:-1])
If you want it as a function:
def window(x, n):
return (x[(n-1):] + x[:-(n-1)])/float(n)
>>> x = np.array([1,2,3,4,5])
>>> np.vstack([x[1:], x[:-1]]).mean(axis=0)