Beispiel #1
0
 def test_reduce(self):
     self.assertEqual(
         self.reduced_qubit_op,
         openfermion.QubitOperator("X0 Z1", self.a) +
         openfermion.QubitOperator("Y2", self.b) +
         openfermion.QubitOperator("Z0 X1 X2", self.c) +
         openfermion.QubitOperator("Y3", self.d))
Beispiel #2
0
 def test_reduce_inactive_qubits(self):
     self.assertEqual(
         self.inactive_qubits_reduced_qubit_op,
         openfermion.QubitOperator("X0 Y1 Z2 X4", self.a) +
         openfermion.QubitOperator("Y1 Y3 X4", self.b) +
         openfermion.QubitOperator("Z0 Y1 X2 X3 X4", self.c) +
         openfermion.QubitOperator("Y1 X4 Y5", self.d))
Beispiel #3
0
 def test_reduce_stationary_qubits(self):
     self.assertEqual(
         self.stationary_qubits_inactivated_qubit_op,
         openfermion.QubitOperator("X0 Z2", self.a) +
         openfermion.QubitOperator("Y3", self.b) +
         openfermion.QubitOperator("Z0 X2 X3", self.c) +
         openfermion.QubitOperator("Y7", self.d))
Beispiel #4
0
    def test_eigvalsh(self):
        a, b, c, d, e = 1, 2, 3, 4, 5
        qubit_op = (openfermion.QubitOperator("X0 Y1 Z2", a) +
                    openfermion.QubitOperator("Y1 X2", b) +
                    openfermion.QubitOperator("Y1 X4", c) +
                    openfermion.QubitOperator("Z0 Y1 X2", d) +
                    openfermion.QubitOperator("Z0 Y1 Z4", e))

        inactive_qubits_reduced_qubit_op, _ = \
            reduce_inactive_qubits(qubit_op)
        stationary_qubits_inactivated_qubit_op, _ = \
            inactivate_stationary_qubits(qubit_op)

        reduced_qubit_op, n_stationary, n_inactive = reduce(qubit_op)

        # # n_stationary==1, n_inactive==1 in this case
        # self.assertEqual(n_stationary, 1)
        # self.assertEqual(n_inactive, 1)

        # e.g.
        # [-11,    -11,    -11,    -11,
        #   -3,     -3,     -3,     -3,
        #    3,      3,      3,      3,
        #   11,     11,     11,     11]
        eig = np.linalg.eigvalsh(
            openfermion.get_sparse_operator(qubit_op).toarray())

        # e.g.
        # [-11,    -11,
        #   -3,     -3,
        #    3,      3,
        #   11,     11]
        eig_inactive_qubits_reduced = np.linalg.eigvalsh(
            openfermion.get_sparse_operator(
                inactive_qubits_reduced_qubit_op).toarray())

        # Note that `inactivate_stationary_qubits` won't reduce the dimension of
        # the multi-qubit space of the qubit operator.
        eig_stationary_qubits_inactivated = np.linalg.eigvalsh(
            openfermion.get_sparse_operator(
                stationary_qubits_inactivated_qubit_op).toarray())

        # e.g.
        # [-11,
        #   -3,
        #    3,
        #   11]
        eig_reduced = np.linalg.eigvalsh(
            openfermion.get_sparse_operator(reduced_qubit_op).toarray())

        self.assertTrue(
            np.allclose(eig,
                        np.repeat(eig_inactive_qubits_reduced, 2**n_inactive)))
        self.assertTrue(
            np.allclose(eig,
                        np.repeat(eig_reduced,
                                  2**(n_stationary + n_inactive))))
