Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored core #70

Merged
merged 73 commits into from
Nov 24, 2023
Merged

Refactored core #70

merged 73 commits into from
Nov 24, 2023

Conversation

MangaBoba
Copy link
Collaborator

@MangaBoba MangaBoba commented Nov 13, 2023

New features:

  • Experiments configuration with single file.
  • Configuration classes are pydantic models with native serialization, deserialization and validation.
  • Geometry type can be set to convex and non convex.
  • Convex-safe and self-intersection-safe mutations. (Significantly reduced postprocessing corrections).
  • Polygon-level crossover.
  • Joblib backend for parallel operations execution.
  • Fast and accurate default polygons generation taking into account the geometry type. Based on polygenerator.
  • GOLEM optimization features support
    • Surrogate and GPComp optimizers
    • Adaptive mutations, genetic schemes, etc.
    • Tuners
  • Modular framework structure simplifies code base extension.
  • Code auto formatting and linting configuration (locally and git action).
  • SPEA2 and MOEAD can be set as selectors for multi objective tasks. Tournament and roulette selectors can be set for SPEA2 and MOEAD fitnesses.
  • Sensitivity analysis (SA old core #71)

Minor changes:

  • Objective evaluates only if structure changed.
  • Simple mp4 visualization of population.
  • Migrated to the new core cases:
    • single and multi objective synthetic circle,
    • COMSOL microfluidic,
    • sound waves pressure,
    • SWAN breakwaters.
  • Population can be easily serialized and deserialized from json.
  • Upd docs API Reference, quickstart guide, tutorials.

zsurrogate.py Outdated Show resolved Hide resolved
Comment on lines 48 to 66
border = shape(border_dict['features'][0]['geometry'])
water = [i for i in res_list['features'] if i['properties']['type'] =='water']
water_coord =[p['geometry']['coordinates'] for p in water]
cargo_piers = [i for i in res_list['features'] if i['properties']['type'] =='cargo_pier']
passenger_pier = [i for i in res_list['features'] if i['properties']['type'] =='passenger_pier']
piers = [i for i in res_list['features'] if (i['properties']['type']=='passenger_pier') or (i['properties']['type'] =='cargo_pier')]
piers_coords = [x[0] for x in [i['geometry']['coordinates'] for i in piers]]
piers_line = [max(p,key=lambda i: i[1]) for p in piers_coords]
unique_types = np.unique([i['properties']['type'] for i in res_list['features']])
allow_water = [i for i in water_coord[0][0] if (i[0]>74.8) and (i[1]<67.942) and (i[1]>67.915)]
###########
allow_area = [[74.80,67.92],[74.80,67.94]]+allow_water +[[74.80,67.92]]
grid_resolution_x = 17 # Number of points on x-axis
grid_resolution_y = 31 # Number of points on y-axis
coord_Y = np.linspace(min([p[1] for p in allow_area])*500, max([p[1] for p in allow_area])*500, grid_resolution_y + 1) # X coordinate for spatial grid
coord_X = np.linspace(min([p[0] for p in allow_area])*500, max([p[0] for p in allow_area])*500, grid_resolution_x + 1)
grid = [grid_resolution_x, grid_resolution_y] # points grid
fixed_area = None
targets = [[14,10],[16,10],[18,10]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут напрашивается заварачивание в какую-то функцию, парсящую geojson

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут напрашивается заварачивание в какую-то функцию, парсящую geojson

Завернул в функцию. Теперь этот main находится в cases/breakwaters/arctic_config/acrtic_config.py.
А функция находится cases/breakwaters/utils.

from loguru import logger


class BaseParallelDispatcher:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А это из GOLEM-а не взять?

Copy link
Collaborator Author

@MangaBoba MangaBoba Nov 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В GOLEM есть класс для параллельных вычислений, но он предназначен только для objective. Тогда как прочие операции вычисляются не параллельно, мутации например.

BaseParallelDispatcher же является утилитой "общего назначения", то есть ее можно применить почти к любой функции. Что собственно и реализовано в CrossoverStrategy и MutationStrategy. Отсюда следует очевидное преимущество в скорости вычислений. На примере multi objective синтетик кейса с кружками: вычисления занимают для GOLEM ≈54 секунды, для GEFEST ≈12 секунд.

Следующий момент - параллельное вычисление objective с физ. симулятором. В большинстве случаев на уровне кода библиотеки это оказывается бессмысленно или даже деструктивно. В частности, COMSOL и SWAN умеют использовать параллельные вычисления и сами, таким образом если сделать это еще и в коде, то не будет никакого прироста производительности. Клеточный симулятор звуковых волн же плохо поддается распараллеливанию в принципе, поскольку он хранит состояние и вычисляется итеративно. Таким образом как есть он не заработает параллельно, а если его подать в GOLEM оптимизатор и задать более 1 ядра, то вычисления и вовсе упадут.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тогда как прочие операции вычисляются не параллельно, мутации [например]
(https://github.com/aimclub/GOLEM/blob/main/golem/core/optimisers/genetic/operators/mutation.py#L84C69-L84C113).

А вот этот - не то что нужно aimclub/GOLEM#199? Пока ещё не в мастере.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Эта штука явно сделает вычисления GOELM быстрее, но ей будет сложно и менее эффективно заменить BaseParallelDispatcher.
Для начала предлагаемый в aimclub/GOLEM#199 ReproduceWorker это параллелизм на уровне всего пайплайна репродукции, что на мой взгляд ограничивает гибкость и возможность расширения, и возможно будет работать медленнее чем параллелизм на уровне операций/функций.
Далее, одна из основных проблем совместимости GEFEST и GOLEM кроется в постпроцессинге, для которого в пайплайне оптимизации GOLEM нет отдельного шага, поэтому приходится прицеплять его к операциям мутации, кроссовера, и т.д. Теряется опция, например, не запускать постпроцессинг, если полученный индивид уже валиден, или удалось его исправить за меньшее число попыток, чем максимальное. В каждом случае параллельный запуск будет ждать самого долгого воркера. Замечу, что это пожалуй в значительной степени компенсируется за счет того, что сейчас в принципе редко порождаются невалидные индивиды, однако не факт что не появится такой кейс в будущем.
Ну и что касается интеграции ReproduceWorker в GEFEST, то речь пойдет именно об интеграции целиком шага репродукции, что имеет мало смысла, поскольку это тащит за собой все описанные выше недостатки, а так же требует по сути дублировать логику, реализованную в том же EvoGraphOptimizer.

Если рассмотреть проблему интеграции с GOLEM с точки зрения реализации новых алгоритмов, то если я правильно понимаю, их ключевую логику можно вынести в оператор селекции (речь про moead, nsga2, nsga3 и пр.), как это сделано в GOLEM для spea2. Тогда имеет смысл создать feature request на возможность добавлять пользовательские селекторы и просто реализовать нужные операции в GEFEST. Ну или даже контрибутить их сразу в GOLEM.

Таким образом полностью переехать на GOLEM в качестве бекенда эволюционной оптимизации мешает:

  • Скорость вычислений
  • Отсутствие постпроцессинга в пайплайне (сейчас решено последовательными вызовами)
  • Невозможность добавить пользовательские функции селекции
    Возможно что-то забыл, но это ключевые пункты.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ок.

Пока тогда пусть остается так, но создай в GOLEM-е issue по тому, чего не хватает.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сейчас в aimclub/GOLEM#199 реализован параллелизм на уровне операций.
Также планируется в этот же PR добавить функционал, который позволит составить свою схему подготовки поколения из любых операций, которые будут применяться параллельно в любом порядке и любое количество раз.
Плюсом к тому, решены некоторые важные для голема проблемы с распараллеливанием операций.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сейчас в aimclub/GOLEM#199 реализован параллелизм на уровне операций.

Не нашел в aimclub/GOLEM@main...parallel-population-processing параллельных вызовов кроме как в кроссовере и в репродукции, для ReproduceWorker, который объединяет собственно все шаги репродукции. Поправьте, если я что-то пропустил.

Также планируется в этот же PR добавить функционал, который позволит составить свою схему подготовки поколения из любых операций, которые будут применяться параллельно в любом порядке и любое количество раз.

Звучит круто. Интерфейсы этой утилиты будут привязаны к интерфейсам GOLEM? Можно будет применить ее для параллельного выполнения кастомных операций на кастомных типах данных?

Небольшое пожелание по конфигурированию: очень хотелось бы иметь возможность раздельно выбрать число потоков, хотя бы для вычисления обжективов и всего остального.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не нашел в aimclub/GOLEM@main...parallel-population-processing параллельных вызовов

Сделано за один вызов.

Интерфейсы этой утилиты будут привязаны к интерфейсам GOLEM?

Да.

Можно будет применить ее для параллельного выполнения кастомных операций на кастомных типах данных?

Да.

возможность раздельно выбрать число потоков, хотя бы для вычисления обжективов и всего остального.

Если нужно последовательно выполнить несколько операций в многопоток, а потом одну в однопоток - это можно.

@MangaBoba MangaBoba merged commit c36d5af into main Nov 24, 2023
5 checks passed
@MangaBoba
Copy link
Collaborator Author

#71

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants