def _construct_qpe_evolution(self): """Implement the Quantum Phase Estimation algorithm""" a = QuantumRegister(self._num_ancillae, name='a') c = ClassicalRegister(self._num_ancillae, name='c') q = QuantumRegister(self._operator.num_qubits, name='q') qc = QuantumCircuit(a, q, c) # initialize state_in qc.data += self._state_in.construct_circuit('circuit', q).data # Put all ancillae in uniform superposition qc.u2(0, np.pi, a) if self._use_basis_gates else qc.h(a) # phase kickbacks via dynamics pauli_list = self._operator.reorder_paulis( grouping=self._paulis_grouping) if len(pauli_list) == 1: slice_pauli_list = pauli_list else: if self._expansion_mode == 'trotter': slice_pauli_list = pauli_list elif self._expansion_mode == 'suzuki': slice_pauli_list = Operator._suzuki_expansion_slice_pauli_list( pauli_list, 1, self._expansion_order) else: raise ValueError('Unrecognized expansion mode {}.'.format( self._expansion_mode)) for i in range(self._num_ancillae): qc.data += self._operator.construct_evolution_circuit( slice_pauli_list, -2 * np.pi, self._num_time_slices, q, a, ctl_idx=i, use_basis_gates=self._use_basis_gates).data # global phase shift for the ancilla due to the identity pauli term qc.u1(2 * np.pi * self._ancilla_phase_coef * (2**i), a[i]) # inverse qft on ancillae self._iqft.construct_circuit('circuit', a, qc) # measuring ancillae qc.measure(a, c) self._circuit = qc
def _estimate_phase_iteratively(self): """Iteratively construct the different order of controlled evolution circuit to carry out phase estimation""" pauli_list = self._operator.reorder_paulis( grouping=self._paulis_grouping) if len(pauli_list) == 1: slice_pauli_list = pauli_list else: if self._expansion_mode == 'trotter': slice_pauli_list = pauli_list else: slice_pauli_list = Operator._suzuki_expansion_slice_pauli_list( pauli_list, 1, self._expansion_order) self._ret['top_measurement_label'] = '' omega_coef = 0 # k runs from the number of iterations back to 1 for k in range(self._num_iterations, 0, -1): omega_coef /= 2 qc = self._construct_kth_evolution(slice_pauli_list, k, -2 * np.pi * omega_coef) measurements = self.execute(qc).get_counts(qc) if '0' not in measurements: if '1' in measurements: x = 1 else: raise RuntimeError( 'Unexpected measurement {}.'.format(measurements)) else: if '1' not in measurements: x = 0 else: x = 1 if measurements['1'] > measurements['0'] else 0 self._ret['top_measurement_label'] = '{}{}'.format( x, self._ret['top_measurement_label']) omega_coef = omega_coef + x / 2 logger.info( 'Reverse iteration {} of {} with measured bit {}'.format( k, self._num_iterations, x)) return omega_coef