Beispiel #5
0
 def test_group(self):
     grouped = group(self.qubit_op, by_qubit_indices=(3, 5))
     self.assertEqual(
         grouped, {
             ((3, "I"), (5, "X")):
             openfermion.QubitOperator("X0 Y1 Z2    X5   ", self.a) +
             openfermion.QubitOperator("   Y1       X5 Y7", self.d),
             ((3, "Y"), (5, "X")):
             openfermion.QubitOperator("   Y1    Y3 X5   ", self.b),
             ((3, "X"), (5, "X")):
             openfermion.QubitOperator("Z0 Y1 X2 X3 X5   ", self.c)
         })
Beispiel #6
0
 def setUp(self) -> None:
     self.a, self.b, self.c, self.d = np.random.rand(4)
     self.qubit_op = (
         openfermion.QubitOperator("X0 Y1 Z2    X5   ", self.a) +
         openfermion.QubitOperator("   Y1    Y3 X5   ", self.b) +
         openfermion.QubitOperator("Z0 Y1 X2 X3 X5   ", self.c) +
         openfermion.QubitOperator("   Y1       X5 Y7", self.d))
     self.inactive_qubits_reduced_qubit_op, _ = \
         reduce_inactive_qubits(self.qubit_op)
     self.stationary_qubits_inactivated_qubit_op, _ = \
         inactivate_stationary_qubits(self.qubit_op)
     self.reduced_qubit_op, _, _ = reduce(self.qubit_op)
Beispiel #7
0
def inactivate_stationary_qubits(
    qubit_operator: openfermion.QubitOperator
) -> typing.Tuple[openfermion.QubitOperator, int]:
    """
    Set the stationary qubits in a qubit operator to be "inactive".

    Here, "stationary" means the qubit is ONLY acted by ONE kind of operators
    in {"X", "Y", "Z", "I"}, which differs from the meaning of "generally
    stationary" in `block_reduce`.

    "Inactive" means the qubit is not acted by any effective Pauli operators
    (i.e. only acted on by the identity operator). The definition here is same
    as in `reduce_inactive_qubits`.

    See also:
        `block_reduce`
        `reduce_inactive_qubits`

    :param qubit_operator:
        The qubit operator to be processed.

    :return:
        The processed qubit operator, and the number of inactivated stationary
        qubits.

    Example:

    >>> op = (openfermion.QubitOperator("X0 Y1", 0.1) +
    ...       openfermion.QubitOperator("Z0 Y1 X3", 0.2))
    >>> inactivate_stationary_qubits(op)
    (0.1 [X0] +
    0.2 [Z0 X3], 1)

    """
    common_ops = typing.cast(set,
                             None)  # type: typing.Set[typing.Tuple[int, str]]
    for term in qubit_operator.terms.keys():
        if common_ops is not None:
            common_ops.intersection_update(set(term))
        else:
            common_ops = set(term)
    num_stationary_qubits = len(common_ops)

    reduced_qubit_op = openfermion.QubitOperator()
    for term, coefficient in qubit_operator.terms.items():
        reduced_term = tuple(pauli_on_qubit for pauli_on_qubit in term
                             if pauli_on_qubit not in common_ops)
        _op = openfermion.QubitOperator()
        _op.terms[reduced_term] = coefficient
        reduced_qubit_op += _op

    return reduced_qubit_op, num_stationary_qubits
Beispiel #8
0
    def test_nonzero_op_constant(self):
        # matrix_a form:
        # [[ 0.96,  0.   ]
        #  [ 0.  , -0.49 ]]
        # qubit_op.constant == 0.235
        qubit_op = (openfermion.QubitOperator("", 0.235) +
                    openfermion.QubitOperator("Z0", 0.725))

        self.assertEqual(reduce_inactive_qubits(qubit_op), (qubit_op, 0))

        self.assertEqual(inactivate_stationary_qubits(qubit_op), (qubit_op, 0))

        self.assertEqual(reduce(qubit_op), (qubit_op, 0, 0))
