Python 复制字典和在SQLAlchemy ORM对象上使用deepcopy时出现问题

Python 复制字典和在SQLAlchemy ORM对象上使用deepcopy时出现问题,python,sqlalchemy,deep-copy,simulated-annealing,Python,Sqlalchemy,Deep Copy,Simulated Annealing,我正在做一个模拟退火算法来优化给定的学生和项目分配 这是来自维基百科的语言不可知伪代码: s ← s0; e ← E(s) // Initial state, energy. sbest ← s; ebest ← e // Initial "best" solution k ← 0 // Energ

我正在做一个模拟退火算法来优化给定的学生和项目分配

这是来自维基百科的语言不可知伪代码:

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.
s← s0;E← E(s)//初始状态,能量。
斯贝斯特← s埃伯斯特← e//初始“最佳”解决方案
K← 0//能量评估计数。
当kemax//当时间还剩&不够好时:
冷嘲热讽← 邻居///挑选一些邻居。
新能源← E(snew)//计算它的能量。
如果enewrandom(),那么//我们应该转向它吗?
s← snew;E← enew//是,更改状态。
K← k+1//再进行一次评估
return sbest//返回找到的最佳解决方案。
以下是对该技术的改编。我的主管说这个想法在理论上是好的

首先,我从一整套随机分配中选取一些分配(即学生及其分配项目的整个字典,包括项目的排名),复制并传递给我的函数。让我们把这个分配称为aOld(它是一个字典)
aOld
有一个与之相关的权重,称为
wOld
。权重如下所述

该函数执行以下操作:

  • 让此分配,
    aOld
    成为
    最佳节点
  • 从所有学生中,随机挑选一些学生,并将其粘贴在列表中
  • 剥离(取消分配)他们的项目++反映项目(
    已分配
    参数现在为
    False
    )和讲师(如果一个或多个项目不再分配,则释放插槽)
  • 将该列表随机化
  • 再次尝试分配(重新分配)该列表中的每个项目
  • 计算权重(将等级相加,等级1=1,等级2=2…无项目等级=101)
  • 对于这个新的分配
    重新
    ,如果权重
    wNew
    小于我在开始时拾取的分配权重
    wOld
    ,那么这就是
    最佳节点
    (由上面的
    模拟退火算法定义)。将算法重新应用于
    并继续
  • 如果
    wOld
    ,则再次将算法应用于
    aOld
    ,然后继续
分配/数据点被表示为“节点”,这样一个
节点=(权重、分配、项目、讲师)

现在,我只能执行此算法一次,但我需要尝试一个数字N(在维基百科代码片段中用
kmax
表示),并确保我始终随身携带上一个
节点和
最佳节点

为了不修改我的原始词典(我可能想重置为),我对词典做了一个浅拷贝。从我在文档中读到的内容来看,它似乎只复制引用,而且因为我的字典包含对象,所以更改复制的字典最终还是会更改对象。因此,我尝试使用
copy.deepcopy()
。这些字典引用了已经用SQLA映射的对象


问题:

我已经得到了一些解决所面临问题的方法,但由于我对使用Python非常熟悉,它们对我来说都相当神秘

  • Deepcopy不能很好地使用SQLA。有人告诉我,ORM对象上的DeepCopy可能存在一些问题,使其无法按预期工作。显然,我最好使用“构建副本构造函数,即def copy(self):return FooBar(…)”。有人能解释一下这是什么意思吗

  • 我检查并发现
    deepcopy
    存在问题,因为SQLAlchemy在对象上放置了额外的信息,即
    \u sa\u instance\u state
    属性,我不希望在副本中包含该属性,但该属性是对象必须具备的。有人告诉我:“有很多方法可以手动清除旧的
    \u sa\u instance\u state
    并在对象上放置一个新的状态,但最简单的方法是使用
    \u init\u()
    创建一个新对象并设置重要的属性,而不是进行完整的深度复制。”这到底意味着什么?我是否创建了一个新的未映射类,类似于旧的映射类

  • 另一种解决方案是,我必须“在您的对象上实现
    \uuu deepcopy\uuuuu()
    ,并确保设置了一个新的\u sa\u实例\u状态,sqlalchemy.orm.attributes中有一些函数可以帮助实现这一点。”这再一次超出了我的理解范围,所以有人可以解释一下它的含义吗

  • 一个更一般的问题:鉴于上述信息,如果我的实际对象(由字典引用,因此是节点),我有没有建议如何维护
    最佳节点
    (必须始终通过while循环保持)和
    上一个节点
    的信息/状态是否因发生解除分配/重新分配而发生变化?也就是说,不使用复制


  • 您不希望像那样复制sqlalchemy对象。您可以实现自己的方法,这些方法可以很容易地创建副本,但这可能不是您想要的。你不想在数据库中保存学生和项目的副本,是吗?所以不要复制这些数据

    因此,您有一本保存分配的词典。在此过程中,永远不要修改SQLAlchemy对象。所有可以修改的信息都应存储在这些词典中。如果你
    # transactional session
    Session = sessionmaker(transactional=True)
    sess = Session()