Я делаю алгоритм имитации отжига для оптимизации заданного распределения студентов и проектов.
Это не зависящий от языка псевдокод из Википедии:
s ← s0; e ← E(s) // Initial state, energy.
sbest ← s; ebest ← e // Initial "best" solution
k ← 0 // Energy evaluation count.
while k < kmax and e > emax // While time left & not good enough:
snew ← neighbour(s) // Pick some neighbour.
enew ← E(snew) // Compute its energy.
if enew < ebest then // Is this a new best?
sbest ← snew; ebest ← enew // Save 'new neighbour' to 'best found'.
if P(e, enew, temp(k/kmax)) > random() then // Should we move to it?
s ← snew; e ← enew // Yes, change state.
k ← k + 1 // One more evaluation done
return sbest // Return the best solution found.
Ниже приводится адаптация техники. Мой руководитель сказал, что идея в теории прекрасна.
Сначала я выбираю некоторое распределение (т. Е. Полный словарь студентов и их распределенных проектов, включая ранги проектов) из всего набора рандомизированных распределений, копирую его и передаю его моей функции. Назовем это распределение aOld
(это словарь). aOld
имеет связанный с ним вес, который называется wOld
. Взвешивание описано ниже.
Функция выполняет следующие действия:
- Пусть это распределение,
aOld
будет best_node
- Из всех студентов выберите случайное количество студентов и вставьте в список
- Убрать (DEALLOCATE) их из своих проектов ++ отразить изменения для проектов (
allocated
параметр теперь False
) и лекторов (освободить слоты, если один или несколько их проектов больше не выделены)
- Случайный выбор этого списка
- Попробуйте назначить (REALLOCATE) всех в этом списке проектов снова
- Рассчитать вес (сложить ранги, ранг 1 = 1, ранг 2 = 2 ... и без рейтинга проекта = 101)
- Для этого нового распределения
aNew
, если вес wNew
меньше веса распределения wOld
, который я выбрал в начале, то это best_node
(как определено алгоритмом Simulated Annealing
выше ). Примените алгоритм к aNew
и продолжайте.
- Если
wOld < wNew
, применить алгоритм к aOld
снова и продолжить.
Распределения / точки данных выражаются в виде «узлов», так что node = (weight, allocation_dict, projects_dict, lecturers_dict)
Прямо сейчас я могу выполнить этот алгоритм только один раз, но мне нужно будет попытаться найти число N (обозначено kmax
в фрагменте Википедии) и убедиться, что у меня всегда есть предыдущий node
и best_node
.
Чтобы я не изменял свои исходные словари (которые я мог бы сбросить), я сделал мелкую копию словарей. Из того, что я прочитал в документации, кажется, что он только копирует ссылки, и, поскольку мои словари содержат объекты, изменение скопированного словаря в конечном итоге приводит к изменению объектов в любом случае. Поэтому я попытался использовать copy.deepcopy()
. Эти словари ссылаются на объекты, которые были сопоставлены с SQLA.
Questions:
Мне были даны некоторые решения для проблем, с которыми я столкнулся, но из-за моей исключительной зелёности при использовании Python все они звучат довольно загадочно для меня.
Deepcopy не очень хорошо работает с SQLA. Мне сказали, что у глубокой копии на объектах ORM, вероятно, есть проблемы, которые мешают ей работать так, как вы ожидаете. По-видимому, лучше было бы «создавать конструкторы копий, то есть def copy (self): return FooBar (....)». Может кто-нибудь объяснить, что это значит?
Я проверил и обнаружил, что deepcopy
имеет проблемы, потому что SQLAlchemy помещает дополнительную информацию в ваши объекты, то есть атрибут _sa_instance_state
, который я не хотел бы видеть в копии, но необходим для того, чтобы объект имел , Мне сказали: «Есть способы вручную сдуть старый _sa_instance_state
и наложить новый на объект, но самым простым является создание нового объекта с __init__()
и настройка значимых атрибутов. вместо того, чтобы делать полную глубокую копию. " Что именно это значит? Создать новый не сопоставленный класс, похожий на старый, сопоставленный класс?
Альтернативное решение состоит в том, что мне придется «реализовать __deepcopy__()
на ваших объектах и убедиться, что настроено новое _sa_instance_state, в sqlalchemy.orm.attributes есть функции, которые могут помочь с этим». Еще раз, это за мной, поэтому кто-то может объяснить, что это значит?
Более общий вопрос: учитывая приведенную выше информацию, есть ли какие-либо предложения о том, как я могу поддерживать информацию / состояние для best_node
(который всегда должен сохраняться в моем цикле while) и previous_node
, если мой фактические объекты (на которые ссылаются словари, следовательно, узлы) изменяются из-за того, что происходит освобождение / перераспределение? То есть без использования копии?