Beispiel #9
0
def break_operators_into_subsets(qubit_operator):
    """Break a qubit operator into subsets, where the terms in each subset all mutually commute."""

    qop_zero = openfermion.QubitOperator('', 0)
    subsets = []
    for term in qubit_operator:
        #print('term ',term)
        new_subset = True
        for subset in subsets:
            #print('subset ',subset)
            is_commutable_with_all_term_in_subset = True
            for term_in_subset in subset:
                #print('term_in_subset ',term_in_subset)
                if openfermion.utils.commutator(term,
                                                term_in_subset) != qop_zero:
                    is_commutable_with_all_term_in_subset = False
                    #print(term,'and',term_in_subset,'dont commute.')
                    break

            if is_commutable_with_all_term_in_subset:
                subset += term
                new_subset = False
                break

        if new_subset:
            subsets.append(term)

    return subsets
Beispiel #10
0
def system_to_QubitOperator(sys):
    '''
    Export a spin lattice hamiltonian built in kwant to openfermion.

    Parameters
    ----------
    sys: kwant.system.FiniteSystem or kwant.system.InfiniteSystem

    Returns
    ----------
    ham: openfermion.QubitOperator
        The hamiltonian of sys as an openfermion object.
    '''

    if not isinstance(sys, kwant.system.System):
        raise TypeError(f'Expecting an instance of System, got {type(sys)}.')

    ham = openfermion.QubitOperator()

    #on site terms
    for lat_ix in sys.id_by_site.values():
        val = sys.hamiltonian(lat_ix, lat_ix)
        ham += _single_term_to_QubitOperator(val, lat_ix, lat_ix)

    #interaction terms
    for edge in range(sys.graph.num_edges):
        lat_ix1 = sys.graph.head(edge)
        lat_ix2 = sys.graph.tail(edge)
        val = sys.hamiltonian(lat_ix1, lat_ix2) / 2
        ham += _single_term_to_QubitOperator(val, lat_ix1, lat_ix2)

    return ham
Beispiel #11
0
def group(qubit_operator: openfermion.QubitOperator,
          by_qubit_indices: typing.Iterable[int]):
    grouped = {}
    for term, coefficient in qubit_operator.terms.items():
        paulis_at_indices = {
            qubit_index: pauli
            for qubit_index, pauli in term if qubit_index in by_qubit_indices
        }

        for i in by_qubit_indices:
            if i not in paulis_at_indices:
                paulis_at_indices[i] = "I"

        paulis_at_indices = sorted(
            ((qubit_index, pauli)
             for qubit_index, pauli in paulis_at_indices.items()),
            key=lambda item: item[0])
        paulis_at_indices = tuple(paulis_at_indices)

        op = openfermion.QubitOperator()
        op.terms[term] = coefficient

        if paulis_at_indices not in grouped:
            grouped[paulis_at_indices] = op
        else:
            grouped[paulis_at_indices] += op

    return grouped
Beispiel #12
0
def break_operators_into_subsets_dummy(qubit_operator):
    """Break a qubit operator into subsets, where the terms in each subset all mutually commute."""

    qop_zero = openfermion.QubitOperator('', 0)
    subsets = []
    for term in qubit_operator:
        subsets.append(term)

    return subsets
