Exemple #1
0
    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
Exemple #2
0
    def __init__(self,
                 operator,
                 state_in,
                 iqft,
                 num_time_slices=1,
                 num_ancillae=1,
                 paulis_grouping='random',
                 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
            paulis_grouping (str): the pauli term grouping mode
            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 = copy.deepcopy(operator)
        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']

        self._phase_estimation_component = PhaseEstimation(
            self._operator,
            state_in,
            iqft,
            num_time_slices=num_time_slices,
            num_ancillae=num_ancillae,
            paulis_grouping=paulis_grouping,
            expansion_mode=expansion_mode,
            expansion_order=expansion_order,
            shallow_circuit_concat=shallow_circuit_concat)
        self._binary_fractions = [1 / 2**p for p in range(1, num_ancillae + 1)]
Exemple #3
0
    def _setup_qpe(self):
        self._operator._check_representation('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']

        # 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(p[1].v == 0) and np.all(p[1].w == 0):
                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]

        self._construct_qpe_evolution()
        logger.info('QPE circuit qasm length is roughly {}.'.format(
            len(self._circuit.qasm().split('\n'))))
Exemple #4
0
    def __init__(self,
                 operator,
                 state_in,
                 iqft,
                 num_time_slices=1,
                 num_ancillae=1,
                 paulis_grouping='random',
                 expansion_mode='trotter',
                 expansion_order=1,
                 shallow_circuit_concat=False):
        self.validate(locals())
        super().__init__()

        self._ret = {}
        self._operator = copy.deepcopy(operator)
        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']

        self._phase_estimation_component = PhaseEstimation(
            self._operator,
            state_in,
            iqft,
            num_time_slices=num_time_slices,
            num_ancillae=num_ancillae,
            paulis_grouping=paulis_grouping,
            expansion_mode=expansion_mode,
            expansion_order=expansion_order,
            shallow_circuit_concat=shallow_circuit_concat)
        self._binary_fractions = [1 / 2**p for p in range(1, num_ancillae + 1)]
Exemple #5
0
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]
Exemple #6
0
    def _compute_energy(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']

        # check for identify paulis to get its coef for applying global phase shift on ancilla 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]

        self._ret['phase'] = self._estimate_phase_iteratively()
        self._ret['top_measurement_decimal'] = sum([
            t[0] * t[1] for t in
            zip([1 / 2**p for p in range(1, self._num_iterations + 1)],
                [int(n) for n in self._ret['top_measurement_label']])
        ])
        self._ret['energy'] = self._ret['phase'] / self._ret[
            'stretch'] - self._ret['translation']