Декартово произведение фиксированных отношений в Python - PullRequest
0 голосов
/ 27 июня 2018

Справочная информация:
Я заинтересован в изучении квантовых фазовых переходов различных материалов, написав имитацию на адиабатическом квантовом компьютере 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}], который представляет декартово произведение входных данных h и J на каждом отдельном кубите и связи.

Чего я на самом деле хочу и что уже написал:
Выше я столкнулся с серьезной проблемой. Предположим, я хочу просмотреть серию параметров, в которых некоторые кубиты или ответвители имеют фиксированные отношения по отношению друг к другу в любом заданном цикле. Это важно из-за некоторых сложностей, когда логическая проблема должна быть отображена на DWave нетривиальными способами. Например, предположим, что я хочу запустить проблему, где qubit0 имеет h в [0, 1, 2], qubit1 имеет h в [1, 2, 3] и qubit3 имеет h в [5, 8], НО отношения qubit1_h = qubit0_h + 1 должно быть сохранено; то есть я хочу, чтобы произведение значений было [(0, 1, 5), (0, 1, 8), (1, 2, 5), (1, 2, 8), ...], а НЕ всеми комбинациями, как это дано декартовым произведением.

Следующий код сделает это для параметров h, но не работает для параметров J, поскольку ключи словаря являются кортежами. Кроме того, я должен запустить свой исходный код, чтобы сгенерировать продукт для ухода за больными, если мне не нужны эти функции, поэтому, похоже, он генерирует «3 случая».

def fixed_relationship_sweep(input_params, together):
    """
    Inputs
    ------
    input_params: {0:[x1, x2], 1:[x3, x4], 2:[y1, y2], 3:[y3, y4]]}
    dictionary mapping qubits to parameter lists to iterate through
    together: [[0, 1], [2, 3]]
    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:
    [{0:x1, 1:x3, 2:y1, 3:y3}, {0:x1, 1:x3, 2:y2, 3:y4}, {0:x2, 1:x4, 2:y1, 3:y3},
    {0:x2, 1:x4, 2:y2, 3:y4}] 
    """
    qsorcs = []
    params = []
    #index representation of params, as cartesian product must respect fixed positions
    #of arguments and not their values, ie [x1, x3] vary together in example
    tempidxrep = []
    for key, value in input_params.items():
        qsorcs.append(key)
        params.append(value)
        tempidxrep.append([i for i in range(len(value))])

    idxrep = []
    #remove redundancy in index representation governed by fixed relationships in together
    for fix_rel in together:
        idxrep.append(tempidxrep[fix_rel[0]])

    #sweep combinations via carteisan product
    idxcombos = itertools.product(*idxrep)

    #reconstruct actual parameter combinations
    param_combos = []
    for idxcombo in idxcombos:
        trial = {qsorcs[j]: params[j][idxcombo[i]] for i in range(len(idxcombo)) for j in together[i]}
        param_combos.append(trial)

    return param_combos

Существует ли более простой и лучший способ сделать это с помощью встроенных инструментов, таких как itertools, которые могут обрабатывать ключи как целые числа или кортежи без написания отдельных сложных функций? Другими словами, я просто подхожу к этой, казалось бы, простой проблеме с неправильного направления?

1 Ответ

0 голосов
/ 02 июля 2018

После публикации этого вопроса я написал улучшенную версию исходного кода, которая допускает исходный ввод (словарь в форме {h_n: hval} с h итератором, представляющим n-й кубит) вместе с дополнительными входами в виде {J_nm: Jval} с J_nm набор (qn, qm) силы связи между кубитами n и m. Кроме того, он не ломается, когда некоторые кубиты / ответвители исключаются из «общих» списков, как это сделал оригинал. Таким образом, этот новый код функционально работает для того, что я хочу сделать. Тем не менее, я подозреваю, что есть лучший выход.

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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...