def _setup(self): self._ret['translation'] = sum( [abs(p[0]) for p in self._operator.get_flat_pauli_list()]) 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 self._pauli_list = self._operator.get_flat_pauli_list() # 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 = Operator._suzuki_expansion_slice_pauli_list( self._pauli_list, 1, self._expansion_order) self._slice_pauli_list = slice_pauli_list
def __init__(self, operator, state_in, iqft, num_time_slices=1, num_ancillae=1, expansion_mode='trotter', expansion_order=1, shallow_circuit_concat=False): """ Constructor. Args: operator (Operator): the hamiltonian Operator object state_in (InitialState): the InitialState pluggable component representing the initial quantum state iqft (IQFT): the Inverse Quantum Fourier Transform pluggable component num_time_slices (int): the number of time slices num_ancillae (int): the number of ancillary qubits to use for the measurement expansion_mode (str): the expansion mode (trotter|suzuki) expansion_order (int): the suzuki expansion order shallow_circuit_concat (bool): indicate whether to use shallow (cheap) mode for circuit concatenation """ self.validate(locals()) super().__init__() self._num_ancillae = num_ancillae self._ret = {} self._operator = deepcopy(operator) self._ret['translation'] = sum( [abs(p[0]) for p in self._operator.get_flat_pauli_list()]) 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 self._pauli_list = self._operator.get_flat_pauli_list() # stretch the operator for p in self._pauli_list: p[0] = p[0] * self._ret['stretch'] self._phase_estimation_circuit = PhaseEstimationCircuit( operator=self._operator, state_in=state_in, iqft=iqft, num_time_slices=num_time_slices, num_ancillae=num_ancillae, expansion_mode=expansion_mode, expansion_order=expansion_order, shallow_circuit_concat=shallow_circuit_concat, pauli_list=self._pauli_list) self._binary_fractions = [1 / 2**p for p in range(1, num_ancillae + 1)]
def limit_paulis(mat, n=5, sparsity=None): """ Limits the number of Pauli basis matrices of a hermitian matrix to the n highest magnitude ones. Args: mat (np.ndarray): Input matrix n (int): number of surviving Pauli matrices (default=5) sparsity (float < 1): sparsity of matrix Returns: scipy.sparse.csr_matrix """ from qiskit.aqua import Operator # Bringing matrix into form 2**Nx2**N _l = mat.shape[0] if np.log2(_l) % 1 != 0: k = int(2**np.ceil(np.log2(_l))) m = np.zeros([k, k], dtype=np.complex128) m[:_l, :_l] = mat m[_l:, _l:] = np.identity(k - _l) mat = m # Getting Pauli matrices op = Operator(matrix=mat) op._check_representation("paulis") op._simplify_paulis() paulis = sorted(op.paulis, key=lambda x: abs(x[0]), reverse=True) g = 2**op.num_qubits mat = scipy.sparse.csr_matrix(([], ([], [])), shape=(g, g), dtype=np.complex128) # Truncation if sparsity is None: for pa in paulis[:n]: mat += pa[0] * pa[1].to_spmatrix() else: idx = 0 while mat[:_l, :_l].nnz / _l**2 < sparsity: mat += paulis[idx][0] * paulis[idx][1].to_spmatrix() idx += 1 n = idx mat = mat.toarray() return mat[:_l, :_l]