Exemple #1
0
def test_neg():
    op = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5)
    -op
    # out of place
    assert op.isclose(QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5))
    correct = -1.0 * op
    assert correct.isclose(-op)
def test_imul_qubit_op():
    op1 = QubitOperator(((0, 'Y'), (3, 'X'), (8, 'Z'), (11, 'X')), 3.j)
    op2 = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5)
    op1 *= op2
    correct_term = ((0, 'Y'), (1, 'X'), (3, 'Z'), (11, 'X'))
    assert len(op1.terms) == 1
    assert correct_term in op1.terms
Exemple #3
0
def test_str_multiple_terms():
    op = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5)
    op += QubitOperator(((1, 'Y'), (3, 'Y'), (8, 'Z')), 0.6)
    assert (str(op) == "0.5 X1 Y3 Z8 +\n0.6 Y1 Y3 Z8" or
            str(op) == "0.6 Y1 Y3 Z8 +\n0.5 X1 Y3 Z8")
    op2 = QubitOperator((), 2)
    assert str(op2) == "2 I"
Exemple #4
0
def test_imul_qubit_op_2():
    op3 = QubitOperator(((1, 'Y'), (0, 'X')), -1j)
    op4 = QubitOperator(((1, 'Y'), (0, 'X'), (2, 'Z')), -1.5)
    op3 *= op4
    op4 *= op3
    assert ((2, 'Z'), ) in op3.terms
    assert op3.terms[((2, 'Z'), )] == 1.5j
Exemple #5
0
def test_mul_multiple_terms():
    op = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5)
    op += QubitOperator(((1, 'Z'), (3, 'X'), (8, 'Z')), 1.2)
    op += QubitOperator(((1, 'Z'), (3, 'Y'), (9, 'Z')), 1.4j)
    res = op * op
    correct = QubitOperator((), 0.5**2 + 1.2**2 + 1.4j**2)
    correct += QubitOperator(((1, 'Y'), (3, 'Z')), 2j * 1j * 0.5 * 1.2)
    assert res == correct
Exemple #6
0
def test_mul_out_of_place():
    op1 = QubitOperator(((0, 'Y'), (3, 'X'), (8, 'Z'), (11, 'X')), 3.j)
    op2 = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5)
    op3 = op1 * op2
    correct_coefficient = 1.j * 3.0j * 0.5
    correct_term = ((0, 'Y'), (1, 'X'), (3, 'Z'), (11, 'X'))
    assert op1 == QubitOperator(((0, 'Y'), (3, 'X'), (8, 'Z'), (11, 'X')), 3.j)
    assert op2 == QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5)
    assert op3 == QubitOperator(correct_term, correct_coefficient)
Exemple #7
0
def test_imul_bidir():
    op_a = QubitOperator(((1, 'Y'), (0, 'X')), -1j)
    op_b = QubitOperator(((1, 'Y'), (0, 'X'), (2, 'Z')), -1.5)
    op_a *= op_b
    op_b *= op_a
    assert ((2, 'Z'), ) in op_a.terms
    assert op_a.terms[((2, 'Z'), )] == 1.5j
    assert ((0, 'X'), (1, 'Y')) in op_b.terms
    assert op_b.terms[((0, 'X'), (1, 'Y'))] == -2.25j
def test_get_operators():
    """Tests get_operators() with an operator with two terms."""
    operator_00 = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 1)
    operator_01 = QubitOperator(((2, 'Z'), (3, 'Y')), 1)
    sum_operator = operator_00 + operator_01

    operators = list(sum_operator.get_operators())
    assert operators in [[operator_00, operator_01],
                         [operator_01, operator_00]]
Exemple #9
0
def test_itruediv_and_idiv(divisor):
    op = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5)
    op2 = copy.deepcopy(op)
    original = copy.deepcopy(op)
    correct = op * (1. / divisor)
    op /= divisor
    op2.__idiv__(divisor)  # To test python 2 version as well
    assert op.isclose(correct)
    assert op2.isclose(correct)
    # Test if done in-place
    assert not op.isclose(original)
    assert not op2.isclose(original)
Exemple #10
0
def test_truediv_and_div(divisor):
    op = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5)
    op2 = copy.deepcopy(op)
    original = copy.deepcopy(op)
    res = op / divisor
    res2 = op2.__div__(divisor)  # To test python 2 version as well
    correct = op * (1. / divisor)
    assert res.isclose(correct)
    assert res2.isclose(correct)
    # Test if done out of place
    assert op.isclose(original)
    assert op2.isclose(original)
