1

I have used 2 for loops to check if the points are within the set, but apparently it takes too much time, giving less details on the plot itself. How can I optimise the code to run faster, and thus add more detail to the plot ? The pygame origin is at the top left corner, so I manually set each point relative to the centre.

import math
import pygame


class Point:
    def __init__(self, x, y):
        self.x = x - 250
        self.y = y - 250


class Complex:
    def __init__(self, real, imaginary):
        self.real = real
        self.imaginary = imaginary

    def __eq__(self, other):
        if self.real == other.real:
            if self.imaginary == other.imaginary:
                return True
        return False

    def __abs__(self):
        return math.sqrt(self.real ** 2 + self.imaginary ** 2)

    def __round__(self, n=None):
        return Complex(round(self.real, 4), round(self.imaginary, 4))

    def __add__(self, other):
        return Complex(self.real + other.real, self.imaginary + other.imaginary)

    def __sub__(self, other):
        return Complex(self.real - other.real, self.imaginary - other.imaginary)

    def __mul__(self, other):
        return Complex((self.real * other.real) - (self.imaginary * other.imaginary),
                       (self.real * other.imaginary) + (self.imaginary * other.real))


def zheta(z, c):
    return round((z * z) + c, 3)


def mandelbrotNumber(num):
    z0 = Complex(0, 0)
    c = num
    checkList = [Complex(0, 0)]
    for i in range(10):
        z = zheta(z0, c)
        if abs(z) > 2:
            return False
        if z in checkList:
            return True
        checkList.append(z)
        z0 = z
    return True


def plotPoint(x, y):
    color = (0, 0, 0)
    position = (x, y)
    pygame.draw.circle(screen, color, position, 2)

pygame.init()
screen = pygame.display.set_mode((500, 500))
running = True
startPosX = (0, 250)
endPosX = (500, 250)
startPosY = (250, 0)
endPosY = (250, 500)

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    screen.fill("white")
    for i in range(-200, 200):
        for j in range(-200, 200):
            number = Complex(i / 100, j / 100)
            if mandelbrotNumber(number):
                plotPoint((number.real*100) + 300, (number.imaginary*100) + 250)

    pygame.display.flip()
pygame.quit()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
astle dsa
  • 11
  • 3
  • First step: don't use an interpreted language. The basic Mandelbrot set calculation needs to use the fastest coding methods available; not to mention an efficient algorithm. – Weather Vane Aug 10 '23 at 19:19
  • `for i in range(10):` you seem only to iterate to a very shallow depth. That will give a rudimentary Mandelbrot set. Not my DV. – Weather Vane Aug 10 '23 at 19:41
  • Thank you very much. I chose python just for practice, but I would like to hear alternate suggestions too. – astle dsa Aug 11 '23 at 04:13

1 Answers1

0

How can I optimise the code to run faster

  1. Use the complex type built into Python.
  2. Drop the rounding, that's just unnecessary extra steps.
  3. Drop the checkList since exact equality is very unlikely and not worth the effort.
  4. Instead of drawing a circle for each pixel, construct a raster image in memory (pygame docs suggest this is called a Surface), set pixels on that then draw that whole image to your application windowin a single drawing operation.
MvG
  • 57,380
  • 22
  • 148
  • 276