def parse_factor(self):
token = self.tokens[self.position]
if token.isdigit():
self.position += 1
return NumberNode(int(token))
elif token.isalpha():
self.position += 1
return VariableNode(token)
elif token == '(':
self.position += 1
node = self.parse_expression()
if self.tokens[self.position] == ')':
self.position += 1
return node
else:
raise SyntaxError('Ожидалось ")"')
else:
raise SyntaxError(f'Неожиданный токен: {token}')
# Класс интерпретатора
class Interpreter:
def __init__(self):
self.context = {}
def execute(self, nodes):
for node in nodes:
node.evaluate(self.context)
# Пример кода на нашем мини-языке
code = """
x = 10
y = 20
result = x * y + (x - y) / 2
print result
"""
# Парсим и выполняем код
parser = Parser(code)
ast_nodes = parser.parse()
interpreter = Interpreter()
interpreter.execute(ast_nodes)
Описание кода:
1. Импортируем необходимые модули:
-
re для разбивки кода на токены.-
abc для создания абстрактных классов.2. Создаем абстрактный класс `ASTNode`:
- Определяет интерфейс для всех узлов синтаксического дерева.
- Метод
evaluate выполняет узел в заданном контексте переменных.3. Реализуем различные типы узлов:
-
NumberNode для числовых значений.-
VariableNode для переменных.-
BinaryOperationNode для бинарных операций (`+`, -, *, `/`).-
AssignmentNode для операций присваивания.-
PrintNode для вывода значений на экран.4. Создаем класс `Parser`:
- Инициализируется кодом и разбивает его на токены.
- Метод
parse анализирует код и строит список узлов AST.- Методы
parse_statement, parse_assignment, parse_expression, parse_term, parse_factor реализуют разбор различных частей кода.5. Создаем класс `Interpreter`:
- Содержит контекст переменных (`self.context`).
- Метод
execute выполняет список узлов AST.6. Пример кода на нашем мини-языке:
- Присваиваем значения переменным
x и y.- Вычисляем
result с использованием арифметических операций и скобок.- Выводим
result на экран.7. Парсим и выполняем код:
- Создаем экземпляр
Parser и парсим код, получая AST.- Создаем
Interpreter и выполняем AST.Как это работает:
- Парсинг кода:
- Код разбивается на токены (слова, числа, операторы).
- Парсер строит абстрактное синтаксическое дерево (AST), представляющее структуру кода.
- Выполнение кода:
- Интерпретатор проходит по узлам AST и выполняет их.
- Контекст переменных сохраняется в словаре
self.context.- При выполнении арифметических операций вычисляются значения с учетом текущего контекста.
- Пример выполнения:
-
x = 10 — переменной x присваивается значение 10.-
y = 20 — переменной y присваивается значение 20.-
result = x * y + (x - y) / 2 — вычисляется выражение и результат сохраняется в result.-
print result — выводится значение переменной result.Особенности ООП в коде:
- Инкапсуляция:
- Классы узлов AST скрывают детали реализации каждой операции.
- Контекст переменных хранится внутри интерпретатора.
- Наследование и полиморфизм:
- Все узлы AST наследуют от абстрактного класса
ASTNode.- Метод
evaluate переопределяется в каждом узле для специфического поведения.- Абстрактные классы и методы:
- Использование
ABC и @abstractmethod для определения интерфейса узлов.Как запустить код:
1. Убедитесь, что установлен Python 3.x.
2. Сохраните код в файле с расширением `.py`, например, `mini_interpreter.py`.
3. Запустите скрипт:
python mini_interpreter.py
Ожидаемый результат:
- На экране будет выведено число
190, которое является результатом вычисления выражения в переменной result.Возможные улучшения:
- Добавить поддержку дополнительных операторов и функций:
- Операторы сравнения (`==`,
- Логические операторы (`and`,
- Встроенные функции (например,
- Реализовать управление потоком исполнения:
- Условные операторы (`if`, `else`).
- Циклы (`while`, `for`).
- Добавить обработку ошибок и исключений:
- Улучшить сообщения об ошибках синтаксиса и выполнения.
- Оптимизировать парсер:
- Использовать более продвинутые техники парсинга (например, грамматики и генераторы парсеров).
Вывод:
Этот пример демонстрирует, как с помощью ООП можно реализовать интерпретатор простого языка программирования. Такой подход позволяет легко расширять функциональность языка, добавляя новые конструкции и возможности. Это отличное упражнение для понимания принципов парсинга, интерпретации и выполнения кода, а также для практики в использовании ООП в Python.
Подпишись 👉🏻 @KodduuPython 🤖
- Операторы сравнения (`==`,
!=, >, `<`).- Логические операторы (`and`,
or, `not`).- Встроенные функции (например,
sqrt, sin, `cos`).- Реализовать управление потоком исполнения:
- Условные операторы (`if`, `else`).
- Циклы (`while`, `for`).
- Добавить обработку ошибок и исключений:
- Улучшить сообщения об ошибках синтаксиса и выполнения.
- Оптимизировать парсер:
- Использовать более продвинутые техники парсинга (например, грамматики и генераторы парсеров).
Вывод:
Этот пример демонстрирует, как с помощью ООП можно реализовать интерпретатор простого языка программирования. Такой подход позволяет легко расширять функциональность языка, добавляя новые конструкции и возможности. Это отличное упражнение для понимания принципов парсинга, интерпретации и выполнения кода, а также для практики в использовании ООП в Python.
Подпишись 👉🏻 @KodduuPython 🤖
Давайте создадим сложную программу на Python без использования ООП. Мы реализуем алгоритм Быстрого преобразования Фурье (FFT) и применим его для анализа звукового сигнала. Также визуализируем результаты с помощью
Описание кода:
1. Импортируем необходимые модули:
-
-
-
-
2. Функция `read_wave`:
- Читает WAV-файл и возвращает сигнал и частоту дискретизации.
3. Функция `fft`:
- Рекурсивная реализация алгоритма Быстрого преобразования Фурье.
- Разделяет сигнал на четные и нечетные части и рекурсивно вычисляет их преобразования.
- Использует формулу "бабочки" для комбинирования результатов.
4. Основная часть программы:
- Проверяет наличие аргумента командной строки (имя файла).
- Читает звуковой сигнал из файла.
- Обрезает или дополняет сигнал до размера
- Выполняет FFT и получает спектр сигнала.
- Вычисляет частоты, соответствующие каждому значению спектра.
- Визуализирует исходный сигнал и его спектр.
5. Визуализация:
- Первая графика показывает сигнал во временной области.
- Вторая графика показывает амплитудный спектр сигнала в частотной области.
Как использовать:
1. Подготовьте WAV-файл:
- Убедитесь, что у вас есть звуковой файл в формате WAV для анализа.
2. Запустите скрипт:
- В командной строке выполните:
- Замените
3. Просмотрите результаты:
- Появится окно с двумя графиками, отображающими сигнал и его спектр.
Примечания:
- Размер выборки `N`:
- Выбранное значение
- Можно изменить
- Ограничения:
- Данная реализация FFT не оптимизирована и предназначена для образовательных целей.
- Для больших сигналов рекомендуется использовать
Подпишись 👉🏻 @KodduuPython 🤖
matplotlib.
import numpy as np
import matplotlib.pyplot as plt
import wave
import sys
# Чтение звукового файла
def read_wave(filename):
with wave.open(filename, 'r') as wf:
n_frames = wf.getnframes()
frames = wf.readframes(n_frames)
signal = np.frombuffer(frames, dtype=np.int16)
framerate = wf.getframerate()
return signal, framerate
# Реализация алгоритма FFT
def fft(signal):
N = len(signal)
if N <= 1:
return signal
even = fft(signal[::2])
odd = fft(signal[1::2])
T = [np.exp(-2j * np.pi * k / N) * odd[k % (N//2)] for k in range(N//2)]
return [even[k] + T[k] for k in range(N//2)] + \
[even[k] - T[k] for k in range(N//2)]
# Пример использования
if __name__ == "__main__":
# Проверка аргументов командной строки
if len(sys.argv) < 2:
print("Использование: python fft.py <filename.wav>")
sys.exit(1)
filename = sys.argv[1]
signal, framerate = read_wave(filename)
N = 1024 # Размер выборки
# Обрезаем или дополняем сигнал до нужного размера
if len(signal) < N:
signal = np.pad(signal, (0, N - len(signal)), 'constant')
else:
signal = signal[:N]
# Выполняем FFT
spectrum = fft(signal)
# Получаем частоты
freqs = np.fft.fftfreq(N, d=1/framerate)
# Визуализация
plt.figure(figsize=(12, 6))
plt.subplot(121)
plt.plot(np.arange(N), signal)
plt.title('Временная область')
plt.xlabel('Образцы')
plt.ylabel('Амплитуда')
plt.subplot(122)
plt.plot(freqs[:N//2], np.abs(spectrum[:N//2]) * 2 / N)
plt.title('Частотная область')
plt.xlabel('Частота (Гц)')
plt.ylabel('Амплитуда')
plt.tight_layout()
plt.show()
Описание кода:
1. Импортируем необходимые модули:
-
numpy для работы с массивами и математическими операциями.-
matplotlib.pyplot для визуализации.-
wave для работы с WAV-файлами.-
sys для доступа к аргументам командной строки.2. Функция `read_wave`:
- Читает WAV-файл и возвращает сигнал и частоту дискретизации.
3. Функция `fft`:
- Рекурсивная реализация алгоритма Быстрого преобразования Фурье.
- Разделяет сигнал на четные и нечетные части и рекурсивно вычисляет их преобразования.
- Использует формулу "бабочки" для комбинирования результатов.
4. Основная часть программы:
- Проверяет наличие аргумента командной строки (имя файла).
- Читает звуковой сигнал из файла.
- Обрезает или дополняет сигнал до размера
N (1024 образца).- Выполняет FFT и получает спектр сигнала.
- Вычисляет частоты, соответствующие каждому значению спектра.
- Визуализирует исходный сигнал и его спектр.
5. Визуализация:
- Первая графика показывает сигнал во временной области.
- Вторая графика показывает амплитудный спектр сигнала в частотной области.
Как использовать:
1. Подготовьте WAV-файл:
- Убедитесь, что у вас есть звуковой файл в формате WAV для анализа.
2. Запустите скрипт:
- В командной строке выполните:
python fft.py your_audio_file.wav
- Замените
your_audio_file.wav на имя вашего файла.3. Просмотрите результаты:
- Появится окно с двумя графиками, отображающими сигнал и его спектр.
Примечания:
- Размер выборки `N`:
- Выбранное значение
N = 1024 обеспечивает баланс между разрешением по времени и частоте.- Можно изменить
N в коде для анализа большего или меньшего фрагмента сигнала.- Ограничения:
- Данная реализация FFT не оптимизирована и предназначена для образовательных целей.
- Для больших сигналов рекомендуется использовать
numpy.fft.fft для производительности.Подпишись 👉🏻 @KodduuPython 🤖
🎉1
Собрали программу для тех кому некогда, но нужно быстро пройти весь Python + DataScience 👈👈👈
Подпишись 👉🏻 @KodduuPython 🤖
Подпишись 👉🏻 @KodduuPython 🤖
⚡4🔥1
Создадим интересную программу на Python, которая реализует генетический алгоритм для решения задачи оптимизации — нахождения минимума функции. Мы применим генетический алгоритм для минимизации функции Растригина, известной своей сложностью и множеством локальных минимумов.
Описание кода:
1. Функция Растригина (`rastrigin`): сложная функция с множеством локальных минимумов, часто используемая для тестирования алгоритмов оптимизации.
2. Параметры алгоритма:
-
-
-
-
3. Инициализация популяции: создаем начальную популяцию со случайными значениями в диапазоне [-5.12, 5.12].
4. Эволюционный цикл:
- Оценка приспособленности: вычисляем отрицательное значение функции Растригина для каждой особи (так как мы минимизируем функцию).
- Сохранение лучшего результата: отслеживаем наилучшее значение функции в каждом поколении.
- Селекция: выбираем лучших особей (с наилучшей приспособленностью) для создания потомства.
- Кроссовер: комбинируем гены пар родителей для создания новых особей.
- Мутация: вносим случайные изменения в гены потомков с определенной вероятностью.
- Обновление популяции: формируем новую популяцию из родителей и потомков.
5. Вывод результатов:
- Находим и выводим лучшую особь после всех поколений.
- Выводим соответствующее значение функции Растригина.
- Строим график сходимости значений функции по поколениям.
Как запустить код:
1. Установите необходимые библиотеки:
2. Сохраните код в файл, например `genetic_algorithm.py`.
3. Запустите скрипт:
Ожидаемый результат:
- В консоли отобразится лучшее найденное решение и значение функции в этой точке.
- Откроется график, показывающий, как значение функции менялось по мере эволюции поколений.
Примечания:
import numpy as np
import matplotlib.pyplot as plt
# Определение функции Растригина
def rastrigin(x):
A = 10
return A * len(x) + sum([(xi**2 - A * np.cos(2 * np.pi * xi)) for xi in x])
# Параметры генетического алгоритма
POP_SIZE = 100 # Размер популяции
GENES = 2 # Количество генов (размерность задачи)
GENERATIONS = 50 # Количество поколений
MUTATION_RATE = 0.1 # Вероятность мутации
# Инициализация популяции
population = [np.random.uniform(-5.12, 5.12, GENES) for _ in range(POP_SIZE)]
# Эволюционный цикл
best_scores = []
for generation in range(GENERATIONS):
# Оценка приспособленности
fitness = [ -rastrigin(individual) for individual in population]
# Сохранение лучшего результата
best_scores.append(-min(fitness))
# Селекция
parents = [population[i] for i in np.argsort(fitness)[-POP_SIZE//2:]]
# Кроссовер
offspring = []
for _ in range(POP_SIZE//2):
parent1, parent2 = np.random.choice(parents, 2, replace=False)
crossover_point = np.random.randint(1, GENES)
child = np.concatenate([parent1[:crossover_point], parent2[crossover_point:]])
offspring.append(child)
# Мутация
for individual in offspring:
if np.random.rand() < MUTATION_RATE:
mutation_point = np.random.randint(GENES)
individual[mutation_point] += np.random.uniform(-1, 1)
individual[mutation_point] = np.clip(individual[mutation_point], -5.12, 5.12)
# Обновление популяции
population = parents + offspring
# Вывод результатов
best_individual = population[np.argmax(fitness)]
print("Лучшее решение:", best_individual)
print("Значение функции:", rastrigin(best_individual))
# Визуализация сходимости
plt.plot(best_scores)
plt.title('Сходимость генетического алгоритма')
plt.xlabel('Поколение')
plt.ylabel('Значение функции')
plt.show()
Описание кода:
1. Функция Растригина (`rastrigin`): сложная функция с множеством локальных минимумов, часто используемая для тестирования алгоритмов оптимизации.
2. Параметры алгоритма:
-
POP_SIZE: количество особей в популяции.-
GENES: количество генов в хромосоме (размерность задачи).-
GENERATIONS: количество поколений для эволюции.-
MUTATION_RATE: вероятность мутации потомка.3. Инициализация популяции: создаем начальную популяцию со случайными значениями в диапазоне [-5.12, 5.12].
4. Эволюционный цикл:
- Оценка приспособленности: вычисляем отрицательное значение функции Растригина для каждой особи (так как мы минимизируем функцию).
- Сохранение лучшего результата: отслеживаем наилучшее значение функции в каждом поколении.
- Селекция: выбираем лучших особей (с наилучшей приспособленностью) для создания потомства.
- Кроссовер: комбинируем гены пар родителей для создания новых особей.
- Мутация: вносим случайные изменения в гены потомков с определенной вероятностью.
- Обновление популяции: формируем новую популяцию из родителей и потомков.
5. Вывод результатов:
- Находим и выводим лучшую особь после всех поколений.
- Выводим соответствующее значение функции Растригина.
- Строим график сходимости значений функции по поколениям.
Как запустить код:
1. Установите необходимые библиотеки:
pip install numpy matplotlib
2. Сохраните код в файл, например `genetic_algorithm.py`.
3. Запустите скрипт:
python genetic_algorithm.py
Ожидаемый результат:
- В консоли отобразится лучшее найденное решение и значение функции в этой точке.
- Откроется график, показывающий, как значение функции менялось по мере эволюции поколений.
Примечания:
⚡2
- Эксперименты с параметрами: Попробуйте изменить параметры алгоритма (размер популяции, количество поколений, вероятность мутации), чтобы увидеть, как они влияют на результат и скорость сходимости.
- Расширение на большую размерность: Вы можете увеличить
Заключение:
Этот пример демонстрирует применение генетических алгоритмов для решения задач оптимизации сложных функций. Генетические алгоритмы имитируют процессы естественного отбора и генетической мутации, позволяя находить приближенные решения в задачах, где аналитическое решение затруднительно.
Подпишись 👉🏻 @KodduuPython 🤖
- Расширение на большую размерность: Вы можете увеличить
GENES для решения задачи в пространстве большей размерности, что сделает задачу более сложной.Заключение:
Этот пример демонстрирует применение генетических алгоритмов для решения задач оптимизации сложных функций. Генетические алгоритмы имитируют процессы естественного отбора и генетической мутации, позволяя находить приближенные решения в задачах, где аналитическое решение затруднительно.
Подпишись 👉🏻 @KodduuPython 🤖
🔥2
Вот код, который создает интерактивную визуализацию, где точки движутся, образуя различные узоры. Этот код создает окно с анимацией точек, которые перемещаются по кругу и создают интересные узоры. К тому же, это легко настраивается для других геометрических форм.
Этот код:
- Создает 50 точек, которые расположены по кругу.
- С каждой итерацией они слегка смещаются, создавая эффект "волны" и "размытости".
- Получается гипнотическая анимация, которую можно менять, изменяя радиус, количество точек или скорость.
Подпишись 👉🏻 @KodduuPython 🤖
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# Настройка параметров
num_points = 50
radius = 10
# Создаем исходные координаты точек на окружности
angles = np.linspace(0, 2 * np.pi, num_points, endpoint=False)
x_coords = radius * np.cos(angles)
y_coords = radius * np.sin(angles)
fig, ax = plt.subplots()
ax.set_aspect('equal', 'box')
scatter = ax.scatter(x_coords, y_coords, s=50, color='blue')
ax.set_xlim(-radius * 1.2, radius * 1.2)
ax.set_ylim(-radius * 1.2, radius * 1.2)
def update(frame):
# Обновление углов и координат для движения точек
new_angles = angles + 0.1 * frame
x_coords = radius * np.cos(new_angles + frame * 0.01)
y_coords = radius * np.sin(new_angles + frame * 0.01)
scatter.set_offsets(np.c_[x_coords, y_coords])
return scatter,
ani = animation.FuncAnimation(fig, update, frames=200, interval=50, blit=True)
plt.show()
Этот код:
- Создает 50 точек, которые расположены по кругу.
- С каждой итерацией они слегка смещаются, создавая эффект "волны" и "размытости".
- Получается гипнотическая анимация, которую можно менять, изменяя радиус, количество точек или скорость.
Подпишись 👉🏻 @KodduuPython 🤖
Попробуем создать более сложную анимацию, в которой точки будут двигаться по нелинейным траекториям, создавая узоры. Этот пример использует траектории, которые зависят от синусоидальных и косинусоидальных функций с переменным радиусом, чтобы добавить нелинейные колебания.
### Как это работает:
- Радиус каждой точки зависит от времени и изменяется по синусоиде, что делает движение точек более динамичным.
- Траектория движения каждой точки - это комбинация нескольких синусоидальных и косинусоидальных функций, что создает уникальные узоры на каждом кадре.
- Частотные множители для
Подпишись 👉🏻 @KodduuPython 🤖
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# Настройка параметров
num_points = 50
base_radius = 10
# Создаем исходные углы для точек
angles = np.linspace(0, 2 * np.pi, num_points, endpoint=False)
fig, ax = plt.subplots()
ax.set_aspect('equal', 'box')
scatter = ax.scatter([], [], s=50, color='purple')
ax.set_xlim(-base_radius * 1.5, base_radius * 1.5)
ax.set_ylim(-base_radius * 1.5, base_radius * 1.5)
# Обновление координат для нелинейных траекторий
def update(frame):
# Нелинейный радиус с добавлением синусоидальной амплитуды
radius = base_radius + 3 * np.sin(frame * 0.05)
x_coords = radius * np.cos(angles + 0.05 * frame) + 2 * np.sin(angles * 3 + frame * 0.1)
y_coords = radius * np.sin(angles + 0.05 * frame) + 2 * np.cos(angles * 4 + frame * 0.1)
scatter.set_offsets(np.c_[x_coords, y_coords])
return scatter,
# Настройка анимации
ani = animation.FuncAnimation(fig, update, frames=400, interval=50, blit=True)
plt.show()
### Как это работает:
- Радиус каждой точки зависит от времени и изменяется по синусоиде, что делает движение точек более динамичным.
- Траектория движения каждой точки - это комбинация нескольких синусоидальных и косинусоидальных функций, что создает уникальные узоры на каждом кадре.
- Частотные множители для
angles (например, 3 и 4 внутри x_coords и `y_coords`) добавляют колебания по окружности, что создает сложные, закрученные траектории.Подпишись 👉🏻 @KodduuPython 🤖
Собрали программу Junior FullStack Developer and Data Scientist, включает 3 наших самых компактных курса, можно пройти за 2-3 викэнда. В программе вся база по Python + вся база по JavaScript + вся база по Data Science в Python 😎
Подпишись 👉🏻 @KodduuPython 🤖
Подпишись 👉🏻 @KodduuPython 🤖
Как насчёт кода, который рисует фрактал *Множества Мандельброта* и анимирует его приближение? Это отличный пример красоты и сложности фрактальной геометрии! И демо того как оно может тормозить на большом кол-во объектов 🐌 В следующем посте расскажем как ускорить ⚡️
Вот код для визуализации этого фрактала с постепенным "увеличением" на определённой области:
### Объяснение кода:
- Множество Мандельброта создаётся путём проверки, стремятся ли точки в комплексной плоскости к бесконечности при итерациях по формуле \( z = z^2 + c \).
- Функция `generate_mandelbrot` вычисляет фрактал для заданных границ и преобразует его в массив значений.
- Анимация `update` постепенно уменьшает масштаб (приближает) вокруг интересной точки, что позволяет видеть больше деталей.
Подпишись 👉🏻 @KodduuPython 🤖
Вот код для визуализации этого фрактала с постепенным "увеличением" на определённой области:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# Настройка параметров фрактала
width, height = 800, 800 # Размер окна
max_iter = 256 # Максимальное количество итераций
# Начальные координаты для анимации (центр Мандельброта)
xmin, xmax, ymin, ymax = -2.0, 1.0, -1.5, 1.5
# Функция для вычисления множества Мандельброта
def mandelbrot(c, max_iter):
z = c
for n in range(max_iter):
if abs(z) > 2:
return n
z = z*z + c
return max_iter
# Функция, которая генерирует фрактал
def generate_mandelbrot(xmin, xmax, ymin, ymax, width, height, max_iter):
x, y = np.linspace(xmin, xmax, width), np.linspace(ymin, ymax, height)
C = x + y[:, None] * 1j
mandelbrot_set = np.frompyfunc(lambda c: mandelbrot(c, max_iter), 1, 1)(C).astype(np.float32)
return mandelbrot_set
# Создаем фигуру и ось для анимации
fig, ax = plt.subplots(figsize=(6, 6))
im = ax.imshow(generate_mandelbrot(xmin, xmax, ymin, ymax, width, height, max_iter),
extent=(xmin, xmax, ymin, ymax), cmap='hot', origin='lower')
# Функция обновления для анимации
def update(frame):
zoom_factor = 1.5 ** (-frame * 0.1)
x_center, y_center = -0.7435, 0.1314 # координаты интересной точки
dx, dy = (xmax - xmin) * zoom_factor, (ymax - ymin) * zoom_factor
xmin_new, xmax_new = x_center - dx / 2, x_center + dx / 2
ymin_new, ymax_new = y_center - dy / 2, y_center + dy / 2
mandelbrot_set = generate_mandelbrot(xmin_new, xmax_new, ymin_new, ymax_new, width, height, max_iter)
im.set_data(mandelbrot_set)
im.set_extent((xmin_new, xmax_new, ymin_new, ymax_new))
return im,
# Анимация фрактала
ani = animation.FuncAnimation(fig, update, frames=100, interval=50, blit=True)
plt.show()
### Объяснение кода:
- Множество Мандельброта создаётся путём проверки, стремятся ли точки в комплексной плоскости к бесконечности при итерациях по формуле \( z = z^2 + c \).
- Функция `generate_mandelbrot` вычисляет фрактал для заданных границ и преобразует его в массив значений.
- Анимация `update` постепенно уменьшает масштаб (приближает) вокруг интересной точки, что позволяет видеть больше деталей.
Подпишись 👉🏻 @KodduuPython 🤖
Для ускорения анимации Множества Мандельброта можно воспользоваться несколькими подходами:
1. Уменьшить разрешение (размер
2. Оптимизировать функцию `mandelbrot` с использованием Numba для компиляции в машинный код, что значительно ускоряет обработку.
3. Параллельные вычисления для обработки точек массива.
Давайте применим Numba и создадим ускоренную версию. Для этого сначала нужно установить
Затем добавим
### Изменения в коде:
- Numba (`@njit`) значительно ускоряет функции
- Уменьшение `width` и `height` до 600x600 пикселей снижает нагрузку на процессор.
Эти изменения помогут повысить производительность, делая анимацию более плавной и быстрой.
Подпишись 👉🏻 @KodduuPython 🤖
1. Уменьшить разрешение (размер
width и `height`), чтобы уменьшить количество вычисляемых точек.2. Оптимизировать функцию `mandelbrot` с использованием Numba для компиляции в машинный код, что значительно ускоряет обработку.
3. Параллельные вычисления для обработки точек массива.
Давайте применим Numba и создадим ускоренную версию. Для этого сначала нужно установить
numba, если она не установлена:
pip install numba
Затем добавим
@njit из Numba, чтобы ускорить расчёты:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from numba import njit
# Настройка параметров фрактала
width, height = 600, 600 # Уменьшили размер для повышения скорости
max_iter = 256 # Максимальное количество итераций
# Компилируем функцию с помощью Numba
@njit
def mandelbrot(c, max_iter):
z = c
for n in range(max_iter):
if abs(z) > 2:
return n
z = z * z + c
return max_iter
@njit
def generate_mandelbrot(xmin, xmax, ymin, ymax, width, height, max_iter):
x = np.linspace(xmin, xmax, width)
y = np.linspace(ymin, ymax, height)
mandelbrot_set = np.empty((height, width), dtype=np.float32)
for i in range(width):
for j in range(height):
mandelbrot_set[j, i] = mandelbrot(x[i] + 1j * y[j], max_iter)
return mandelbrot_set
# Создаем фигуру и ось для анимации
fig, ax = plt.subplots(figsize=(6, 6))
im = ax.imshow(generate_mandelbrot(-2.0, 1.0, -1.5, 1.5, width, height, max_iter),
extent=(-2.0, 1.0, -1.5, 1.5), cmap='hot', origin='lower')
# Функция обновления для анимации
def update(frame):
zoom_factor = 1.5 ** (-frame * 0.1)
x_center, y_center = -0.7435, 0.1314 # координаты интересной точки
dx, dy = (1.0 - -2.0) * zoom_factor, (1.5 - -1.5) * zoom_factor
xmin_new, xmax_new = x_center - dx / 2, x_center + dx / 2
ymin_new, ymax_new = y_center - dy / 2, y_center + dy / 2
mandelbrot_set = generate_mandelbrot(xmin_new, xmax_new, ymin_new, ymax_new, width, height, max_iter)
im.set_data(mandelbrot_set)
im.set_extent((xmin_new, xmax_new, ymin_new, ymax_new))
return im,
# Анимация фрактала
ani = animation.FuncAnimation(fig, update, frames=100, interval=50, blit=True)
plt.show()
### Изменения в коде:
- Numba (`@njit`) значительно ускоряет функции
mandelbrot и generate_mandelbrot за счёт компиляции в машинный код.- Уменьшение `width` и `height` до 600x600 пикселей снижает нагрузку на процессор.
Эти изменения помогут повысить производительность, делая анимацию более плавной и быстрой.
Подпишись 👉🏻 @KodduuPython 🤖