Exemple #11
0
def test_isub_different_term():
    term_a = ((1, 'X'), (3, 'Y'), (8, 'Z'))
    term_b = ((1, 'Z'), (3, 'Y'), (8, 'Z'))
    a = QubitOperator(term_a, 1.0)
    a -= QubitOperator(term_b, 0.5)
    assert len(a.terms) == 2
    assert a.terms[term_a] == pytest.approx(1.0)
    assert a.terms[term_b] == pytest.approx(-0.5)
    a -= QubitOperator(term_b, 0.5)
    assert len(a.terms) == 2
    assert a.terms[term_a] == pytest.approx(1.0)
    assert a.terms[term_b] == pytest.approx(-1.0)
Exemple #12
0
def test_sub():
    term_a = ((1, 'X'), (3, 'Y'), (8, 'Z'))
    term_b = ((1, 'Z'), (3, 'Y'), (8, 'Z'))
    a = QubitOperator(term_a, 1.0)
    b = QubitOperator(term_b, 0.5)
    res = a - b
    assert len(res.terms) == 2
    assert res.terms[term_a] == pytest.approx(1.0)
    assert res.terms[term_b] == pytest.approx(-0.5)
    res2 = b - a
    assert len(res2.terms) == 2
    assert res2.terms[term_a] == pytest.approx(-1.0)
    assert res2.terms[term_b] == pytest.approx(0.5)
Exemple #13
0
def test_isclose_different_terms():
    a = QubitOperator(((1, 'Y'),), -0.1j)
    b = QubitOperator(((1, 'X'),), -0.1j)
    assert a.isclose(b, rel_tol=1e-12, abs_tol=0.2)
    assert not a.isclose(b, rel_tol=1e-12, abs_tol=0.05)
    assert b.isclose(a, rel_tol=1e-12, abs_tol=0.2)
    assert not b.isclose(a, rel_tol=1e-12, abs_tol=0.05)
def test_integration_observable_to_vqe_cost(monkeypatch, mol_name, terms_ref,
                                            expected_cost, custom_wires, tol):
    r"""Test if `convert_observable()` in qchem integrates with `ExpvalCost()` in pennylane"""

    qOp = QubitOperator()
    if terms_ref is not None:
        monkeypatch.setattr(qOp, "terms", terms_ref)
    vqe_observable = qchem.convert_observable(qOp, custom_wires)

    num_qubits = len(vqe_observable.wires)
    assert vqe_observable.terms.__repr__()  # just to satisfy codecov

    if custom_wires is None:
        wires = num_qubits
    elif isinstance(custom_wires, dict):
        wires = qchem.structure._process_wires(custom_wires)
    else:
        wires = custom_wires[:num_qubits]
    dev = qml.device("default.qubit", wires=wires)

    # can replace the ansatz with more suitable ones later.
    def dummy_ansatz(phis, wires):
        for phi, w in zip(phis, wires):
            qml.RX(phi, wires=w)

    dummy_cost = qml.ExpvalCost(dummy_ansatz, vqe_observable, dev)
    params = [0.1 * i for i in range(num_qubits)]
    res = dummy_cost(params)

    assert np.allclose(res, expected_cost, **tol)
Exemple #15
0
def test_integration_hamiltonian_to_vqe_cost(monkeypatch, mol_name, terms_ref,
                                             expected_cost, tol):
    r"""Test if `convert_hamiltonian()` in qchem integrates with `VQECost()` in pennylane"""

    qOp = QubitOperator()
    if terms_ref is not None:
        monkeypatch.setattr(qOp, "terms", terms_ref)
    vqe_hamiltonian = qchem.convert_hamiltonian(qOp)

    # maybe make num_qubits a @property of the Hamiltonian class?
    num_qubits = max(
        1, len(set([w for op in vqe_hamiltonian.ops for w in op.wires])))

    dev = qml.device("default.qubit", wires=num_qubits)
    print(vqe_hamiltonian.terms)

    # can replace the ansatz with more suitable ones later.
    def dummy_ansatz(phis, wires):
        for phi, w in zip(phis, wires):
            qml.RX(phi, wires=w)

    dummy_cost = qml.VQECost(dummy_ansatz, vqe_hamiltonian, dev)
    params = [0.1 * i for i in range(num_qubits)]
    res = dummy_cost(params)

    assert np.allclose(res, expected_cost, **tol)
