Python中的固定关系笛卡尔积

时间:2018-06-27 16:01:48

标签: python python-3.x cartesian-product

背景:
我对通过在DWave的绝热量子计算机上编写模拟研究各种材料的量子相变感兴趣。为了更容易生成作为参数函数的相图,我正在编写实用程序来扫过参数,使用这些参数集运行仿真并收集数据。

输入条件的背景:
在DWave上,我可以设置两组参数,h偏置和J耦合。这些输入如下:h = {qubit0: hvalue0, qubit1: hvalue1,...}J = {(qubit0, qubit1): J01, (qubit2, qubit3): J23, ...}。到目前为止,我有一个工具可以对给定的输入进行参数扫描,如下所示:{qubit: [hz1, hz2,..., hzn]}将量子位映射到h的值进行扫描,将{coupler: [J1, J2,..., Jn]}映射耦合器映射到J的值进行扫描。在这两种情况下,输出都是格式为[{trial1}, {trial2}, ... {trialn}]的列表,表示每个单独的量子位和耦合上hJ输入的笛卡尔积。

我实际上想要什么和到目前为止我写的东西:
在上面,我遇到了一个严重的问题。假设我想浏览一系列参数,其中某些量子位或耦合器在任何给定运行中彼此之间具有固定关系。由于某些复杂性,这很重要,在这种情况下,必须以非平凡的方式将逻辑问题映射到DWave上。例如,假设我要运行一个问题,其中qubit0h中有[0, 1, 2]qubit1h中有[1, 2, 3]并且{{1 }}在qubit3中有h,但必须保留关系[5, 8];即,我希望值的乘积为qubit1_h = qubit0_h + 1,而不是笛卡尔乘积给出的所有组合。

以下代码将对h参数执行此操作,但不适用于J参数,因为字典键是元组。另外,如果我不想要此功能,则必须运行我的原始代码来生成笛卡尔积,因此它似乎会生成“ 3种情况”。

[(0, 1, 5), (0, 1, 8), (1, 2, 5), (1, 2, 8), ...]

是否有一种更简便,更好的方法,例如使用itertools这样的内置工具,可以处理整数或元组的键,而无需编写单独的复杂函数?换句话说,我是从错误的方向来解决这个看似简单的问题吗?

1 个答案:

答案 0 :(得分:0)

发布此问题后,我编写了原始代码的改进版本,该版本允许原始输入(格式为{h_n: hval}的词典,其中h代表第n个qubit的iteger)以及该格式的其他输入{J_nm: Jval},其中J_nm为量子位n和m之间的耦合强度的元组(qn,qm)。另外,当像原始灯一样从“一起”的灯中排除某些量子位/耦合器时,它也不会中断。因此,此新代码在功能上可以满足我的需求。尽管如此,我怀疑还有更好的方法。

def fixed_relationship_sweep(input_params, together):
"""
Inputs
------
input_params: {qorc1:[x1, x2], qorc2:[x3, x4], qorc3:[y1, y2], qorc4:[y3, y4]]}
dictionary mapping qubits or couplers to parameter lists to iterate through
together: [[qorc1, qorc2], [qorc3, qorc4]]
list of qubit lists that specify which qubit parameters to sweep with a fixed relationship

Output
------
fixed_rel_sweep: [{trial1}, {trial2}, ...{trialn}] where qubits labelled as "together" are
swept with fixed 1-1 relationship, ie, above produces:
[{qorc1:x1, qorc2:x3, qorc3:y1, qorc4:y3}, {qorc1:x1, qorc2:x3, qorc3:y2, qorc4:y4},
{qorc1:x2, qorc2:x4, qorc3:y1, qorc4:y3},{qorc1:x2, qorc2:x4, qorc3:y2, qorc4:y4}] 
"""
#list of qubits or couplers
qsorcs = []
#index representation of params, as cartesian product must respect fixed positions
#of arguments and not their values, ie [x1, x3] vary together in example
idxrep = {}
for key, value in input_params.items():
    qsorcs.append(key)
    idxrep[key] = [i for i in range(len(value))]

#remove redundancy in index representation governed by fixed relationships in together
count = 0
for fix_rel in together:
    for j in range(len(fix_rel)):
        if j != 0:
            del idxrep[fix_rel[j]]

#sweep combinations via cartesian product
idxdict_combos = (list(dict(zip(idxrep, x)) for x in itertools.product(*idxrep.values())))

#reconstruct actual parameter combinations with "redundant" parameter values
dict_combos = []
for combo in idxdict_combos:
    #add back in "redundant" parameters
    for fix_rel in together:
        for qorc in fix_rel[1::]:
            combo[qorc] = combo[fix_rel[0]]

    #add back in true values corresponding to indices
    tempdict = {}
    for key, value in combo.items():
        tempdict[key] = input_params[key][value]

    dict_combos.append(tempdict)

return dict_combos