Beispiel #13
0
    def test_exponent_statevectors(self):

        qubit_operators = []
        # only symetric qubit operators will works, because qiskit and openfermion use different qubit orderings
        qubit_operators.append(openfermion.QubitOperator('Z0 Y1 Z2'))
        qubit_operators.append(openfermion.QubitOperator('X0 Y1 X2'))
        qubit_operators.append(openfermion.QubitOperator('Y0 X1 X2 Y3'))

        for qubit_operator in qubit_operators:

            qubit_operator_tuple = list(qubit_operator.terms.keys())[0]
            n_qubits = len(qubit_operator_tuple)

            for angle in range(10):
                angle = 2 * numpy.pi / 10

                # <<< create a statevector using QiskitSimulation.get_exponent_qasm >>>
                qasm = QasmUtils.qasm_header(n_qubits)
                qasm += QasmUtils.exponent_qasm(qubit_operator_tuple, angle)
                qiskit_statevector = QiskitSimBackend.statevector_from_qasm(
                    qasm)
                qiskit_statevector = qiskit_statevector * numpy.exp(
                    1j * angle)  # correct for a global phase
                qiskit_statevector = qiskit_statevector.round(
                    2)  # round for the purpose of testing

                # <<< create a statevector using MatrixCalculation.get_qubit_operator_exponent_matrix >>>
                exp_matrix = MatrixUtils.get_excitation_matrix(
                    1j * qubit_operator, n_qubits, angle).todense()
                # prepare initial statevector corresponding to state |0>
                array_statevector = numpy.zeros(2**n_qubits)
                array_statevector[0] = 1
                # update statevector
                array_statevector = numpy.array(
                    exp_matrix.dot(array_statevector))[0].round(
                        2)  # round for the purpose of testing

                # <<<< compare both state vectors >>>>
                self.assertEqual(len(array_statevector),
                                 len(qiskit_statevector))
                # check the components of the two vectors are equal
                for i in range(len(qiskit_statevector)):
                    self.assertEqual(qiskit_statevector[i],
                                     array_statevector[i])
Beispiel #14
0
 def test_block_reduce(self):
     const = 1
     qubit_op = (openfermion.QubitOperator("", const) +
                 openfermion.QubitOperator("X0 Y1 Z2    X5    X8", self.a) +
                 openfermion.QubitOperator("   Y1    Y3 X5    X8", self.b) +
                 openfermion.QubitOperator("Z0 Y1 X2 X3 X5 Y7 X8", self.c) +
                 openfermion.QubitOperator("   Y1       X5 Y7   ", self.d))
     self.assertEqual(
         block_reduce(qubit_op), {
             ((1, "I"), (4, "I"), (5, "I"), (6, "I"), (7, "I"), (8, "I")):
             openfermion.QubitOperator("", const),
             ((1, "Y"), (4, "I"), (5, "X"), (6, "I"), (7, "I"), (8, "X")):
             openfermion.QubitOperator("X0 Z1   ", self.a) +
             openfermion.QubitOperator("      Y2", self.b),
             ((1, "Y"), (4, "I"), (5, "X"), (6, "I"), (7, "Y"), (8, "X")):
             openfermion.QubitOperator("Z0 X1 X2", self.c),
             ((1, "Y"), (4, "I"), (5, "X"), (6, "I"), (7, "Y"), (8, "I")):
             openfermion.QubitOperator("", self.d)
         })
Beispiel #15
0
    def test_pauli_gates_circuit_statevector(self):

        qubit_operator = openfermion.QubitOperator('X0 Y1')
        qasm_circuit = QasmUtils.qasm_header(2)
        qasm_circuit += QasmUtils.pauli_word_qasm(qubit_operator)
        statevector = QiskitSimBackend.statevector_from_qasm(qasm_circuit)

        expected_statevector = numpy.array([0, 0, 0, 1j])

        self.assertEqual(len(expected_statevector), len(statevector))

        for i in range(len(statevector)):
            self.assertEqual(statevector[i], expected_statevector[i])