Exemple #16
0
def test_isclose_rel_tol():
    a = QubitOperator('X0', 1)
    b = QubitOperator('X0', 2)
    assert a.isclose(b, rel_tol=2.5, abs_tol=0.1)
    # Test symmetry
    assert a.isclose(b, rel_tol=1, abs_tol=0.1)
    assert b.isclose(a, rel_tol=1, abs_tol=0.1)
Exemple #17
0
def _terms_to_qubit_operator(coeffs, ops):
    r"""Converts a 2-tuple of complex coefficients and PennyLane operations to
    OpenFermion ``QubitOperator``.

    This function is the inverse of ``_qubit_operator_to_terms``.

    Args:
        coeffs (array[complex]):
            coefficients for each observable, same length as ops
        ops (Iterable[pennylane.operation.Observable]): List of PennyLane observables as
            Tensor products of Pauli observables

    Returns:
        QubitOperator: an instance of OpenFermion's ``QubitOperator``.
    """
    q_op = QubitOperator()
    for coeff, op in zip(coeffs, ops):

        # wire ids
        wires = [js[0] for js in op.wires]

        # Pauli axis names, note s[-1] expects only 'Pauli{X,Y,Z}'
        pauli_names = [s[-1] for s in op.name]

        extra_obsvbs = set(
            op.name) - {"PauliX", "PauliY", "PauliZ", "Identity"}
        if extra_obsvbs != set():
            raise ValueError(
                "Expected only PennyLane observables PauliX/Y/Z or Identity, "
                + "but also got {}.".format(extra_obsvbs))

        if op.name == ["Identity"] and wires == [0]:
            term_str = ""
        else:
            term_str = " ".join([
                "{}{}".format(pauli, wire)
                for pauli, wire in zip(pauli_names, wires)
            ])

        # This is how one makes QubitOperator in OpenFermion
        q_op += coeff * QubitOperator(term_str)

    return q_op
Exemple #18
0
def test_add():
    term_a = ((1, 'X'), (3, 'Y'), (8, 'Z'))
    term_b = ((1, 'Z'), (3, 'Y'), (8, 'Z'))
    a = QubitOperator(term_a, 1.0)
    b = QubitOperator(term_b, 0.5)
    res = a + b + b
    assert len(res.terms) == 2
    assert res.terms[term_a] == pytest.approx(1.0)
    assert res.terms[term_b] == pytest.approx(1.0)
    # Test out of place
    assert a.isclose(QubitOperator(term_a, 1.0))
    assert b.isclose(QubitOperator(term_b, 0.5))
Exemple #19
0
def test_renormalize():
    op = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 1)
    op += QubitOperator(((2, 'Z'), (3, 'Y')), 1)
    op.renormalize()
    for term in op.terms:
        assert op.terms[term] == pytest.approx(1 / numpy.sqrt(2.))
    assert op.induced_norm(2) == pytest.approx(1.)
Exemple #20
0
def test_observable(me_table, init_term, mapping, terms_exp, monkeypatch):
    r"""Tests the correctness of the 'observable' function used to build many-body observables.

    The parametrized inputs `terms_exp` are `.terms` attribute of the corresponding
    `QubitOperator. The equality checking is implemented in the `qchem` module itself
    as it could be something useful to the users as well.
    """

    res_obs = qchem.observable(me_table, init_term=init_term, mapping=mapping)

    qubit_op = QubitOperator()
    monkeypatch.setattr(qubit_op, "terms", terms_exp)

    assert qchem._qubit_operators_equivalent(qubit_op, res_obs)
Exemple #21
0
def test_particle_number_observable(n_orbitals, mapping, terms_exp, monkeypatch):
    r"""Tests the correctness of the particle number observable :math:`\hat{N}` generated
    by the ``'particle_number'`` function.

    The parametrized inputs are `.terms` attribute of the particle number `QubitOperator`.
    The equality checking is implemented in the `qchem` module itself as it could be
    something useful to the users as well.
    """

    N = qchem.particle_number(n_orbitals, mapping=mapping)

    particle_number_qubit_op = QubitOperator()
    monkeypatch.setattr(particle_number_qubit_op, "terms", terms_exp)

    assert qchem._qubit_operators_equivalent(particle_number_qubit_op, N)
