def construct_circuit(self, k=None, omega=0, measurement=False): """Construct the kth iteration Quantum Phase Estimation circuit. For details of parameters, please see Fig. 2 in https://arxiv.org/pdf/quant-ph/0610214.pdf. Args: k (int): the iteration idx. omega (float): the feedback angle. measurement (bool): Boolean flag to indicate if measurement should be included in the circuit. Returns: QuantumCircuit: the quantum circuit per iteration """ k = self._num_iterations if k is None else k a = QuantumRegister(1, name='a') q = QuantumRegister(self._operator.num_qubits, name='q') self._ancillary_register = a self._state_register = q qc = QuantumCircuit(q) qc += self._state_in.construct_circuit('circuit', q) # hadamard on a[0] qc.add_register(a) qc.u2(0, np.pi, a[0]) # controlled-U qc_evolutions = Operator.construct_evolution_circuit( self._slice_pauli_list, -2 * np.pi, self._num_time_slices, q, a, unitary_power=2**(k - 1), shallow_slicing=self._shallow_circuit_concat) if self._shallow_circuit_concat: qc.data += qc_evolutions.data else: qc += qc_evolutions # global phase due to identity pauli qc.u1(2 * np.pi * self._ancilla_phase_coef * (2**(k - 1)), a[0]) # rz on a[0] qc.u1(omega, a[0]) # hadamard on a[0] qc.u2(0, np.pi, a[0]) if measurement: c = ClassicalRegister(1, name='c') qc.add_register(c) # qc.barrier(self._ancillary_register) qc.measure(self._ancillary_register, c) return qc
def construct_circuit(self, x, qr=None, inverse=False): """ Construct the second order expansion based on given data. Args: x (numpy.ndarray): 1-D to-be-transformed data. qr (QauntumRegister, optional): the QuantumRegister object for the circuit, if None, generate new registers with name q. inverse (bool, optional): whether or not inverse the circuit Returns: QuantumCircuit: a quantum circuit transform data x. """ if not isinstance(x, np.ndarray): raise TypeError("x must be numpy array.") if x.ndim != 1: raise ValueError("x must be 1-D array.") if x.shape[0] != self._num_qubits: raise ValueError( "number of qubits and data dimension must be the same.") if qr is None: qr = QuantumRegister(self._num_qubits, name='q') qc = QuantumCircuit(qr) for _ in range(self._depth): for i in range(self._num_qubits): qc.u2(0, pi, qr[i]) for pauli in self._pauli_strings: coeff = self._data_map_func( self._extract_data_for_rotation(pauli, x)) p = Pauli.from_label(pauli) qc += Operator.construct_evolution_circuit([[coeff, p]], 1, 1, qr) if inverse: qc = qc.inverse() return qc
def construct_circuit(self, state_register=None, ancillary_register=None, auxiliary_register=None): """ Construct the Phase Estimation circuit Args: state_register (QuantumRegister): the optional register to use for the quantum state ancillary_register (QuantumRegister): the optional register to use for the ancillary measurement qubits auxiliary_register (QuantumRegister): an optional auxiliary quantum register Returns: the QuantumCircuit object for the constructed circuit """ if self._circuit is None: if ancillary_register is None: a = QuantumRegister(self._num_ancillae, name='a') else: a = ancillary_register self._ancillary_register = a 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 self._state_register = q qc = QuantumCircuit(a, q) if auxiliary_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 = auxiliary_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: # check for identify paulis to get its coef for applying global phase shift on ancillae later num_identities = 0 for p in self._pauli_list: 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 len(self._pauli_list) == 1: slice_pauli_list = self._pauli_list else: if self._expansion_mode == 'trotter': slice_pauli_list = self._pauli_list elif self._expansion_mode == 'suzuki': slice_pauli_list = Operator._suzuki_expansion_slice_pauli_list( self._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) self._circuit = qc return self._circuit