Beispiel #16
0
def _single_term_to_QubitOperator(val, ix1, ix2):
    '''
    Export single term of the hamiltonian to openfermion.
    Single term means either an onsite/single spin term at lattice site ix1 = ix2
    - such as Zeeman hamiltonian - or an interaction between two spins at sites ix1 and ix2.

    Parameters
    ----------
    val: 2x2 array for ix1 = ix2 or 4x4 array for ix1 =/= ix2
    ix1, ix2: int
        lattice position indices.
    Returns
    ----------
    op: openfermion.QubitOperator
    '''

    try:
        dims = val.shape
    except:
        raise ValueError(f'Expected a matrix, got {type(val)}.')

    pauli_coefs = to_pauli_basis(val)

    op = openfermion.QubitOperator()

    #On site terms
    if ix1 == ix2:
        assert dims == (2, 2), f'Onsite terms must be 2x2 matrices, got {dims}'
        for name, coef in zip(pauli_names, pauli_coefs):
            if name == '1':
                op += openfermion.QubitOperator('', coef)
            else:
                op += openfermion.QubitOperator(name + str(ix1), coef)
        return op

    #Interaction terms
    assert dims == (4, 4), f'Onsite terms must be 4x4 matrices, got {dims}'
    for name, coef in zip(pauli_names4, pauli_coefs):
        if name == ('1', '1'):
            op += openfermion.QubitOperator('', coef)
        elif name[0] == '1':
            op += openfermion.QubitOperator(name[1] + str(ix2), coef)
        elif name[1] == '1':
            op += openfermion.QubitOperator(name[0] + str(ix1), coef)
        else:
            op += openfermion.QubitOperator(
                name[0] + str(ix1) + ' ' + name[1] + str(ix2), coef)
    return op
def test_hamiltonian_variational_study_init_qubit_operator():

    ansatz = SwapNetworkTrotterAnsatz(test_hamiltonian)
    study = HamiltonianVariationalStudy('study', ansatz,
                                        openfermion.QubitOperator((0, 'X')))
    assert study.hamiltonian == openfermion.QubitOperator((0, 'X'))
def test_single_interaction_term():
    assert sl._single_term_to_QubitOperator(
        5 * np.kron(sl.sigma_x, sl.sigma_z), 0,
        1) == openfermion.QubitOperator('X0 Z1', 5)
Beispiel #19
0
def cleanup(qop, thresh=1e-12):
    retval = openfermion.QubitOperator()
    terms = retval.terms
    for k, v in qop.terms.items():
        if abs(v) > thresh: terms[k] = v
    return retval
Beispiel #20
0
def reduce_inactive_qubits(
    qubit_operator: openfermion.QubitOperator,
    inactive_qubits: typing.Optional[typing.Iterable[int]] = None
) -> typing.Tuple[openfermion.QubitOperator, int]:
    """
    Reduce the inactive qubits in a qubit operator.

    :param qubit_operator:
        The qubit operator to be simplified (i.e. reduced).
    :param inactive_qubits:
        The qubits to be reduced from the qubit operator.

        If given out explicitly, the qubits in `inactive_qubits` will all be
        removed from the qubit operator (no matter whether it is really
        "inactive").

        If left to be default, the inactive qubits to be removed will be
        automatically determined. Here, "inactive" means that there are not
        any effective Pauli operators ("X", "Y", "Z") acting on the qubits in
        `qubit_operator`.

    :return:
        The reduced qubit operator, and the number of reduced qubits.

    Example:

    >>> op = (openfermion.QubitOperator("X0 Y1", 0.1) +
    ...       openfermion.QubitOperator("Z0 Y1 X3", 0.2))
    >>> reduce_inactive_qubits(op)
    (0.1 [X0 Y1] +
    0.2 [Z0 Y1 X2], 1)
    >>> reduce_inactive_qubits(op, (0, 2))
    (0.1 [Y0] +
    0.2 [Y0 X1], 2)
    >>> reduce_inactive_qubits(op, (0,))
    (0.1 [Y0] +
    0.2 [Y0 X2], 1)

    """
    if inactive_qubits is None:
        active_qubits = set()
        for term in qubit_operator.terms.keys():
            for qubit_index, pauli in term:
                active_qubits.add(qubit_index)
        active_qubits = sorted(active_qubits)
    else:
        active_qubits = sorted(
            q for q in range(0, openfermion.count_qubits(qubit_operator))
            if q not in inactive_qubits)

    reduced_qubit_op = openfermion.QubitOperator()
    for term, coefficient in qubit_operator.terms.items():
        reduced_term = tuple((active_qubits.index(qubit_index), pauli)
                             for qubit_index, pauli in term
                             if qubit_index in active_qubits)
        _op = openfermion.QubitOperator()
        _op.terms[reduced_term] = coefficient
        reduced_qubit_op += _op

    if inactive_qubits is None:  # if in the default case:
        assert len(active_qubits) == openfermion.count_qubits(reduced_qubit_op)
    else:
        # For cases like:
        #
        #     reduce_inactive_qubits(
        #         openfermion.QubitOperator("Z0 Y1 X3", 0.2),
        #         (3,)
        #     )
        #
        # active_qubits == (0, 1, 2), but the reduced operator is
        #
        #     openfermion.QubitOperator("Z0 Y1", 0.2)
        #
        # counting whose qubits will give out 2 instead of 3.
        pass

    num_reduced_qubits = \
        openfermion.count_qubits(qubit_operator) - len(active_qubits)

    return reduced_qubit_op, num_reduced_qubits
    #    print(k1,k2,v)
    if k1 == k2:
        b_ij[nvar][nvar] = v
        key_i.append(k1)
        nvar += 1
