qc2.pennylane.convert

Module containing utils for converting Qiskit operators to Pennylane format.

Notes

It representes a major extension of pennylane/qchem/convert.py module. https://github.com/PennyLaneAI/pennylane/blob/master/pennylane/qchem/convert.py

The implemented functions may only be valid to fermionic-to-qubit transformed hamiltonians as it accounts for the distinct alpha and beta qubit (wire) distribution between VQE anzatses in Qiskit-Nature and Pennylane.

Functions

_qiskit_nature_to_pennylane(qubit_operator[, wires])

Convert Qiskit SparsePauliOp to 2-tuple of coeffs and PennyLane Paulis.

_pennylane_to_qiskit_nature(coeffs, ops, wires)

Convert Pennylane to Qiskit-Nature formats.

_qiskit_nature_pennylane_equivalent(...[, wires])

Check functionality of _pennylane_to_qiskit_nature().

import_operator(qubit_observable[, format, wires, tol])

Convert an external operator to a PennyLane operator.

Module Contents

qc2.pennylane.convert._qiskit_nature_to_pennylane(qubit_operator, wires=None)[source]

Convert Qiskit SparsePauliOp to 2-tuple of coeffs and PennyLane Paulis.

This functions is usefull to convert fermionic-to-qubit transformed qchem operators from Qiskit-Nature to Pennynale format.

Parameters:
  • qubit_operator (qiskit.quantum_info.SparsePauliOp) – Qiskit operator representing the qubit electronic Hamiltonian from Qiskit-Nature.

  • wires (Wires, list, tuple, dict) – Custom wire mapping used to convert the qubit operator to an observable terms measurable in PennyLane. For types Wires/list/tuple, each item in the iterable represents a wire label corresponding to the qubit number equal to its index. For type dict, only int-keyed dict (for qubit-to-wire conversion) is accepted. If None, will use identity map (0->0, 1->1, …).

Returns:

coeffs and their corresponding PennyLane observables in the Pauli basis.

Return type:

tuple[array[float], Iterable[pennylane.operation.Operator]]

Example

>>> from qiskit.quantum_info import SparsePauliOp
>>> qubit_op = SparsePauliOp.from_list([("XIIZI", 1), ("IYIIY", 2)])
>>> qubit_op
SparsePauliOp(['XIIZI', 'IYIIY'],
          coeffs=[1.+0.j, 2.+0.j])
>>> _qiskit_nature_to_pennylane(qubit_op,wires=['w0','w1','w2','w3','w4'])
(tensor([1., 2.], requires_grad=False),
[PauliX(wires=['w2']) @ PauliZ(wires=['w3']),
PauliY(wires=['w0']) @ PauliY(wires=['w4'])])

If the new op-math is active, the list of operators will be cast as Prod instances instead of Tensor instances when appropriate.

qc2.pennylane.convert._pennylane_to_qiskit_nature(coeffs, ops, wires)[source]

Convert Pennylane to Qiskit-Nature formats.

Convert a 2-tuple of complex coefficients and PennyLane operations to Qiskit SparsePauliOp.

Parameters:
  • coeffs (array[complex]) – coefficients for each observable, same length as ops

  • ops (Iterable[pennylane.operation.Operations]) – list of PennyLane operations that have a valid PauliSentence representation.

  • wires (Wires, list, tuple, dict) – Full wire mapping used to convert to qubit operator from an observable terms measurable in a PennyLane ansatz. For types Wires/list/tuple, each item in the iterable represents a wire label corresponding to the qubit number equal to its index. For type dict, only consecutive-int-valued dict (for wire-to-qubit conversion) is accepted.

Returns:

an instance of Qiskit’s SparsePauliOp.

Return type:

SparsePauliOp

Notes

Instead of having to provide the full list of wires, e.g., wires=[0, 1, 2, 3, …, n_wires], this function could be alternativelly implemented using SparsePauliOp.from_sparse_list() in place of SparsePauliOp.from_list(), e.g.,

op = SparsePauliOp.from_sparse_list(
    [("ZX", [1, 4], 1), ("YY", [0, 3], 2)], num_qubits=5)

