Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v0.40.0 QA] PL Improvements #6773

Merged
merged 11 commits into from
Jan 9, 2025
8 changes: 4 additions & 4 deletions doc/code/qml_fermi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ the orbital it acts on. The values of the dictionary are one of ``'+'`` or ``'-'
denote creation and annihilation operators, respectively. The operator
:math:`a^{\dagger}_0 a_3 a^{\dagger}_1` can then be constructed with

>>> qml.fermi.FermiWord({(0, 0): '+', (1, 3): '-', (2, 1): '+'})
>>> qml.FermiWord({(0, 0): '+', (1, 3): '-', (2, 1): '+'})
a⁺(0) a(3) a⁺(1)

A Fermi sentence can be constructed directly by passing a dictionary of Fermi words and their
corresponding coefficients to the :class:`~pennylane.fermi.FermiSentence` class. For instance, the
Fermi sentence :math:`1.2 a^{\dagger}_0 a_0 + 2.3 a^{\dagger}_3 a_3` can be constructed as

>>> fw1 = qml.fermi.FermiWord({(0, 0): '+', (1, 0): '-'})
>>> fw2 = qml.fermi.FermiWord({(0, 3): '+', (1, 3): '-'})
>>> qml.fermi.FermiSentence({fw1: 1.2, fw2: 2.3})
>>> fw1 = qml.FermiWord({(0, 0): '+', (1, 0): '-'})
>>> fw2 = qml.FermiWord({(0, 3): '+', (1, 3): '-'})
>>> qml.FermiSentence({fw1: 1.2, fw2: 2.3})
1.2 * a⁺(0) a(0)
+ 2.3 * a⁺(3) a(3)
2 changes: 2 additions & 0 deletions pennylane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
from pennylane.fermi import (
FermiC,
FermiA,
FermiWord,
FermiSentence,
jordan_wigner,
parity_transform,
bravyi_kitaev,
Expand Down
20 changes: 10 additions & 10 deletions pennylane/bose/bosonic.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class BoseWord(dict):
symbols that denote creation and annihilation operators, respectively. The operator
:math:`b^{\dagger}_0 b_1` can then be constructed as

>>> w = qml.bose.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> w = qml.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> print(w)
b⁺(0) b(1)
"""
Expand Down Expand Up @@ -112,7 +112,7 @@ def to_string(self):
represented by the number of the wire it operates on, and a `+` or `-` to indicate either
a creation or annihilation operator.

>>> w = qml.bose.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> w = qml.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> w.to_string()
'b⁺(0) b(1)'
"""
Expand Down Expand Up @@ -209,7 +209,7 @@ def __rsub__(self, other):
def __mul__(self, other):
r"""Multiply a BoseWord with another BoseWord, a BoseSentence, or a constant.

>>> w = qml.bose.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> w = qml.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> print(w * w)
b⁺(0) b(1) b⁺(0) b(1)
"""
Expand Down Expand Up @@ -263,7 +263,7 @@ def __rmul__(self, other):
def __pow__(self, value):
r"""Exponentiate a Bose word to an integer power.

>>> w = qml.bose.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> w = qml.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> print(w**3)
b⁺(0) b(1) b⁺(0) b(1) b⁺(0) b(1)
"""
Expand All @@ -280,7 +280,7 @@ def __pow__(self, value):
def normal_order(self):
r"""Convert a BoseWord to its normal-ordered form.

>>> bw = qml.bose.BoseWord({(0, 0): "-", (1, 0): "-", (2, 0): "+", (3, 0): "+"})
>>> bw = qml.BoseWord({(0, 0): "-", (1, 0): "-", (2, 0): "+", (3, 0): "+"})
>>> print(bw.normal_order())
4.0 * b⁺(0) b(0)
+ 2.0 * I
Expand Down Expand Up @@ -420,9 +420,9 @@ class BoseSentence(dict):
r"""Dictionary used to represent a Bose sentence, a linear combination of Bose words,
with the keys as BoseWord instances and the values correspond to coefficients.

>>> w1 = qml.bose.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> w2 = qml.bose.BoseWord({(0, 1) : '+', (1, 2) : '-'})
>>> s = BoseSentence({w1 : 1.2, w2: 3.1})
>>> w1 = qml.BoseWord({(0, 0) : '+', (1, 1) : '-'})
>>> w2 = qml.BoseWord({(0, 1) : '+', (1, 2) : '-'})
>>> s = qml.BoseSentence({w1 : 1.2, w2: 3.1})
>>> print(s)
1.2 * b⁺(0) b(1)
+ 3.1 * b⁺(1) b(2)
Expand Down Expand Up @@ -608,8 +608,8 @@ def simplify(self, tol=1e-8):
def normal_order(self):
r"""Convert a BoseSentence to its normal-ordered form.

>>> bw = qml.bose.BoseWord({(0, 0): "-", (1, 0): "-", (2, 0): "+", (3, 0): "+"})
>>> bs = qml.bose.BoseSentence({bw: 1})
>>> bw = qml.BoseWord({(0, 0): "-", (1, 0): "-", (2, 0): "+", (3, 0): "+"})
>>> bs = qml.BoseSentence({bw: 1})
>>> print(bw.normal_order())
4.0 * b⁺(0) b(0)
+ 2.0 * I
Expand Down
10 changes: 5 additions & 5 deletions pennylane/bose/bosonic_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def binary_mapping(

**Example**

>>> w = qml.bose.BoseWord({(0, 0): "+"})
>>> w = qml.BoseWord({(0, 0): "+"})
>>> qml.binary_mapping(w, n_states=4)
0.6830127018922193 * X(0)
+ -0.1830127018922193 * X(0) @ Z(1)
Expand Down Expand Up @@ -93,7 +93,7 @@ def binary_mapping(
@singledispatch
def _binary_mapping_dispatch(bose_operator, n_states, tol):
"""Dispatches to appropriate function if bose_operator is a BoseWord or BoseSentence."""
raise ValueError(f"bose_operator must be a BoseWord or BoseSentence, got: {bose_operator}")
raise TypeError(f"bose_operator must be a BoseWord or BoseSentence, got: {bose_operator}")


@_binary_mapping_dispatch.register
Expand Down Expand Up @@ -188,7 +188,7 @@ def unary_mapping(

**Example**

>>> w = qml.bose.BoseWord({(0, 0): "+"})
>>> w = qml.BoseWord({(0, 0): "+"})
>>> qml.unary_mapping(w, n_states=4)
0.25 * X(0) @ X(1)
+ -0.25j * X(0) @ Y(1)
Expand Down Expand Up @@ -220,7 +220,7 @@ def unary_mapping(
@singledispatch
def _unary_mapping_dispatch(bose_operator, n_states, ps=False, wires_map=None, tol=None):
"""Dispatches to appropriate function if bose_operator is a BoseWord or BoseSentence."""
raise ValueError(f"bose_operator must be a BoseWord or BoseSentence, got: {bose_operator}")
raise TypeError(f"bose_operator must be a BoseWord or BoseSentence, got: {bose_operator}")


@_unary_mapping_dispatch.register
Expand Down Expand Up @@ -352,7 +352,7 @@ def christiansen_mapping(
@singledispatch
def _christiansen_mapping_dispatch(bose_operator, tol):
"""Dispatches to appropriate function if bose_operator is a BoseWord or BoseSentence."""
raise ValueError(f"bose_operator must be a BoseWord or BoseSentence, got: {bose_operator}")
raise TypeError(f"bose_operator must be a BoseWord or BoseSentence, got: {bose_operator}")


@_christiansen_mapping_dispatch.register
Expand Down
24 changes: 14 additions & 10 deletions pennylane/fermi/fermionic.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class FermiWord(dict):
:math:`a^{\dagger}_0 a_1` can then be constructed as

>>> w = FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w
>>> print(w)
a⁺(0) a(1)
"""

Expand Down Expand Up @@ -114,7 +114,7 @@ def to_string(self):

>>> w = FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w.to_string()
a⁺(0) a(1)
'a⁺(0) a(1)'
"""
if len(self) == 0:
return "I"
Expand Down Expand Up @@ -211,7 +211,7 @@ def __mul__(self, other):
r"""Multiply a FermiWord with another FermiWord, a FermiSentence, or a constant.

>>> w = FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w * w
>>> print(w * w)
a⁺(0) a(1) a⁺(0) a(1)
"""

Expand Down Expand Up @@ -265,7 +265,7 @@ def __pow__(self, value):
r"""Exponentiate a Fermi word to an integer power.

>>> w = FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w**3
>>> print(w**3)
a⁺(0) a(1) a⁺(0) a(1) a⁺(0) a(1)
"""

Expand Down Expand Up @@ -348,7 +348,7 @@ def shift_operator(self, initial_position, final_position):

**Example**

>>> w = qml.fermi.FermiWord({(0, 0): '+', (1, 1): '-'})
>>> w = qml.FermiWord({(0, 0): '+', (1, 1): '-'})
>>> w.shift_operator(0, 1)
-1 * a(1) a⁺(0)
"""
Expand Down Expand Up @@ -427,7 +427,7 @@ class FermiSentence(dict):
>>> w1 = FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w2 = FermiWord({(0, 1) : '+', (1, 2) : '-'})
>>> s = FermiSentence({w1 : 1.2, w2: 3.1})
>>> s
>>> print(s)
1.2 * a⁺(0) a(1)
+ 3.1 * a⁺(1) a(2)
"""
Expand Down Expand Up @@ -754,13 +754,15 @@ class FermiC(FermiWord):

To construct the operator :math:`a^{\dagger}_0`:

>>> FermiC(0)
>>> w = FermiC(0)
>>> print(w)
a⁺(0)

This can be combined with the annihilation operator :class:`~pennylane.FermiA`. For example,
:math:`a^{\dagger}_0 a_1 a^{\dagger}_2 a_3` can be constructed as:

>>> qml.FermiC(0) * qml.FermiA(1) * qml.FermiC(2) * qml.FermiA(3)
>>> w = qml.FermiC(0) * qml.FermiA(1) * qml.FermiC(2) * qml.FermiA(3)
>>> print(w)
a⁺(0) a(1) a⁺(2) a(3)
"""

Expand Down Expand Up @@ -796,13 +798,15 @@ class FermiA(FermiWord):

To construct the operator :math:`a_0`:

>>> FermiA(0)
>>> w = FermiA(0)
>>> print(w)
a(0)

This can be combined with the creation operator :class:`~pennylane.FermiC`. For example,
:math:`a^{\dagger}_0 a_1 a^{\dagger}_2 a_3` can be constructed as:

>>> qml.FermiC(0) * qml.FermiA(1) * qml.FermiC(2) * qml.FermiA(3)
>>> w = qml.FermiC(0) * qml.FermiA(1) * qml.FermiC(2) * qml.FermiA(3)
>>> print(w)
a⁺(0) a(1) a⁺(2) a(3)
"""

Expand Down
10 changes: 5 additions & 5 deletions pennylane/qchem/convert_openfermion.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def from_openfermion(openfermion_op, wires=None, tol=1e-16):
tol (float): Tolerance for discarding negligible coefficients.
Returns:
Union[FermiWord, FermiSentence, LinearCombination]: PennyLane operator.
Union[~.FermiWord, ~.FermiSentence, LinearCombination]: PennyLane operator.
**Example**
Expand Down Expand Up @@ -113,7 +113,7 @@ def to_openfermion(
`FermionOperator <https://quantumai.google/reference/python/openfermion/ops/FermionOperator>`__.
Args:
pennylane_op (~ops.op_math.Sum, ~ops.op_math.LinearCombination, FermiWord, FermiSentence):
pennylane_op (~ops.op_math.Sum, ~ops.op_math.LinearCombination, ~.FermiWord, ~.FermiSentence):
PennyLane operator
wires (dict): Custom wire mapping used to convert a PennyLane qubit operator
to the external operator.
Expand All @@ -126,9 +126,9 @@ def to_openfermion(
**Example**
>>> import pennylane as qml
>>> w1 = qml.fermi.FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w2 = qml.fermi.FermiWord({(0, 1) : '+', (1, 2) : '-'})
>>> fermi_s = qml.fermi.FermiSentence({w1 : 1.2, w2: 3.1})
>>> w1 = qml.FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w2 = qml.FermiWord({(0, 1) : '+', (1, 2) : '-'})
>>> fermi_s = qml.FermiSentence({w1 : 1.2, w2: 3.1})
>>> of_fermi_op = qml.to_openfermion(fermi_s)
>>> of_fermi_op
1.2 [0^ 1] +
Expand Down
10 changes: 5 additions & 5 deletions pennylane/qchem/observable_hf.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def fermionic_observable(constant, one=None, two=None, cutoff=1.0e-12):
cutoff (float): cutoff value for discarding the negligible integrals

Returns:
FermiSentence: fermionic observable
~.FermiSentence: fermionic observable

**Example**

Expand Down Expand Up @@ -98,7 +98,7 @@ def qubit_observable(o_ferm, cutoff=1.0e-12, mapping="jordan_wigner"):
r"""Convert a fermionic observable to a PennyLane qubit observable.

Args:
o_ferm (Union[FermiWord, FermiSentence]): fermionic operator
o_ferm (Union[~.FermiWord, ~.FermiSentence]): fermionic operator
cutoff (float): cutoff value for discarding the negligible terms
mapping (str): Specifies the fermion-to-qubit mapping. Input values can
be ``'jordan_wigner'``, ``'parity'`` or ``'bravyi_kitaev'``.
Expand All @@ -107,9 +107,9 @@ def qubit_observable(o_ferm, cutoff=1.0e-12, mapping="jordan_wigner"):

**Example**

>>> w1 = qml.fermi.FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w2 = qml.fermi.FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> s = qml.fermi.FermiSentence({w1 : 1.2, w2: 3.1})
>>> w1 = qml.FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> w2 = qml.FermiWord({(0, 0) : '+', (1, 1) : '-'})
>>> s = qml.FermiSentence({w1 : 1.2, w2: 3.1})
>>> print(qubit_observable(s))
-0.775j * (Y(0) @ X(1)) + 0.775 * (Y(0) @ Y(1)) + 0.775 * (X(0) @ X(1)) + 0.775j * (X(0) @ Y(1))
"""
Expand Down
4 changes: 2 additions & 2 deletions pennylane/qchem/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,9 @@ def excitations(electrons, orbitals, delta_sz=0, fermionic=False):
if not fermionic:
return singles, doubles

fermionic_singles = [qml.fermi.FermiWord({(0, x[0]): "+", (1, x[1]): "-"}) for x in singles]
fermionic_singles = [qml.FermiWord({(0, x[0]): "+", (1, x[1]): "-"}) for x in singles]
fermionic_doubles = [
qml.fermi.FermiWord({(0, x[0]): "+", (1, x[1]): "+", (2, x[2]): "-", (3, x[3]): "-"})
qml.FermiWord({(0, x[0]): "+", (1, x[1]): "+", (2, x[2]): "-", (3, x[3]): "-"})
for x in doubles
]

Expand Down
2 changes: 1 addition & 1 deletion tests/bose/test_binary_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ def test_binary_mapping_wiremap(bose_op, wire_map, result):
def test_error_is_raised_for_incompatible_type():
"""Test that an error is raised if the input is not a BoseWord or BoseSentence"""

with pytest.raises(ValueError, match="bose_operator must be a BoseWord or BoseSentence"):
with pytest.raises(TypeError, match="bose_operator must be a BoseWord or BoseSentence"):
binary_mapping(X(0))


Expand Down
2 changes: 1 addition & 1 deletion tests/bose/test_christiansen_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,5 +388,5 @@ def test_christiansen_mapping_tolerance(bose_op, qubit_op_data, tol):
def test_error_is_raised_for_incompatible_type():
"""Test that an error is raised if the input is not a BoseWord or BoseSentence"""

with pytest.raises(ValueError, match="bose_operator must be a BoseWord or BoseSentence"):
with pytest.raises(TypeError, match="bose_operator must be a BoseWord or BoseSentence"):
christiansen_mapping(X(0))
2 changes: 1 addition & 1 deletion tests/bose/test_unary_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ def test_n_states_error_unary():
def test_error_is_raised_for_incompatible_type():
"""Test that an error is raised if the input is not a BoseWord or BoseSentence"""

with pytest.raises(ValueError, match="bose_operator must be a BoseWord or BoseSentence"):
with pytest.raises(TypeError, match="bose_operator must be a BoseWord or BoseSentence"):
unary_mapping(X(0))


Expand Down
Loading
Loading