使用pygame在python中优化Mandelbrot集

55ooxyrt  于 2024-01-05  发布在  Python
关注(0)|答案(2)|浏览(161)

我使用了2个for循环来检查点是否在集合内,但显然这花费了太多的时间,在图本身上给出的细节较少。我如何优化代码以更快地运行,从而为图添加更多的细节?pygame原点在左上角,所以我手动设置每个点相对于中心的位置。

  1. import math
  2. import pygame
  3. class Point:
  4. def __init__(self, x, y):
  5. self.x = x - 250
  6. self.y = y - 250
  7. class Complex:
  8. def __init__(self, real, imaginary):
  9. self.real = real
  10. self.imaginary = imaginary
  11. def __eq__(self, other):
  12. if self.real == other.real:
  13. if self.imaginary == other.imaginary:
  14. return True
  15. return False
  16. def __abs__(self):
  17. return math.sqrt(self.real ** 2 + self.imaginary ** 2)
  18. def __round__(self, n=None):
  19. return Complex(round(self.real, 4), round(self.imaginary, 4))
  20. def __add__(self, other):
  21. return Complex(self.real + other.real, self.imaginary + other.imaginary)
  22. def __sub__(self, other):
  23. return Complex(self.real - other.real, self.imaginary - other.imaginary)
  24. def __mul__(self, other):
  25. return Complex((self.real * other.real) - (self.imaginary * other.imaginary),
  26. (self.real * other.imaginary) + (self.imaginary * other.real))
  27. def zheta(z, c):
  28. return round((z * z) + c, 3)
  29. def mandelbrotNumber(num):
  30. z0 = Complex(0, 0)
  31. c = num
  32. checkList = [Complex(0, 0)]
  33. for i in range(10):
  34. z = zheta(z0, c)
  35. if abs(z) > 2:
  36. return False
  37. if z in checkList:
  38. return True
  39. checkList.append(z)
  40. z0 = z
  41. return True
  42. def plotPoint(x, y):
  43. color = (0, 0, 0)
  44. position = (x, y)
  45. pygame.draw.circle(screen, color, position, 2)
  46. pygame.init()
  47. screen = pygame.display.set_mode((500, 500))
  48. running = True
  49. startPosX = (0, 250)
  50. endPosX = (500, 250)
  51. startPosY = (250, 0)
  52. endPosY = (250, 500)
  53. while running:
  54. for event in pygame.event.get():
  55. if event.type == pygame.QUIT:
  56. running = False
  57. screen.fill("white")
  58. for i in range(-200, 200):
  59. for j in range(-200, 200):
  60. number = Complex(i / 100, j / 100)
  61. if mandelbrotNumber(number):
  62. plotPoint((number.real*100) + 300, (number.imaginary*100) + 250)
  63. pygame.display.flip()
  64. pygame.quit()

字符串

esyap4oy

esyap4oy1#

如何优化代码以使其运行得更快
1.使用Python内置的复杂类型。
1.去掉四舍五入,那只是不必要的额外步骤。
1.放弃checkList,因为完全相等是不可能的,不值得付出努力。
1.与其为每个像素画一个圆,不如在内存中构建一个光栅图像(pygame文档建议称之为Surface),在其上设置像素,然后在一个绘制操作中将整个图像绘制到应用程序窗口。

x33g5p2x

x33g5p2x2#

1.优化计算

Python有一个内置的类complex,它应该更快,因为它是在C中内部实现的,但我猜你实现这个类是为了练习。
算法本身可以自行改进-请参阅@MvG列出的内容,但您可以做更多事情来提高速度-计算数字的平方根是一个相当慢的操作,x**2 + y**2 > 4将与sqrt(x**2 + y**2) > 2一样好,但会避免不必要的平方根。有更多的优化,让减少乘法的数量(比sqrt()的操作成本低,但仍然需要一点)。Wikipedia文章有一节专门介绍优化mandelbrot集绘制算法,请参阅此。
太慢了?有一些高级库可以帮助加速操作,numpy允许您“一次”对多个值进行操作,但在这里它不是很有用(没有简单的方法可以避免对已经转义的点进行不必要的操作)。更有用的库是numba-它是python子集的jit编译器,它让你编写代码的速度与编译语言相当。
如果你真的想给予一切来提高速度,那么应该使用第三方库来提高性能,但这绝对不是一个初学者友好的解决方案。

2.优化绘图

画圆-这是一个复杂的操作,最好使用类似surface.set_at()的东西来设置所选像素的颜色。
计算Mandelbrot分形每帧不是一个好主意,你可以有一个单独的表面,你可以画一次Mandelbrot集(当你在屏幕上画,你真的只是画在表面上是链接到窗口,你可以想象表面是一些虚拟的窗口,你看不见,但你可以在他们身上画,就像你通常在窗口上做的那样)
如果你真的想使用numba,使用任何与pygame表面相关的函数在numba will reduce the speed gained for usingnumba, to avoid this, edit values from an object received from` pygame.surfarray``优化的函数中绘制它们。

3.限制

总有一些限制,我上面列出的命题(即使没有关于使用numba的命题),你应该得到一个体面的程序来绘制mandelbrot集,但事实是,如果你缩放越来越多,计算所选点是否可能属于mandelbrot集就变得越来越繁重。
还有一个问题是你想花多少时间来优化这段代码。

展开查看全部

相关问题