for (k1, k2), v in Q.items():
    if k1 != k2:
        for i in range(nvar):
            for j in range(nvar):
                if k1 == key_i[i] and k2 == key_i[j]:
                    if i < j:
                        b_ij[i][j] = v
                    else:
                        b_ij[j][i] = v

hamil = of.QubitOperator()

J_ij = np.zeros((nvar, nvar))
h_i = np.zeros(nvar)
for i in range(nvar):
    for j in range(nvar):
        if i >= j:
            continue
        J_ij[i][j] = b_ij[i][j]
        if J_ij[i][j] == 0:
            continue
        hamil += of.QubitOperator(((i, 'Z'), (j, 'Z')), J_ij[i][j])

for i in range(nvar):
    bias = 0
    for k in range(nvar):
Beispiel #22
0
def Hamiltonian(u,v,t):
    '''
    Function that returns the hamiltonian with the given parameters by using openfermion.QubitOperators.

    Parameters
    ----------
    u : float
        One the parameters in the Hamiltonian, see report for description.
    v : float
        One the parameters in the Hamiltonian, see report for description.
    t : float
        One the parameters in the Hamiltonian, see report for description.

    Returns
    -------
    hamiltonian : Sum of openfermion.QubitOperators
        The hamiltonian as defined in the report with the parameters as provided.

    '''
    hamiltonian =  -2 * t *       of.QubitOperator('X0') 
    hamiltonian += -2 * t *       of.QubitOperator('X1') 
    hamiltonian += -2 * t *       of.QubitOperator('X2') 
    hamiltonian += -2 * t *       of.QubitOperator('X3') 
    hamiltonian += v/16   *       of.QubitOperator('Z0 Z3') 
    hamiltonian += v/16   *       of.QubitOperator('Z1 Z2') 
    hamiltonian += v/16   *       of.QubitOperator('Z0 Z1 Z2') 
    hamiltonian += v/16   *       of.QubitOperator('Z0 Z2 Z3') 
    hamiltonian += v/16   *       of.QubitOperator('Z0 Z1 Z3') 
    hamiltonian += v/16   *       of.QubitOperator('Z1 Z2 Z3') 
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z0 Z1') 
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z2 Z3') 
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z0 Z2')  
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z1 Z3') 
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z0')  
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z1') 
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z2') 
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z3') 
    hamiltonian += (v + 4*u)/16 * of.QubitOperator('Z0 Z1 Z2 Z3') 
    
    return hamiltonian
def test_hamiltonian_objective_init_qubit_operator():

    obj = HamiltonianObjective(openfermion.QubitOperator((0, 'X')))
    assert obj.hamiltonian == openfermion.QubitOperator((0, 'X'))
def test_single_onsite_term():
    assert sl._single_term_to_QubitOperator(
        sl.sigma_x, 0, 0) == openfermion.QubitOperator('X0')