【发布时间】:2011-02-27 13:35:33
【问题描述】:
我正在使用模拟退火算法来优化给定的学生和项目分配。
这是来自维基百科的与语言无关的伪代码:
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(在维基百科 sn-p 中由 kmax 表示)并确保我始终拥有前一个 @ 987654339@ 和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的信息/状态的建议,如果我的实际对象(由字典引用,因此是节点)由于发生释放/重新分配而发生变化?也就是不使用copy?
【问题讨论】:
标签: python sqlalchemy deep-copy simulated-annealing