Exemplo n.º 1
0
def get_qwc_group(H: QubitOperator):
    '''
    Return a list of qubit-wise commuting fragments of H
    '''
    # Preparing all terms in H into a list
    qubit_ops = []
    for pw, val in H.terms.items():
        qubit_ops.append(QubitOperator(term=pw, coefficient=val))
    n = len(qubit_ops)

    # Making commutation matrix
    comm_matrix = np.zeros((n, n))
    for i in range(n):
        for j in range(i + 1, n):
            comm_matrix[i, j] = qubit_wise_commuting(qubit_ops[i],
                                                     qubit_ops[j])

    # Compute commuting fragments
    comm_matrix = np.identity(n) + comm_matrix + comm_matrix.T
    colors = largest_first(1 - comm_matrix)

    # Collect commuting fragments into a list of QubitOperators
    qwc_list = []
    qwc_list_idx = 0
    for key, indices in colors.items():
        qwc_list.append(QubitOperator.zero())
        for idx in indices:
            qwc_list[qwc_list_idx] += qubit_ops[idx]
        qwc_list_idx += 1
    return qwc_list
Exemplo n.º 2
0
def get_commuting_group(H: QubitOperator):
    '''
    Get a dictionary of mutually commuting groups with terms in Hp
    '''
    n = get_number_qubit(H)

    pws = []
    pws_val = []
    for pw, val in H.terms.items():
        pws.append(pw)
        pws_val.append(val)

    binvecs = pauli2binvec(pws, n)
    tnum = len(binvecs)
    comm_matrix = np.zeros((tnum, tnum))

    for i in range(tnum):
        for j in range(i + 1, tnum):
            comm_matrix[i, j] = 1 - anticommute(binvecs[i], binvecs[j])

    comm_matrix = np.identity(tnum) + comm_matrix + comm_matrix.T
    colors = largest_first(1 - comm_matrix)

    dict = {}
    for key, indices in colors.items():
        dict[key] = QubitOperator.zero()
        for idx in indices:
            dict[key] += QubitOperator(term=pws[idx], coefficient=pws_val[idx])

    return dict
Exemplo n.º 3
0
    def map_qubits(self, qubit_map: dict):
        """

        E.G.  X(1)Y(2) --> X(3)Y(1) with qubit_map = {1:3, 2:1}

        Parameters
        ----------
        qubit_map
            a dictionary which maps old to new qubits

        Returns
        -------
        the Hamiltonian with mapped qubits

        """

        mapped_terms = {}

        for k, v in self.qubit_operator.terms.items():
            mk = tuple([(qubit_map[x[0]], x[1]) for x in k])
            mapped_terms[mk] = v

        mapped = QubitOperator.zero()
        mapped.terms = mapped_terms
        return QubitHamiltonian(qubit_operator=mapped)
Exemplo n.º 4
0
def remove_complex(H: QubitOperator, tiny=1e-8):
    '''
    Removing near-zero complex coefficient
    '''
    real_h = QubitOperator.zero()
    for term, val in H.terms.items():
        if np.imag(val) < tiny:
            val = np.real(val)
        real_h += QubitOperator(term=term, coefficient=val)
    return real_h
def benchmark_linear_qubit_operator(n_qubits, n_terms, processes=None):
    """Test speed with getting a linear operator from a Qubit Operator.

    Args:
        n_qubits: The number of qubits, implying the dimension of the operator
            is 2 ** n_qubits.
        n_terms: The number of terms in a qubit operator.
        processes: The number of processors to use.

    Returns:
        runtime_operator: The time it takes to get the linear operator.
        runtime_matvec: The time it takes to perform matrix multiplication.
    """
    # Generates Qubit Operator with specified number of terms.
    map_int_to_operator = {
        0: 'X',
        1: 'Y',
        2: 'Z',
    }
    qubit_operator = QubitOperator.zero()
    for _ in range(n_terms):
        tuples = []
        for i in range(n_qubits):
            operator = numpy.random.randint(4)
            # 3 is 'I', so just skip.
            if operator > 2:
                continue
            tuples.append((i, map_int_to_operator[operator]))
        if tuples:
            qubit_operator += QubitOperator(tuples, 1.00)

    # Gets an instance of (Parallel)LinearQubitOperator.
    start = time.time()
    if processes is None:
        linear_operator = LinearQubitOperator(qubit_operator, n_qubits)
    else:
        linear_operator = ParallelLinearQubitOperator(
            qubit_operator, n_qubits,
            LinearQubitOperatorOptions(processes=processes))

    end = time.time()
    runtime_operator = end - start

    vec = numpy.random.rand(2**n_qubits)
    # Performs matrix multiplication.
    start = time.time()
    _ = linear_operator * vec
    end = time.time()
    runtime_matvec = end - start
    return runtime_operator, runtime_matvec
Exemplo n.º 6
0
    def __init__(self, qubit_hamiltonian: typing.Union[QubitOperator, str, numbers.Number] = None):
        """
        Initialize from string or from a preexisting OpenFermion QubitOperator instance
        :param qubit_hamiltonian: string or openfermion.QubitOperator
        if string: Same conventions as openfermion
        if None: The Hamiltonian is initialized as identity operator
        if Number: initialized as scaled unit operator
        """
        if isinstance(qubit_hamiltonian, str):
            self._qubit_operator = self.from_string(string=qubit_hamiltonian)._qubit_operator
        elif qubit_hamiltonian is None:
            self._qubit_operator = QubitOperator.zero()
        elif isinstance(qubit_hamiltonian, numbers.Number):
            self._qubit_operator = qubit_hamiltonian * QubitOperator.identity()
        else:
            self._qubit_operator = qubit_hamiltonian

        assert (isinstance(self._qubit_operator, QubitOperator))