复制字典和在SQLAlchemy ORM对象上使用Deepcopy时遇到问题 [英] Trouble with copying dictionaries and using deepcopy on an SQLAlchemy ORM object

查看:417
本文介绍了复制字典和在SQLAlchemy ORM对象上使用Deepcopy时遇到问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm doing a Simulated Annealing algorithm to optimise a given allocation of students and projects.

这是维基百科中与语言无关的伪代码:

This is language-agnostic pseudocode from Wikipedia:

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.

以下是该技术的改编.我的上司说这个想法理论上很好.

The following is an adaptation of the technique. My supervisor said the idea is fine in theory.

首先,我从整个随机分配集中选择一些分配(即学生及其分配的项目的完整词典,包括项目的等级),将其复制并传递给我的函数.我们将此分配称为aOld(这是一个字典). aOld具有与之相关的权重,称为wOld.加权说明如下.

First I pick up some allocation (i.e. an entire dictionary of students and their allocated projects, including the ranks for the projects) from entire set of randomised allocations, copy it and pass it to my function. Let's call this allocation aOld (it is a dictionary). aOld has a weight related to it called wOld. The weighting is described below.

该函数执行以下操作:

  • 让此分配为aOldbest_node
  • 从所有学生中随机选择一名学生并坚持列出
  • 将他们的项目剥离(取消分配)++反映项目(allocated参数现在为False)和讲师的更改(如果不再分配一个或多个项目,则腾出空位)
  • 随机列出该列表
  • 尝试再次分配(重新分配)该列表中的每个人
  • 计算权重(累加等级,等级1 = 1,等级2 = 2 ...而没有项目等级= 101)
  • 对于此新分配aNew,如果权重wNew小于我在一开始就获得的分配权重wOld,则该权重为best_node(由上面的Simulated Annealing算法定义).将算法应用于aNew并继续.
  • 如果为wOld < wNew,则将算法再次应用于aOld,然后继续.
  • Let this allocation, aOld be the best_node
  • From all the students, pick a random number of students and stick in a list
  • Strip (DEALLOCATE) them of their projects ++ reflect the changes for projects (allocated parameter is now False) and lecturers (free up slots if one or more of their projects are no longer allocated)
  • Randomise that list
  • Try assigning (REALLOCATE) everyone in that list projects again
  • Calculate the weight (add up ranks, rank 1 = 1, rank 2 = 2... and no project rank = 101)
  • For this new allocation aNew, if the weight wNew is smaller than the allocation weight wOld I picked up at the beginning, then this is the best_node (as defined by the Simulated Annealing algorithm above). Apply the algorithm to aNew and continue.
  • If wOld < wNew, then apply the algorithm to aOld again and continue.

分配/数据点表示为节点",以使node = (weight, allocation_dict, projects_dict, lecturers_dict)

The allocations/data-points are expressed as "nodes" such that a node = (weight, allocation_dict, projects_dict, lecturers_dict)

现在,我只能执行一次该算法,但是我需要尝试输入数字N(在Wikipedia摘录中由kmax表示),并确保我一直在使用,以前的nodebest_node.

Right now, I can only perform this algorithm once, but I'll need to try for a number N (denoted by kmax in the Wikipedia snippet) and make sure I always have with me, the previous node and the best_node.

为了不修改原始字典(我可能希望将其重置为原始字典),我对字典进行了浅表复制.从我在文档中阅读的内容来看,它似乎仅复制引用,并且由于我的词典包含对象,因此更改复制的字典最终还是会更改对象.因此,我尝试使用copy.deepcopy().这些词典是指已使用SQLA映射的对象.

So that I don't modify my original dictionaries (which I might want to reset to), I've done a shallow copy of the dictionaries. From what I've read in the docs, it seems that it only copies the references and since my dictionaries contain objects, changing the copied dictionary ends up changing the objects anyway. So I tried to use copy.deepcopy().These dictionaries refer to objects that have been mapped with SQLA.

Questions:

已经为我面临的问题提供了一些解决方案,但是由于我使用python的绿色环保,它们听起来对我来说都是很神秘的.

I've been given some solutions to the problems faced but due to my über green-ness with using Python, they all sound rather cryptic to me.

  1. Deepcopy在SQLA中不能很好地发挥作用.有人告诉我,ORM对象上的Deepcopy可能存在阻止其按预期工作的问题.显然我最好还是构建副本构造函数,即def copy(self):return FooBar(....)". 有人可以解释一下这是什么意思吗?

我检查并发现deepcopy存在问题,因为SQLAlchemy在您的对象上放置了额外的信息,即_sa_instance_state属性,我不想在副本中使用该属性,但是该对象具有此属性是必需的.有人告诉我:有种方法可以手动删除旧的_sa_instance_state并在对象上放置一个新对象,但是最直接的方法是使用__init__()制作一个新对象并设置重要的属性,而不是进行完整的深层复制." 这到底是什么意思?我是否要创建一个新的,未映射的类,类似于旧的映射类?

I checked and found out that deepcopy has issues because SQLAlchemy places extra information on your objects, i.e. an _sa_instance_state attribute, that I wouldn't want in the copy but is necessary for the object to have. I've been told: "There are ways to manually blow away the old _sa_instance_state and put a new one on the object, but the most straightforward is to make a new object with __init__() and set up the attributes that are significant, instead of doing a full deep copy." What exactly does that mean? Do I create a new, unmapped class similar to the old, mapped one?

另一种解决方案是,我必须对您的对象实施__deepcopy__()并确保设置了新的_sa_instance_state,sqlalchemy.orm.attributes中有一些函数可以帮助您解决此问题." 这又一次超出了我的范围,所以有人可以解释一下这是什么意思吗?

An alternate solution is that I'd have to "implement __deepcopy__() on your objects and ensure that a new _sa_instance_state is set up, there are functions in sqlalchemy.orm.attributes which can help with that." Once again this is beyond me so could someone kindly explain what it means?

一个更笼统的问题:鉴于上述信息,对于如何维护best_node(必须始终通过我的while循环持续存在)和previous_node的信息/状态,有什么建议?我的实际对象(由字典引用,因此由节点引用)由于发生了重新分配/重新分配而发生了变化?那就是不使用副本?

A more general question: given the above information are there any suggestions on how I can maintain the information/state for the best_node (which must always persist through my while loop) and the previous_node, if my actual objects (referenced by the dictionaries, therefore the nodes) are changing due to the deallocation/reallocation taking place? That is, without using copy?

推荐答案

我还有另一种可能的解决方案:使用事务.这可能仍然不是最好的解决方案,但实施起来应该更快.

I have another possible solution: use transactions. This probably still isn't the best solution but implementing it should be faster.

首先像这样创建会话:

# transactional session
Session = sessionmaker(transactional=True)
sess = Session()

那样,它将具有事务性.事务的工作方式是sess.commit()将使您的更改永久生效,而sess.rollback()将恢复它们.

That way it will be transactional. The way transactions work is that sess.commit() will make your changes permanent while sess.rollback() will revert them.

在模拟退火的情况下,您想在找到新的最佳解决方案时进行提交.以后,您可以调用rollback()将状态恢复到该位置.

In the case of simulated annealing you want to commit when you find a new best solution. At any later point, you can invoke rollback() to revert the status back to that position.

这篇关于复制字典和在SQLAlchemy ORM对象上使用Deepcopy时遇到问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