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

Add Unary mapping for bosonic operators #6576

Merged
merged 106 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 99 commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
a488e29
bosonic ops
austingmhuang Nov 5, 2024
fe6a264
refactor
austingmhuang Nov 5, 2024
7ef89ff
ordering fix
austingmhuang Nov 5, 2024
57e55d0
small
austingmhuang Nov 5, 2024
844c04f
Added christiansen boson and fixed the bug
ddhawan11 Nov 7, 2024
180e26b
tests? could revert
austingmhuang Nov 5, 2024
59459a9
ascending order
austingmhuang Nov 7, 2024
d5f82d3
Apply suggestions from code review
austingmhuang Nov 8, 2024
67873a1
Merge branch 'master' into bose_operators
austingmhuang Nov 8, 2024
06ae4ec
test fragments
austingmhuang Nov 8, 2024
07b8d96
small fixes, and tests
austingmhuang Nov 8, 2024
d39a3d3
[skip ci] black
austingmhuang Nov 8, 2024
c210ada
tests
austingmhuang Nov 8, 2024
f33f120
Update pennylane/labs/tests/vibrational_ham/test_bosonic.py
austingmhuang Nov 8, 2024
f0819be
Update pennylane/labs/vibrational_ham/bosonic.py
austingmhuang Nov 8, 2024
86fc4d6
Update pennylane/labs/vibrational_ham/bosonic.py
austingmhuang Nov 8, 2024
82a366a
Update pennylane/labs/vibrational_ham/bosonic.py
austingmhuang Nov 8, 2024
09f9981
Update pennylane/labs/vibrational_ham/bosonic.py
austingmhuang Nov 8, 2024
6bc979d
Merge branch 'master' into bose_operators
austingmhuang Nov 8, 2024
18762b5
Merge branch 'master' into bose_operators
austingmhuang Nov 8, 2024
4beccf1
[skip ci] black
austingmhuang Nov 8, 2024
a0fd3ef
Bosonic mapping
ddhawan11 Nov 11, 2024
ee79e24
Added more tests
ddhawan11 Nov 11, 2024
302de16
[skip ci] compact code
ddhawan11 Nov 11, 2024
c493be4
Merge branch 'master' into bose_operators
austingmhuang Nov 12, 2024
718fe06
change name to vibrational
austingmhuang Nov 8, 2024
4141d05
shift operator draft
austingmhuang Nov 11, 2024
0090407
Update pennylane/labs/tests/vibrational_ham/test_bosonic_mapping.py
ddhawan11 Nov 12, 2024
1baea4d
Update pennylane/labs/vibrational_ham/bosonic_mapping.py
ddhawan11 Nov 12, 2024
971e1c2
Update pennylane/labs/vibrational_ham/bosonic_mapping.py
ddhawan11 Nov 12, 2024
9728a4b
Update pennylane/labs/vibrational_ham/bosonic_mapping.py
ddhawan11 Nov 12, 2024
0214ae0
[skip ci] Addressed comments and added more tests
ddhawan11 Nov 12, 2024
6eed9d1
Fixed test
ddhawan11 Nov 12, 2024
fefa2cf
shift operator
austingmhuang Nov 12, 2024
29a7c05
Added unary mapping and tests
ddhawan11 Nov 12, 2024
a8b3723
Resolved conflicts and minor changes
ddhawan11 Nov 13, 2024
c81072b
Merge branch 'bose_operators' into unary_mapping
ddhawan11 Nov 13, 2024
a94e0c4
raise error tests for shift operator
austingmhuang Nov 13, 2024
3a7769b
Merge branch 'master' into bose_operators
austingmhuang Nov 13, 2024
1ea0e01
address codefactor
austingmhuang Nov 13, 2024
f748685
black
austingmhuang Nov 13, 2024
3aa8003
some more tests
austingmhuang Nov 13, 2024
afcf8a1
ready for review
austingmhuang Nov 13, 2024
8667f8f
ready for review
austingmhuang Nov 13, 2024
604095b
Merge branch 'master' into bose_operators
austingmhuang Nov 13, 2024
8abb82c
ready for review
austingmhuang Nov 13, 2024
6cb18ac
black
austingmhuang Nov 13, 2024
7f6fc01
cleaner, but not completely ideal
austingmhuang Nov 13, 2024
3651a1e
cleaner, but not completely ideal
austingmhuang Nov 13, 2024
b03ccb8
Update pennylane/labs/vibrational/bosonic.py
austingmhuang Nov 14, 2024
5ab62c6
Update pennylane/labs/vibrational/bosonic.py
austingmhuang Nov 14, 2024
b33075e
Update pennylane/labs/vibrational/bosonic.py
austingmhuang Nov 14, 2024
2291262
Update pennylane/labs/vibrational/bosonic.py
austingmhuang Nov 14, 2024
45488e7
Update pennylane/labs/vibrational/bosonic.py
austingmhuang Nov 14, 2024
96fbbcb
Update pennylane/labs/vibrational/bosonic.py
austingmhuang Nov 14, 2024
1157ccc
Update pennylane/labs/vibrational/bosonic.py
austingmhuang Nov 14, 2024
ef88820
Update pennylane/labs/vibrational/bosonic.py
austingmhuang Nov 14, 2024
1dc167d
remove useless loc
austingmhuang Nov 14, 2024
5c59617
black
austingmhuang Nov 14, 2024
66b7efc
dont know
austingmhuang Nov 14, 2024
ee79fa0
missing tests
austingmhuang Nov 14, 2024
67dca52
move to qchem main
austingmhuang Nov 15, 2024
9c92076
remove path from labs init
austingmhuang Nov 15, 2024
8073e77
Changed to pl from labs
ddhawan11 Nov 15, 2024
f077acb
move stuff around
austingmhuang Nov 15, 2024
f07008f
fix
austingmhuang Nov 15, 2024
0470d2c
import properly
austingmhuang Nov 15, 2024
63d3b25
import properly
austingmhuang Nov 15, 2024
583a81e
Fixed tests
ddhawan11 Nov 15, 2024
4a69f95
[WIP] Tests for bose operators (#6559)
austingmhuang Nov 15, 2024
411eb42
Merge branch 'master' into bose_operators
austingmhuang Nov 15, 2024
9f96c91
pylint
austingmhuang Nov 15, 2024
ebd95bf
fix
austingmhuang Nov 15, 2024
fb9d8ff
fix tests
austingmhuang Nov 15, 2024
2eee3eb
fixes
austingmhuang Nov 15, 2024
168e82b
black
austingmhuang Nov 15, 2024
fd655b5
Merge branch 'master' into bose_operators
austingmhuang Nov 15, 2024
53331f1
Merge branch 'bose_operators' into unary_mapping
ddhawan11 Nov 18, 2024
8d23944
Fixed miswrite
ddhawan11 Nov 18, 2024
593e10f
Addressed comments
ddhawan11 Nov 21, 2024
6bcf2c0
Added more tests
ddhawan11 Nov 21, 2024
4b7bd11
[skip ci] Removed bose operators code
ddhawan11 Nov 21, 2024
6982dd3
Update pennylane/qchem/vibrational/bosonic_mapping.py
ddhawan11 Nov 22, 2024
a40dc5f
Update tests/qchem/vibrational_tests/test_unary_mapping.py
ddhawan11 Nov 22, 2024
71ddb93
Update tests/qchem/vibrational_tests/test_unary_mapping.py
ddhawan11 Nov 22, 2024
62f5af4
Update tests/qchem/vibrational_tests/test_unary_mapping.py
ddhawan11 Nov 22, 2024
e9d6c59
Addressed comments
ddhawan11 Nov 22, 2024
74884c6
Merge branch 'master' into unary_mapping
ddhawan11 Nov 22, 2024
e4df96c
Update pennylane/qchem/__init__.py
ddhawan11 Nov 22, 2024
72bbbbe
Update pennylane/qchem/__init__.py
ddhawan11 Nov 22, 2024
f009c67
Added tests for tolerance
ddhawan11 Nov 22, 2024
a869e44
Merge branch 'master' into unary_mapping
ddhawan11 Nov 22, 2024
806f36f
Minor docstring fix
ddhawan11 Nov 22, 2024
cb24930
Update pennylane/bose/bosonic_mapping.py
ddhawan11 Nov 25, 2024
80e02e0
Update pennylane/bose/bosonic_mapping.py
ddhawan11 Nov 25, 2024
d61bf47
Minor fixes
ddhawan11 Nov 25, 2024
5d922fd
Merge branch 'master' into unary_mapping
ddhawan11 Nov 25, 2024
88feae9
Merge branch 'master' into unary_mapping
ddhawan11 Nov 25, 2024
d0ca1d3
Added documentation
ddhawan11 Nov 25, 2024
9720e49
resolved conflicts
ddhawan11 Nov 25, 2024
f4320ae
Update pennylane/bose/bosonic_mapping.py
ddhawan11 Nov 25, 2024
5a53d95
Merge remote-tracking branch 'origin/master' into unary_mapping
ddhawan11 Nov 25, 2024
97d0a5a
Fixed isort
ddhawan11 Nov 25, 2024
6641000
modified indexing for docs
ddhawan11 Nov 26, 2024
21bc950
Merge branch 'master' into unary_mapping
ddhawan11 Nov 26, 2024
4273079
Merge branch 'master' into unary_mapping
ddhawan11 Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions doc/code/qml_bose.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
qml.bose
=========

Overview
--------

This module contains functions and classes for creating and manipulating bosonic operators.


BoseWord and BoseSentence
---------------------------

.. currentmodule:: pennylane.bose

.. autosummary::
:toctree: api

~BoseWord
~BoseSentence

Mapping to qubit operators
--------------------------

.. currentmodule:: pennylane.bose

.. autosummary::
:toctree: api

~binary_mapping
~unary_mapping


1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ PennyLane is **free** and **open source**, released under the Apache License, Ve
code/qml_qchem
code/qml_qnn
code/qml_spin
code/qml_bose

.. toctree::
:maxdepth: 1
Expand Down
3 changes: 3 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
* Added a second class `DefaultMixedNewAPI` to the `qml.devices.qubit_mixed` module, which is to be the replacement of legacy `DefaultMixed` which for now to hold the implementations of `preprocess` and `execute` methods.
[(#6607)](https://github.com/PennyLaneAI/pennylane/pull/6507)

* Added `unary_mapping()` function to map `BoseWord` and `BoseSentence` to qubit operators, using unary mapping.
[(#6576)](https://github.com/PennyLaneAI/pennylane/pull/6576)

<h3>Improvements 🛠</h3>

* Raises a comprehensive error when using `qml.fourier.qnode_spectrum` with standard numpy
Expand Down
6 changes: 5 additions & 1 deletion pennylane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@
parity_transform,
bravyi_kitaev,
)
from pennylane.bose import BoseSentence, BoseWord
from pennylane.bose import (
BoseSentence,
BoseWord,
unary_mapping,
)
from pennylane.qchem import (
taper,
symmetry_generators,
Expand Down
16 changes: 15 additions & 1 deletion pennylane/bose/__init__.py
ddhawan11 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# Copyright 2018-2024 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A module containing utility functions and mappings for working with bosonic operators. """

from .bosonic import BoseWord, BoseSentence
from .bosonic import BoseSentence, BoseWord
from .bosonic_mapping import unary_mapping
ddhawan11 marked this conversation as resolved.
Show resolved Hide resolved
172 changes: 172 additions & 0 deletions pennylane/bose/bosonic_mapping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Copyright 2024 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This module contains functions to map bosonic operators to qubit operators."""

from collections import defaultdict
from functools import singledispatch
from typing import Union

import numpy as np

import pennylane as qml
from pennylane.pauli import PauliSentence, PauliWord

from .bosonic import BoseSentence, BoseWord


def _get_pauli_op(i, j, qub_id):
r"""Returns expression to convert qubit-local term ::math::``\ket{x_i}\bra{x_j}``
to qubit operators as given in :math:`Eq. (6-9)` in `arXiv.1909.12847 <https://arxiv.org/abs/1909.12847>`_.
"""

c1, c2 = 0.5, -0.5 if i == 1 else 0.5

if i != j:
return PauliSentence({PauliWord({qub_id: "X"}): c1, PauliWord({qub_id: "Y"}): c2 * 1j})

return PauliSentence({PauliWord({}): c1, PauliWord({qub_id: "Z"}): c2})


def unary_mapping(
bose_operator: Union[BoseWord, BoseSentence],
n_states: int = 2,
ps: bool = False,
wire_map: dict = None,
tol: float = None,
ddhawan11 marked this conversation as resolved.
Show resolved Hide resolved
):
r"""Convert a bosonic operator to a qubit operator using the unary mapping.

The mapping procedure is described in `arXiv.1909.12847 <https://arxiv.org/abs/1909.12847>`_.

Args:
bose_operator(BoseWord, BoseSentence): the bosonic operator
n_states(int): maximum number of allowed bosonic states
ps (bool): Whether to return the result as a PauliSentence instead of an
operator. Defaults to False.
wire_map (dict): A dictionary defining how to map the states of
DSGuala marked this conversation as resolved.
Show resolved Hide resolved
the Bose operator to qubit wires. If None, integers used to
label the bosonic states will be used as wire labels. Defaults to None.
tol (float): tolerance for discarding the imaginary part of the coefficients

Returns:
Union[PauliSentence, Operator]: A linear combination of qubit operators
ddhawan11 marked this conversation as resolved.
Show resolved Hide resolved

**Example**

>>> w = qml.bose.BoseWord({(0, 0): "+"})
>>> qml.unary_mapping(w, n_states=4)
0.25 * X(0) @ X(1)
+ -0.25j * X(0) @ Y(1)
+ 0.25j * Y(0) @ X(1)
+ (0.25+0j) * Y(0) @ Y(1)
+ 0.3535533905932738 * X(1) @ X(2)
+ -0.3535533905932738j * X(1) @ Y(2)
+ 0.3535533905932738j * Y(1) @ X(2)
+ (0.3535533905932738+0j) * Y(1) @ Y(2)
+ 0.4330127018922193 * X(2) @ X(3)
+ -0.4330127018922193j * X(2) @ Y(3)
+ 0.4330127018922193j * Y(2) @ X(3)
+ (0.4330127018922193+0j) * Y(2) @ Y(3)
"""

qubit_operator = _unary_mapping_dispatch(bose_operator, n_states, tol=tol)

wires = list(bose_operator.wires) or [0]
identity_wire = wires[0]
if not ps:
qubit_operator = qubit_operator.operation(wire_order=[identity_wire])

if wire_map:
return qubit_operator.map_wires(wire_map)

return qubit_operator


@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}")


@_unary_mapping_dispatch.register
def _(bose_operator: BoseWord, n_states, tol=None):

if n_states < 2:
raise ValueError(
f"Number of allowed bosonic states cannot be less than 2, provided {n_states}."
)

creation = np.zeros((n_states, n_states))
for i in range(n_states - 1):
creation[i + 1, i] = np.sqrt(i + 1.0)

coeff_mat = {"+": creation, "-": creation.T}

qubit_operator = PauliSentence({PauliWord({}): 1.0})

ops_per_idx = defaultdict(list)

# Avoiding superfluous terms by taking the product of
# coefficient matrices.
for (_, b_idx), sign in bose_operator.items():
ops_per_idx[b_idx].append(sign)

for b_idx, signs in ops_per_idx.items():
coeff_mat_prod = np.eye(n_states)
for sign in signs:
coeff_mat_prod = np.dot(coeff_mat_prod, coeff_mat[sign])

op = PauliSentence()
sparse_coeffmat = np.nonzero(coeff_mat_prod)
for i, j in zip(*sparse_coeffmat):
coeff = coeff_mat_prod[i][j]

row = np.zeros(n_states)
row[i] = 1

col = np.zeros(n_states)
col[j] = 1

pauliOp = PauliSentence({PauliWord({}): 1.0})
for n in range(n_states):
if row[n] == 1 or col[n] == 1:
pauliOp @= _get_pauli_op(row[n], col[n], n + b_idx * n_states)
op += coeff * pauliOp
qubit_operator @= op

for pw in qubit_operator:
if tol is not None and abs(qml.math.imag(qubit_operator[pw])) <= tol:
qubit_operator[pw] = qml.math.real(qubit_operator[pw])
qubit_operator.simplify(tol=1e-16)

return qubit_operator


@_unary_mapping_dispatch.register
def _(bose_operator: BoseSentence, n_states, tol=None):

qubit_operator = PauliSentence()

for bw, coeff in bose_operator.items():
bose_word_as_ps = unary_mapping(bw, n_states=n_states, ps=True)

for pw in bose_word_as_ps:
qubit_operator[pw] = qubit_operator[pw] + bose_word_as_ps[pw] * coeff

if tol is not None and abs(qml.math.imag(qubit_operator[pw])) <= tol:
qubit_operator[pw] = qml.math.real(qubit_operator[pw])

qubit_operator.simplify(tol=1e-16)

return qubit_operator
Loading
Loading