with the requirement that users provide the total number of qubits.

Example

>>> coeffs = np.array([0.1, 0.2, 0.3])
>>>> ops = [
...     qml.operation.Tensor(qml.PauliX(wires=[0])),
...     qml.operation.Tensor(qml.PauliY(wires=[0]), qml.PauliZ(wires=[2])),
...     qml.prod(qml.PauliX(wires=[0]), qml.PauliZ(wires=[3]))
... ]
>>> _pennylane_to_qiskit_nature(coeffs, ops, wires=[0, 1, 2, 3])
SparsePauliOp(['IIIX', 'IZIY', 'ZIIX'],
              coeffs=[0.1+0.j, 0.2+0.j, 0.3+0.j])
qc2.pennylane.convert._qiskit_nature_pennylane_equivalent(qiskit_qubit_operator, pennylane_qubit_operator, wires=None)[source]

Check functionality of _pennylane_to_qiskit_nature().

Check equivalence between Qiskit SparsePauliOp and Pennylane VQE Hamiltonian (Tensor product of Pauli matrices).

Equality is based on Qiskit SparsePauliOp’s equality.

Parameters:
  • qiskit_qubit_operator (SparsePauliOp) – Qiskit-Natuire qubit operator represented as a Pauli summation

  • pennylane_qubit_operator (pennylane.Hamiltonian) – PennyLane Hamiltonian object

  • wires (Wires, list, tuple, dict) – Full wire mapping used to convert to qubit operator from an observable terms measurable in a PennyLane ansatz. For types Wires/list/tuple, each item in the iterable represents a wire label corresponding to the qubit number equal to its index. For type dict, only consecutive-int-valued dict (for wire-to-qubit conversion) is accepted.

Returns:

True if equivalent

Return type:

(bool)

qc2.pennylane.convert.import_operator(qubit_observable, format='openfermion', wires=None, tol=10000000000.0)[source]

Convert an external operator to a PennyLane operator.

The external format currently supported is openfermion and qiskit.

Parameters:
  • qubit_observable – external qubit operator that will be converted

  • format (str) – the format of the operator object to convert from

  • wires (.Wires, list, tuple, dict) – Custom wire mapping used to convert the external qubit operator to a PennyLane operator. For types Wires/list/tuple, each item in the iterable represents a wire label for the corresponding qubit index. For type dict, only int-keyed dictionaries (for qubit-to-wire conversion) are accepted. If None, the identity map (0->0, 1->1, …) will be used.

  • tol (float) – Tolerance in machine epsilon <https://numpy.org/doc/stable/reference/generated/numpy.real_if_close.html> for the imaginary part of the coefficients in qubit_observable. Coefficients with imaginary part less than 2.22e-16*tol are considered to be real.

Returns:

PennyLane operator representing any operator expressed as linear comb of Pauli words, e.g., \(\\sum_{k=0}^{N-1} c_k O_k\)

Return type:

(.Operator)

Example

>>> from openfermion import QubitOperator
>>> h_of = QubitOperator('X0 X1 Y2 Y3', -0.0548)
+ QubitOperator('Z0 Z1', 0.14297)
>>> h_pl = import_operator(h_of, format='openfermion')
>>> print(h_pl)
(0.14297) [Z0 Z1]
+ (-0.0548) [X0 X1 Y2 Y3]
>>> from qiskit.quantum_info import SparsePauliOp
>>> h_qt = SparsePauliOp.from_list([("XXYY", -0.0548), ("ZZII", 0.14297)])
>>> h_pl = import_operator(h_qt, format='qiskit')
>>> print(h_pl)
(0.14297) [Z1 Z3]
+ (-0.0548) [Y0 X1 Y2 Y3]

If the new op-math is active, an arithmetic operator is returned instead.

>>> qml.operation.enable_new_opmath()
>>> h_pl = import_operator(h_of, format='openfermion')
>>> print(h_pl)
(-0.0548*(PauliX(wires=[0]) @ PauliX(wires=[1]) @ PauliY(wires=[2]) @
PauliY(wires=[3]))) + (0.14297*(PauliZ(wires=[0]) @ PauliZ(wires=[1])))