Я играю со случайным блужданием, у меня два очка. Первый идет хаотично, второй пытается выбраться из своей области, которая задается формулой e^(-t), где t — расстояние между двумя точками. На мой взгляд, это не сложная программа, но ее запуск с сотней точек для расчета занимает около минуты, поэтому я прошу вас помочь мне найти способ ускорить ее и объяснить мне.
import numpy as np
import matplotlib.pyplot as plt
def f(x, y, zx, zy):
return np.exp(-np.sqrt((x-zx)**2+(y-zy)**2))
x = y = np.linspace(-100, 100, 1000)
X, Y = np.meshgrid(x, y)
fig, ax = plt.subplots(1, 1, figsize=(12, 6))
#random picking first location for two points
loksx = [np.random.randn(), ]
loksy = [np.random.randn(), ]
lokzx = [np.random.randn(), ]
lokzy = [np.random.randn(), ]
for i in range(100):
lokzx.append(np.random.randn()+lokzx[-1])
lokzy.append(np.random.randn()+lokzy[-1])
nsx = np.random.randn()
nsy = np.random.randn()
#checking if the next step has smaller value than the last one
if f(loksx[-1]+nsx, loksy[-1]+nsy, lokzx[-1], lokzy[-1]) < f(loksx[-1], loksy[-1], lokzx[-1], lokzy[-1]):
loksx.append(nsx+loksx[-1])
loksy.append(nsy+loksy[-1])
Z = []
for i in range(len(lokzx)):
Z.append(f(X, Y, lokzx[i], lokzy[i]))
ax.plot(lokzx[0], lokzy[0], 'y,',markersize=1)
ax.plot(loksx[0], loksy[0], 'w,', markersize=1)
ax.plot(lokzx[1:-1], lokzy[1:-1], 'g,',markersize=1)
ax.plot(loksx[1:-1], loksy[1:-1], 'b,', markersize=1)
ax.plot(loksx[-1], loksy[-1], 'k,', markersize=1)
ax.plot(lokzx[-1], lokzy[-1], 'r,',markersize=1)
for i in range(len(Z)):
ax.contourf(X, Y, Z[i], 20, cmap='RdGy', alpha=0.01)
ax.plot()
ax.set_aspect('equal')
plt.show()
@редактировать Теперь вместо списков я использую nparrays:
import numpy as np
import matplotlib.pyplot as plt
def f(x, y, zx, zy):
return np.exp(-np.sqrt((x-zx)**2+(y-zy)**2))
x = y = np.linspace(-100, 100, 1000)
X, Y = np.meshgrid(x, y)
fig, ax = plt.subplots(1, 1, figsize=(12, 6))
lokzx = np.random.randn(100)
lokzy = np.random.randn(100)
loksx = np.zeros(100)
loksy = np.zeros(100)
for i in range(1,100):
nsx = np.random.randn()
nsy = np.random.randn()
if f(loksx[i-1]+nsx, loksy[i-1]+nsy, lokzx[i-1], lokzy[i-1]) < f(loksx[i-1], loksy[i-1], lokzx[i-1], lokzy[i-1]):
loksx[i] = loksx[i-1]+nsx
loksy[i] = loksy[i-1]+nsy
else:
loksx[i] = loksx[i-1]
loksy[i] = loksy[i-1]
Z = np.zeros((100,1000,1000))
for i in range(len(lokzx)):
Z[i] = f(X, Y, lokzx[i], lokzy[i])
ax.plot(lokzx[0], lokzy[0], 'y,',markersize=1)
ax.plot(loksx[0], loksy[0], 'w,', markersize=1)
ax.plot(lokzx[1:-1], lokzy[1:-1], 'g,',markersize=1)
ax.plot(loksx[1:-1], loksy[1:-1], 'b,', markersize=1)
ax.plot(loksx[-1], loksy[-1], 'k,', markersize=1)
ax.plot(lokzx[-1], lokzy[-1], 'r,',markersize=1)
for i in range(len(Z)):
ax.contourf(X, Y, Z[i], 20, cmap='RdGy', alpha=0.01)
ax.plot()
ax.set_aspect('equal')
plt.show()
Но все же требуется время, чтобы запустить это. Единственная оставшаяся проблема - это две строки кода:
for i in range(len(Z)):
ax.contourf(X, Y, Z[i], 20, cmap='RdGy', alpha=0.01)
Но я не знаю, как переписать это без использования цикла.
здесь есть хорошая документация: bastibe.de/2013-05-30-speeding-up-matplotlib.html
Хорошо, вы звоните контуру 1000 раз. Это точно будет медленно. Непонятно, почему вы 1000 раз звоните в контур.
@JodyKlymak, потому что я хочу увидеть, какая площадь была в каждой точке
Можете ли вы связать изображение с тем, что вы пытаетесь сделать?
@JodyKlymak вот что я пытаюсь сделать: imgur.com/a/JXdnZB8
Изображение на Imagur просто бордового цвета по осям...
@JodyKlymak здесь у вас более увеличенная версия: imgur.com/a/YTmj7vL
Я не знаю, что, по вашему мнению, вы можете увидеть с этим контуром; это просто беспорядок для меня. Выполнение 1000 из них определенно займет некоторое время. Предложите вам придумать визуализацию, которая не требует так много контуров. Зрителю не так сложно измерить расстояние от точки.
Вы должны попытаться избежать циклов, научившись использовать соответствующие функции numpy. то есть что-то вроде ниже будет намного быстрее:
dx = np.random.randn(100)
dy = np.random.randn(100)
x = np.cumsum(dx)
y = np.cumsum(dy)
Если вам В самом деле нужен цикл for, предварительно выделите свой массив; не продолжайте добавлять:
x = np.zeros(100)
y = np.zeros(100)
for i in range(1, 100):
x[i] = x[i-1] + np.random.randn()
y[i] = y[i-1] + np.random.randn()
Несмотря на изменения, ему все еще нужно время, чтобы нарисовать его. Я думаю, что основная проблема заключается в этом цикле: python for i in range(len(Z)): ax.contourf(X, Y, Z[i], 20, cmap='RdGy', alpha=0.01)
но я не знаю, как я могу написать это по-другому.
Это, вероятно, не заговор, который является медленным. Скорее всего это петли.