Exemple #22
0
def test_spin_z(orbitals, mapping, terms_exp, monkeypatch):
    r"""Tests the correctness of the :math:`\hat{S}_z` observable built by the
    function `'spin_z'`.

    The parametrized inputs are `.terms` attribute of the `QubitOperator. The equality
    checking is implemented in the `qchem` module itself as it could be something
    useful to the users as well.
    """

    Sz = qchem.spin_z(orbitals, mapping=mapping)

    Sz_qubit_op = QubitOperator()
    monkeypatch.setattr(Sz_qubit_op, "terms", terms_exp)

    assert qchem._qubit_operators_equivalent(Sz_qubit_op, Sz)
Exemple #23
0
def test_hamiltonian_conversion(mol_name, terms_ref, monkeypatch):
    r"""Test the correctness of the QubitOperator Hamiltonian conversion from
    OpenFermion to Pennylane.

    The parametrized inputs are `.terms` attribute of the output `QubitOperator`s based on
    the same set of test molecules as `test_gen_hamiltonian_pauli_basis`.

    The equality checking is implemented in the `qchem` module itself as it could be
    something useful to the users as well.
    """
    qOp = QubitOperator()
    if terms_ref is not None:
        monkeypatch.setattr(qOp, "terms", terms_ref)

    vqe_hamiltonian = qchem.convert_hamiltonian(qOp)

    assert qchem._qubit_operators_equivalent(qOp, vqe_hamiltonian)
def test_build_s2_observable(mol_name, n_act_elect, n_act_orb, mapping, terms_exp, monkeypatch):
    r"""Tests the correctness of the built total-spin observable.

    The parametrized inputs are `.terms` attribute of the total spin `QubitOperator.
    The equality checking is implemented in the `qchem` module itself as it could be
    something useful to the users as well.
    """

    s2_me_table, init_term = qchem.get_spin2_matrix_elements(
        mol_name, ref_dir, n_active_electrons=n_act_elect, n_active_orbitals=n_act_orb
    )

    s2_obs = qchem.observable(s2_me_table, init_term=init_term, mapping=mapping)

    s2_qubit_op = QubitOperator()
    monkeypatch.setattr(s2_qubit_op, "terms", terms_exp)

    assert qchem._qubit_operators_equivalent(s2_qubit_op, s2_obs)
def test_observable_conversion(mol_name, terms_ref, custom_wires, monkeypatch):
    r"""Test the correctness of the QubitOperator observable conversion from
    OpenFermion to Pennylane.

    The parametrized inputs are `.terms` attribute of the output `QubitOperator`s based on
    the same set of test molecules as `test_gen_hamiltonian_pauli_basis`.

    The equality checking is implemented in the `qchem` module itself as it could be
    something useful to the users as well.
    """
    qOp = QubitOperator()
    if terms_ref is not None:
        monkeypatch.setattr(qOp, "terms", terms_ref)

    vqe_observable = qchem.convert_observable(qOp, custom_wires)

    if isinstance(custom_wires, dict):
        custom_wires = {v: k for k, v in custom_wires.items()}

    assert qchem._qubit_operators_equivalent(qOp, vqe_observable, custom_wires)
Exemple #26
0
def test_mul_by_scalarzero():
    op = QubitOperator(((1, 'Y'), (0, 'X')), -1j) * 0
    assert ((0, 'X'), (1, 'Y')) in op.terms
    assert op.terms[((0, 'X'), (1, 'Y'))] == pytest.approx(0.0)
Exemple #27
0
def test_imul_bad_multiplier():
    op = QubitOperator(((1, 'Y'), (0, 'X')), -1j)
    with pytest.raises(TypeError):
        op *= "1"
Exemple #28
0
def test_renormalize_error():
    op = QubitOperator()
    with pytest.raises(ZeroDivisionError):
        op.renormalize()
Exemple #29
0
def test_imul_inplace():
    qubit_op = QubitOperator("X1")
    prev_id = id(qubit_op)
    qubit_op *= 3.
    assert id(qubit_op) == prev_id
Exemple #30
0
def test_imul_scalar(multiplier):
    loc_op = ((1, 'X'), (2, 'Y'))
    qubit_op = QubitOperator(loc_op)
    qubit_op *= multiplier
    assert qubit_op.terms[loc_op] == pytest.approx(multiplier)