def _setup(self): self._ret['translation'] = sum( [abs(p[0]) for p in self._operator.reorder_paulis()]) self._ret['stretch'] = 0.5 / self._ret['translation'] # translate the operator self._operator.simplify() translation_op = WeightedPauliOperator([[ self._ret['translation'], Pauli(np.zeros(self._operator.num_qubits), np.zeros(self._operator.num_qubits)) ]]) translation_op.simplify() self._operator += translation_op self._pauli_list = self._operator.reorder_paulis() # stretch the operator for p in self._pauli_list: p[0] = p[0] * self._ret['stretch'] if len(self._pauli_list) == 1: slice_pauli_list = self._pauli_list else: if self._expansion_mode == 'trotter': slice_pauli_list = self._pauli_list else: slice_pauli_list = suzuki_expansion_slice_pauli_list( self._pauli_list, 1, self._expansion_order) self._slice_pauli_list = slice_pauli_list
def _setup( self, operator: Optional[Union[OperatorBase, LegacyBaseOperator]]) -> None: self._operator = None self._ret = {} self._pauli_list = None self._phase_estimation_circuit = None self._slice_pauli_list = None if operator: # Convert to Legacy Operator if Operator flow passed in if isinstance(operator, OperatorBase): operator = operator.to_legacy_op() self._operator = op_converter.to_weighted_pauli_operator( operator.copy()) self._ret['translation'] = sum( [abs(p[0]) for p in self._operator.reorder_paulis()]) self._ret['stretch'] = 0.5 / self._ret['translation'] # translate the operator self._operator.simplify() translation_op = WeightedPauliOperator([[ self._ret['translation'], Pauli(np.zeros(self._operator.num_qubits), np.zeros(self._operator.num_qubits)) ]]) translation_op.simplify() self._operator += translation_op self._pauli_list = self._operator.reorder_paulis() # stretch the operator for p in self._pauli_list: p[0] = p[0] * self._ret['stretch'] if len(self._pauli_list) == 1: slice_pauli_list = self._pauli_list else: if self._expansion_mode == 'trotter': slice_pauli_list = self._pauli_list else: slice_pauli_list = suzuki_expansion_slice_pauli_list( self._pauli_list, 1, self._expansion_order) self._slice_pauli_list = slice_pauli_list
def construct_circuit( self, state_register=None, ancillary_register=None, auxiliary_register=None, measurement=False, ): """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 measurement (bool): Boolean flag to indicate if measurement should be included in the circuit. Returns: QuantumCircuit: the QuantumCircuit object for the constructed circuit Raises: RuntimeError: Multiple identity pauli terms are present ValueError: invalid mode """ # pylint: disable=invalid-name 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) # 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 = 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_inst = evolution_instruction( slice_pauli_list, -self._evo_time, self._num_time_slices, controlled=True, power=(2**i), shallow_slicing=self._shallow_circuit_concat) if self._shallow_circuit_concat: qc_evolutions = QuantumCircuit(q, a) qc_evolutions.append(qc_evolutions_inst, qargs=list(q) + [a[i]]) qc.data += qc_evolutions.data else: qc.append(qc_evolutions_inst, qargs=list(q) + [a[i]]) # global phase shift for the ancilla due to the identity pauli term qc.u1(self._evo_time * 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 if self._iqft.num_qubits != len( a): # check if QFT has the right size try: # try resizing self._iqft.num_qubits = len(a) except AttributeError: raise ValueError( 'The IQFT cannot be resized and does not have the ' 'required size of {}'.format(len(a))) if hasattr(self._iqft, 'do_swaps'): self._iqft.do_swaps = False qc.append(self._iqft.to_instruction(), a) if measurement: c_ancilla = ClassicalRegister(self._num_ancillae, name='ca') qc.add_register(c_ancilla) # real hardware can currently not handle operations after measurements, which might # happen if the circuit gets transpiled, hence we're adding a safeguard-barrier qc.barrier() qc.measure(a, c_ancilla) self._circuit = qc return self._circuit
def construct_circuit( self, state_register=None, ancillary_register=None, auxiliary_register=None, measurement=False, ): """ 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 measurement (bool): Boolean flag to indicate if measurement should be included in the circuit. 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) # 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 = 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_inst = evolution_instruction( slice_pauli_list, -self._evo_time, self._num_time_slices, controlled=True, power=(2**i), shallow_slicing=self._shallow_circuit_concat) if self._shallow_circuit_concat: qc_evolutions = QuantumCircuit(q, a) qc_evolutions.append(qc_evolutions_inst, qargs=[x for x in q] + [a[i]]) qc.data += qc_evolutions.data else: qc.append(qc_evolutions_inst, qargs=[x for x in q] + [a[i]]) # global phase shift for the ancilla due to the identity pauli term qc.u1(self._evo_time * 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(mode='circuit', qubits=a, circuit=qc, do_swaps=False) if measurement: c_ancilla = ClassicalRegister(self._num_ancillae, name='ca') qc.add_register(c_ancilla) # qc.barrier(a) qc.measure(a, c_ancilla) self._circuit = qc return self._circuit