<p>我正在做一个模拟退火算法来优化给定的学生和项目分配。在</p>
<p>这是来自维基百科的语言无关的伪代码:</p>
<pre><code>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.
</code></pre>
<p>以下是对该技术的改编。我的主管说理论上这个主意不错。在</p>
<p>首先,我从整个随机分配集合中获取一些分配(即学生及其分配项目的整个字典,包括项目的排名),复制并传递给我的函数。让我们把这个分配称为<code>aOld</code>(它是一个字典)。<code>aOld</code>有一个与之相关的权重,称为<code>wOld</code>。权重如下所述。在</p>
<p>该函数执行以下操作:</p>
<ul>
<li>让这个分配,<code>aOld</code>就是<code>best_node</code></li>
<li>从所有的学生中,随机抽取几个学生,然后把它们列在一个列表中</li>
<li>剥离(释放)他们的项目++反映项目(<code>allocated</code>参数现在是<code>False</code>)和讲师(如果他们的一个或多个项目不再分配,则释放插槽)</li>
<li>把名单随机化</li>
<li>再次尝试分配(重新分配)该列表项目中的所有人</li>
<li>计算权重(将等级相加,等级1=1,等级2=2。。。无项目等级=101)</li>
<li>对于这个新的分配<code>aNew</code>,如果权重<code>wNew</code>小于我在开始时选择的分配权重<code>wOld</code>,那么这就是<code>best_node</code>(由上面的<code>Simulated Annealing</code>算法定义)。将算法应用于<code>aNew</code>,然后继续。在</li>
<li>如果<code>wOld < wNew</code>,则将该算法再次应用于<code>aOld</code>,然后继续。在</li>
</ul>
<p>分配/数据点表示为“节点”,这样<code>node = (weight, allocation_dict, projects_dict, lecturers_dict)</code></p>
<p>现在,我只能执行这个算法一次,但是我需要尝试一个数字N(在Wikipedia代码片段中用<code>kmax</code>表示),并确保我总是随身携带上一个<code>node</code>和{<cd5>}。在</p>
<p>为了不修改我原来的字典(我可能想重新设置),我对字典做了一个浅拷贝。从我在文档中读到的内容来看,它似乎只复制了引用,而且由于我的词典包含对象,所以无论如何,更改复制的词典最终都会更改对象。所以我尝试使用<code>copy.deepcopy()</code>,这些字典引用的是用SQLA映射的对象。在</p>
<hr/>
<p><code>Questions:</code></p>
<p>我已经得到了一些解决所面临的问题的方法,但由于我对Python的无知,它们对我来说听起来都相当神秘。在</p>
<ol>
<li><p>Deepcopy不能很好地使用SQLA。有人告诉我,ORM对象上的deepcopy可能存在一些问题,使它无法像您预期的那样工作。显然,我最好是“构建复制构造函数,即defcopy(self):returnfoobar(…..)”<I>有人能解释一下这是什么意思吗?</i></p></li>
<li><p>我检查后发现<code>deepcopy</code>有问题,因为SQLAlchemy在您的对象上放置了额外的信息,即<code>_sa_instance_state</code>属性,我不想在副本中出现,但对于对象来说是必需的。有人告诉我:“有很多方法可以手动删除旧的<code>_sa_instance_state</code>并在对象上放置一个新的,但最简单的方法是用<code>__init__()</code>创建一个新的对象,并设置重要的属性,而不是进行完全的深度复制。”<I>这到底意味着什么?我是否要创建一个新的、未映射的类类似于旧的已映射类?</i></p></li>
<li><p>另一种解决方案是,我必须在您的对象上“实现<code>__deepcopy__()</code>”,并确保设置了一个新的实例状态,其中包含sqlalchemy.orm.attributes这对我来说很有帮助。“这又一次超出了我的能力,所以有人能解释一下这意味着什么吗?</i></p></li>
<li><p>一个更一般的问题:对于上面的信息,有没有关于如何维护<code>best_node</code>(必须始终在while循环中保持)和<code>previous_node</code>(如果我的实际对象是被字典引用,因此节点)因释放/重新分配而发生变化?也就是说,不用拷贝?</p></li>
</ol>