-
Notifications
You must be signed in to change notification settings - Fork 4
/
qxx_positions.py
174 lines (145 loc) · 6.03 KB
/
qxx_positions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import numpy
import copy
import qiskit
class QXXPositions:
def __init__(self, dag_circuit, parameters,initial_mapping):
"""
:param dag_circuit:
:param parameters:
:param initial_mapping:
"""
"""
The resulting circuit has a maximum number of qubits of the NISQ chip
"""
self.quantum_reg = qiskit.QuantumRegister(parameters["nisq_qubits"], "q")
self.classic_reg = qiskit.ClassicalRegister(parameters["nisq_qubits"], "c")
'''
Current logical qubit position on physical qubits
'''
"""
Returns an int-to-int map: logical qubit @ physical qubit map
There is something similar in Coupling, but I am not using it
"""
self.pos_circuit_to_phys = {}
for circ_qubit in range(dag_circuit.num_qubits()):
# configuration[i] = nrq - 1 - i # qubit i@i
self.pos_circuit_to_phys[circ_qubit] = initial_mapping[circ_qubit] # qubit i@i
# print("current circ2phys: ", self.pos_circuit_to_phys)
"""
The reverse dictionary of current_positions
"""
self.pos_phys_to_circuit = {k: -1 for k in range(parameters["nisq_qubits"])}
for k, v in self.pos_circuit_to_phys.items():
self.pos_phys_to_circuit[v] = k
# print("current phys2circ: ", self.pos_phys_to_circuit)
def update_configuration(self, route_phys):
if len(route_phys) == 0:
return
route_phys_backup = copy.deepcopy(route_phys)
current_mapping = []
for route_phys_el in route_phys_backup:
current_mapping.append(self.pos_phys_to_circuit[route_phys_el])
"""
Because there is a chain of SWAPs being simulated a chain
of logical qubits 1,2,3,4,5 will become 2,3,4,5,1
Thus, route_circuit_backup is a circular permuation
"""
# Add the first element to the end
route_phys_backup.append(route_phys_backup[0])
# Simulate the permutation by reading from 1 to end (previous start)
route_phys_backup = route_phys_backup[1:]
# Update the circuit to phys
for i in range(0, len(route_phys_backup)):
self.pos_phys_to_circuit[route_phys_backup[i]] = current_mapping[i]
# Calculate the inverse dictionary - phys to circuit
self.pos_circuit_to_phys.update({v: k
for k, v in self.pos_phys_to_circuit.items()
if v != -1})
# print("current circ2phys: ", self.pos_circuit_to_phys)
# print("current phys2circ: ", self.pos_phys_to_circuit)
# # TODO: FIX IT!!!
# """
# Due to refactoring this a very complicated way to update
# :param route_phys: route of physical qubits on the coupling graph
# :return:
# """
# route_circuit = [self.pos_phys_to_circuit[x] for x in route_phys]
#
# if len(route_circuit) == 0:
# return
#
# route_circuit_backup = copy.deepcopy(route_circuit)
#
# current_mapping = []
# for route_circ_el in route_circuit_backup:
# current_mapping.append(self.pos_circuit_to_phys[route_circ_el])
#
# """
# Because there is a chain of SWAPs being simulated a chain
# of logical qubits 1,2,3,4,5 will become 2,3,4,5,1
# Thus, route_circuit_backup is a circular permuation
# """
# # Add the first element to the end
# route_circuit_backup.append(route_circuit_backup[0])
# # Simulate the permutation by reading from 1 to end (previous start)
# route_circuit_backup = route_circuit_backup[1:]
#
# # Update the circuit to phys
# for i in range(0, len(route_circuit_backup)):
# self.pos_circuit_to_phys[route_circuit_backup[i]] = current_mapping[i]
#
# # Calculate the inverse dictionary - phys to circuit
# self.pos_phys_to_circuit.update({v: k for k, v in self.pos_circuit_to_phys.items()})
def translate_op_to_coupling_map(self, op):
'''
Translate qargs and cargs depending on the position of the logical qubit
'''
translated_op = copy.deepcopy(op)
# TODO: deepcopy needed?
# translated_op["params"] = copy.deepcopy(op.params)
# translated_op["condition"] = copy.deepcopy(op.condition)
translated_op.qargs.clear()
for qubit_args in op.qargs:
x = self.pos_circuit_to_phys[qubit_args.index]
translated_op.qargs.append(qiskit.circuit.Qubit(self.quantum_reg, x))
translated_op.cargs.clear()
for carg in op.cargs:
x = self.pos_circuit_to_phys[carg.index]
translated_op.cargs.append(qiskit.circuit.Clbit(self.classic_reg, x))
return translated_op
def debug_configuration(self):
print("-------------------")
for i in range(0, len(self.pos_circuit_to_phys)):
print("q", i, "@", self.pos_circuit_to_phys[i])
"""
The following methods were used instead of cuthill in __init__
"""
# use pagerank
# import operator
# pr1 = nx.pagerank(coupling_object["coupling"].G)
# sorted_pr1 = sorted(pr1.items(), key=operator.itemgetter(1))
# # print(sorted_pr1)
# #
# qgraph = qubit_graph(dag_circuit, False)
# pr2 = nx.pagerank(qgraph)
# sorted_pr2 = sorted(pr2.items(), key=operator.itemgetter(1))
# # print(sorted_pr2)
# for i in range(len(pr1)):
# configuration[sorted_pr2[i][0]] = sorted_pr1[i][0] - 1
# import operator
# qgraph = qubit_graph(dag_circuit, True)
# g2 = nx.compose(qgraph, coupling_object["coupling"].G)
# pos2 = nx.spectral_layout(g2)
#
# # import matplotlib.pyplot as plt
# # print("pos2", pos2)
# # nx.draw(g2, pos2)
# # plt.show()
#
# coll2 = {}
# for x in pos2:
# if x <= 0:
# coll2[-x] = pos2[x][1]
# sorted_3 = sorted(coll2.items(), key=operator.itemgetter(1))
# for i in range(len(sorted_3)):
# configuration[sorted_3[i][0]] = i