qc2.pennylane.convert ===================== .. py:module:: qc2.pennylane.convert .. autoapi-nested-parse:: Module containing utils for converting Qiskit operators to Pennylane format. .. rubric:: 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 --------- .. autoapisummary:: qc2.pennylane.convert._qiskit_nature_to_pennylane qc2.pennylane.convert._pennylane_to_qiskit_nature qc2.pennylane.convert._qiskit_nature_pennylane_equivalent qc2.pennylane.convert.import_operator Module Contents --------------- .. py:function:: _qiskit_nature_to_pennylane(qubit_operator, wires=None) 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. :param qubit_operator: Qiskit operator representing the qubit electronic Hamiltonian from Qiskit-Nature. :type qubit_operator: qiskit.quantum_info.SparsePauliOp :param wires: 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, ...). :type wires: Wires, list, tuple, dict :returns: coeffs and their corresponding PennyLane observables in the Pauli basis. :rtype: 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 :class:`~.Prod` instances instead of :class:`~.Tensor` instances when appropriate. .. py:function:: _pennylane_to_qiskit_nature(coeffs, ops, wires) Convert Pennylane to Qiskit-Nature formats. Convert a 2-tuple of complex coefficients and PennyLane operations to Qiskit ``SparsePauliOp``. :param coeffs: coefficients for each observable, same length as ops :type coeffs: array[complex] :param ops: list of PennyLane operations that have a valid PauliSentence representation. :type ops: Iterable[pennylane.operation.Operations] :param wires: 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. :type wires: Wires, list, tuple, dict :returns: an instance of Qiskit's ``SparsePauliOp``. :rtype: SparsePauliOp .. rubric:: 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., .. code-block:: python 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]) .. py:function:: _qiskit_nature_pennylane_equivalent(qiskit_qubit_operator, pennylane_qubit_operator, wires=None) Check functionality of :func:`_pennylane_to_qiskit_nature`. Check equivalence between Qiskit :class:`~.SparsePauliOp` and Pennylane VQE ``Hamiltonian`` (Tensor product of Pauli matrices). Equality is based on Qiskit :class:`~.SparsePauliOp`'s equality. :param qiskit_qubit_operator: Qiskit-Natuire qubit operator represented as a Pauli summation :type qiskit_qubit_operator: SparsePauliOp :param pennylane_qubit_operator: PennyLane Hamiltonian object :type pennylane_qubit_operator: pennylane.Hamiltonian :param wires: 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. :type wires: Wires, list, tuple, dict :returns: True if equivalent :rtype: (bool) .. py:function:: import_operator(qubit_observable, format='openfermion', wires=None, tol=10000000000.0) Convert an external operator to a PennyLane operator. The external format currently supported is openfermion and qiskit. :param qubit_observable: external qubit operator that will be converted :param format: the format of the operator object to convert from :type format: str :param wires: 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. :type wires: .Wires, list, tuple, dict :param tol: Tolerance in `machine epsilon ` 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. :type tol: float :returns: PennyLane operator representing any operator expressed as linear comb of Pauli words, e.g., :math:`\\sum_{k=0}^{N-1} c_k O_k` :rtype: (.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])))