def _setup(self): self._operator.to_paulis() self._ret['translation'] = sum( [abs(p[0]) for p in self._operator.paulis]) self._ret['stretch'] = 0.5 / self._ret['translation'] # translate the operator self._operator._simplify_paulis() translation_op = Operator([[ self._ret['translation'], Pauli(np.zeros(self._operator.num_qubits), np.zeros(self._operator.num_qubits)) ]]) translation_op._simplify_paulis() self._operator += translation_op # stretch the operator for p in self._operator._paulis: p[0] = p[0] * self._ret['stretch'] 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._slice_pauli_list = slice_pauli_list
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
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') # initialize state_in qc = self._state_in.construct_circuit('circuit', q) # Put all ancillae in uniform superposition qc.add(a) qc.u2(0, np.pi, a) # phase kickbacks via eoh 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_evolutions = Operator.construct_evolution_circuit( slice_pauli_list, -2 * np.pi, self._num_time_slices, q, a, ctl_idx=i, shallow_slicing=self._shallow_circuit_concat) if self._shallow_circuit_concat: qc.data += qc_evolutions.data else: qc += qc_evolutions # 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.add(c) qc.barrier(a) qc.measure(a, c) self._circuit = qc
def construct_circuit(self, state_register=None, ancilla_register=None, aux_register=None, measure=False): """ Construct the Phase Estimation circuit Args: state_register (QuantumRegister): the optional register to use for the quantum state ancilla_register (QuantumRegister): the optional register to use for the ancillary measurement qubits aux_register (QuantumRegister): an optional auxiliary quantum register measure (bool): boolean flag to indicate if the built circuit should include ancilla measurement Returns: the QuantumCircuit object for the constructed circuit """ if self._circuit[measure] is None: if self._operator is not None: # check for identify paulis to get its coef for applying global phase shift on ancillae later num_identities = 0 for p in self._operator.paulis: if np.all(np.logical_not(p[1].z)) and np.all( np.logical_not(p[1].x)): num_identities += 1 if num_identities > 1: raise RuntimeError( 'Multiple identity pauli terms are present.') self._ancilla_phase_coef = p[0].real if isinstance( p[0], complex) else p[0] if ancilla_register is None: a = QuantumRegister(self._num_ancillae, name='a') else: a = ancilla_register if state_register is None: if self._operator is not None: q = QuantumRegister(self._operator.num_qubits, name='q') elif self._unitary_circuit_factory is not None: q = QuantumRegister( self._unitary_circuit_factory.num_target_qubits, name='q') else: raise RuntimeError('Missing operator specification.') else: q = state_register qc = QuantumCircuit(a, q) if aux_register is None: num_aux_qubits, aux = 0, None if self._state_in_circuit_factory is not None: num_aux_qubits = self._state_in_circuit_factory.required_ancillas( ) if self._unitary_circuit_factory is not None: num_aux_qubits = max( num_aux_qubits, self._unitary_circuit_factory. required_ancillas_controlled()) if num_aux_qubits > 0: aux = QuantumRegister(num_aux_qubits, name='aux') qc.add_register(aux) else: aux = aux_register qc.add_register(aux) # initialize state_in if self._state_in is not None: qc.data += self._state_in.construct_circuit('circuit', q).data elif self._state_in_circuit_factory is not None: self._state_in_circuit_factory.build(qc, q, aux) else: raise RuntimeError('Missing initial state specification.') # Put all ancillae in uniform superposition qc.u2(0, np.pi, a) # phase kickbacks via dynamics if self._operator is not None: 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_evolutions = Operator.construct_evolution_circuit( slice_pauli_list, -2 * np.pi, self._num_time_slices, q, a, ctl_idx=i, shallow_slicing=self._shallow_circuit_concat) if self._shallow_circuit_concat: qc.data += qc_evolutions.data else: qc += qc_evolutions # 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]) elif self._unitary_circuit_factory is not None: for i in range(self._num_ancillae): self._unitary_circuit_factory.build_controlled_power( qc, q, a[i], 2**i, aux) # inverse qft on ancillae self._iqft.construct_circuit('circuit', a, qc) # measuring ancillae if measure: c = ClassicalRegister(self._num_ancillae, name='c') qc.add_register(c) qc.barrier(a) qc.measure(a, c) self._circuit[measure] = qc return self._circuit[measure]