@@ -72,6 +72,10 @@ def __init__(self, use_hardware=False, num_runs=1024, verbose=False,
7272 self ._verbose = verbose
7373 self ._user = user
7474 self ._password = password
75+ self ._mapping = dict ()
76+ self ._inverse_mapping = dict ()
77+ self ._mapped_qubits = 0
78+ self ._probabilities = dict ()
7579
7680 def is_available (self , cmd ):
7781 """
@@ -101,6 +105,7 @@ def _reset(self):
101105 for _ in range (self ._num_qubits ):
102106 self ._cmds .append (["" ] * self ._num_cols )
103107 self ._positions = [0 ] * self ._num_qubits
108+ self ._mapped_qubits = 0
104109
105110 def _store (self , cmd ):
106111 """
@@ -113,14 +118,32 @@ def _store(self, cmd):
113118 """
114119 gate = cmd .gate
115120 if gate == Allocate or gate == Deallocate :
116- pass
117- elif gate == Measure :
121+ return
122+
123+ if self ._mapped_qubits == 0 :
124+ self ._mapping = dict ()
125+ self ._inverse_mapping = dict ()
126+ self ._probabilities = dict ()
127+
128+ for qr in cmd .qubits :
129+ for qb in qr :
130+ if not qb .id in self ._mapping :
131+ self ._mapping [qb .id ] = self ._mapped_qubits
132+ self ._inverse_mapping [self ._mapped_qubits ] = qb .id
133+ self ._mapped_qubits += 1
134+ for qb in cmd .control_qubits :
135+ if not qb .id in self ._mapping :
136+ self ._mapping [qb .id ] = self ._mapped_qubits
137+ self ._inverse_mapping [self ._mapped_qubits ] = qb .id
138+ self ._mapped_qubits += 1
139+
140+ if gate == Measure :
118141 for qr in cmd .qubits :
119142 for qb in qr :
120- qb_id = qb .id
121- meas = _IBMGateCommand ("measure" , qb_id )
122- self ._cmds [qb_id ][self ._positions [qb_id ]] = meas
123- self ._positions [qb_id ] += 1
143+ qb_pos = self . _mapping [ qb .id ]
144+ meas = _IBMGateCommand ("measure" , qb_pos )
145+ self ._cmds [qb_pos ][self ._positions [qb_pos ]] = meas
146+ self ._positions [qb_pos ] += 1
124147
125148 elif not (gate == NOT and get_control_count (cmd ) == 1 ):
126149 cls = gate .__class__ .__name__
@@ -129,20 +152,56 @@ def _store(self, cmd):
129152 else :
130153 gate_str = str (gate ).lower ()
131154
132- qb_id = cmd .qubits [0 ][0 ].id
133- ibm_cmd = _IBMGateCommand (gate_str , qb_id )
134- self ._cmds [qb_id ][self ._positions [qb_id ]] = ibm_cmd
135- self ._positions [qb_id ] += 1
155+ qb_pos = self . _mapping [ cmd .qubits [0 ][0 ].id ]
156+ ibm_cmd = _IBMGateCommand (gate_str , qb_pos )
157+ self ._cmds [qb_pos ][self ._positions [qb_pos ]] = ibm_cmd
158+ self ._positions [qb_pos ] += 1
136159 else :
137- ctrl_id = cmd .control_qubits [0 ].id
138- qb_id = cmd .qubits [0 ][0 ].id
139- pos = max (self ._positions [qb_id ], self ._positions [ctrl_id ])
140- self ._positions [qb_id ] = pos
141- self ._positions [ctrl_id ] = pos
142- ibm_cmd = _IBMGateCommand ("cx" , qb_id , ctrl_id )
143- self ._cmds [qb_id ][self ._positions [qb_id ]] = ibm_cmd
144- self ._positions [qb_id ] += 1
145- self ._positions [ctrl_id ] += 1
160+ ctrl_pos = self ._mapping [cmd .control_qubits [0 ].id ]
161+ qb_pos = self ._mapping [cmd .qubits [0 ][0 ].id ]
162+ pos = max (self ._positions [qb_pos ], self ._positions [ctrl_pos ])
163+ self ._positions [qb_pos ] = pos
164+ self ._positions [ctrl_pos ] = pos
165+ ibm_cmd = _IBMGateCommand ("cx" , qb_pos , ctrl_pos )
166+ self ._cmds [qb_pos ][self ._positions [qb_pos ]] = ibm_cmd
167+ self ._positions [qb_pos ] += 1
168+ self ._positions [ctrl_pos ] += 1
169+
170+ def get_probabilities (self , qureg ):
171+ """
172+ Return the list of basis states with corresponding probabilities.
173+
174+ The measured bits are ordered according to the supplied quantum register,
175+ i.e., the left-most bit in the state-string corresponds to the first qubit
176+ in the supplied quantum register.
177+
178+ Warning:
179+ Only call this function after the circuit has been executed!
180+
181+ Args:
182+ qureg (list<Qubit>): Quantum register determining the order of the
183+ qubits.
184+
185+ Returns:
186+ probability_dict (dict): Dictionary mapping n-bit strings to
187+ probabilities.
188+
189+ Raises:
190+ Exception: If no data is available (i.e., if the circuit has not been
191+ executed).
192+ """
193+ if len (self ._probabilities ) == 0 :
194+ raise RuntimeError ("Please, run the circuit first!" )
195+
196+ probability_dict = dict ()
197+
198+ for state in self ._probabilities :
199+ mapped_state = ['0' ] * len (qureg )
200+ for i in range (len (qureg )):
201+ mapped_state [i ] = state [self ._mapping [qureg [i ].id ]]
202+ probability_dict ["" .join (mapped_state )] = self ._probabilities [state ]
203+
204+ return probability_dict
146205
147206 def _run (self ):
148207 """
@@ -239,27 +298,26 @@ def _run(self):
239298 p_sum = 0.
240299 measured = ""
241300 for state , probability in zip (data ['labels' ], data ['values' ]):
242- if self ._verbose and probability > 0 :
243- print (str (state ) + " with p = " + str (probability ))
301+ state = list (reversed (state ))
302+ state [2 ], state [self ._cnot_qubit_id ] = state [self ._cnot_qubit_id ], state [2 ]
303+ state = "" .join (state )
244304 p_sum += probability
305+ star = ""
245306 if p_sum >= P and measured == "" :
246307 measured = state
247-
308+ star = "*"
309+ self ._probabilities [state ] = probability
310+ if self ._verbose and probability > 0 :
311+ print (str (state ) + " with p = " + str (probability ) + star )
312+
248313 class QB ():
249314 def __init__ (self , ID ):
250315 self .id = ID
251-
316+
252317 # register measurement result
253- for i in range (len (data ['qubits' ])):
254- ID = int (data ['qubits' ][i ])
255- if ID == 2 :
256- # we may have swapped these two qubits
257- # (cnot qubit is always #2 on the device)
258- # --> undo this transformation
259- ID = self ._cnot_qubit_id
260- elif ID == self ._cnot_qubit_id : # same here.
261- ID = 2
262- self .main_engine .set_measurement_result (QB (ID ), int (measured [- 1 - i ]))
318+ for ID in self ._mapping :
319+ location = self ._mapping [ID ]
320+ self .main_engine .set_measurement_result (QB (ID ), int (measured [location ]))
263321 self ._reset ()
264322 except TypeError :
265323 raise Exception ("Failed to run the circuit. Aborting." )
0 commit comments