Error mitigation with Amplitude Embedding

Hello! I’m getting an error when using the qml.transforms.mitigate_with_zne transform with a circuit including AmplitudeEmbedding. The forward pass already rises an error. This error disappears if we replace the AmplitudeEmbedding layer by another layer, such as AngleEmbedding. I need to encode a 16-feature vector in a quantum circuit, so that AmplitudeEmbeding is very convinient to reduce the number of qubits. Is there a way to use error mitigation with AmplitudeEmmbedding in Pennylane? Here’s my code:

import pennylane as qml
from pennylane import numpy as qnp
from pennylane.transforms import richardson_extrapolate, fold_global

# Hyperparameters of the circui
nqbits=4
depth=1

# Device definition
dev_ideal = qml.device('default.mixed', wires=nqbits)
dev_mixed = qml.transforms.insert( qml.DepolarizingChannel, 0.05)(dev_ideal) # Adding noise

@qml.transforms.mitigate_with_zne([1, 2, 3], fold_global, richardson_extrapolate) # Adding error mitigation
@qnode(dev_mixed)
def mitigated_qnode(inputs, weights):
    qml.AmplitudeEmbedding(features=inputs, wires=range(nqbits),normalize=True)
    qml.templates.StronglyEntanglingLayers(weights, wires=range(nqbits))
    return qml.expval(qml.PauliZ(0))

# Running the circuit with random inputs/weights
inputs = qnp.random.normal(2, 4,(1, 2**nqbits), requires_grad=False)
weights = qnp.random.uniform(-1,1,(depth, nqbits,3))
mitigated_qnode(inputs, weights)

And here’s the error I get:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[92], line 23
     21 inputs = qnp.random.normal(2, 4,(1, 2**nqbits), requires_grad=False)
     22 weights = qnp.random.uniform(-1,1,(depth, nqbits,3))
---> 23 mitigated_qnode(inputs, weights)

File c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\batch_transform.py:300, in batch_transform.default_qnode_wrapper.<locals>._wrapper(*args, **kwargs)
    297     qnode.interface = qml.math.get_interface(*args, *list(kwargs.values()))
    299 qnode.construct(args, kwargs)
--> 300 tapes, processing_fn = self.construct(qnode.qtape, *targs, **tkwargs)
    302 interface = qnode.interface
    303 execute_kwargs = getattr(qnode, "execute_kwargs", {}).copy()

File c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\batch_transform.py:431, in batch_transform.construct(self, tape, *targs, **tkwargs)
    429 if argnums is not None:
    430     tape.trainable_params = argnums
--> 431 tapes, processing_fn = self.transform_fn(tape, *targs, **tkwargs)
    433 if processing_fn is None:
    435     def processing_fn(x):

File c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\mitigate.py:517, in mitigate_with_zne(circuit, scale_factors, folding, extrapolate, folding_kwargs, extrapolate_kwargs, reps_per_factor)
    514 tape = circuit.expand(stop_at=lambda op: not isinstance(op, QuantumScript))
    515 script_removed = QuantumScript(tape._ops)
--> 517 tapes = [
    518     [folding(script_removed, s, **folding_kwargs) for _ in range(reps_per_factor)]
    519     for s in scale_factors
    520 ]
    522 tapes = [tape_ for tapes_ in tapes for tape_ in tapes_]  # flattens nested list
    523 out_tapes = [QuantumScript(tape_.operations, tape.measurements, tape._prep) for tape_ in tapes]

File c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\mitigate.py:518, in <listcomp>(.0)
    514 tape = circuit.expand(stop_at=lambda op: not isinstance(op, QuantumScript))
    515 script_removed = QuantumScript(tape._ops)
    517 tapes = [
--> 518     [folding(script_removed, s, **folding_kwargs) for _ in range(reps_per_factor)]
    519     for s in scale_factors
    520 ]
    522 tapes = [tape_ for tapes_ in tapes for tape_ in tapes_]  # flattens nested list
    523 out_tapes = [QuantumScript(tape_.operations, tape.measurements, tape._prep) for tape_ in tapes]

File c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\mitigate.py:518, in <listcomp>(.0)
    514 tape = circuit.expand(stop_at=lambda op: not isinstance(op, QuantumScript))
    515 script_removed = QuantumScript(tape._ops)
    517 tapes = [
--> 518     [folding(script_removed, s, **folding_kwargs) for _ in range(reps_per_factor)]
    519     for s in scale_factors
    520 ]
    522 tapes = [tape_ for tapes_ in tapes for tape_ in tapes_]  # flattens nested list
    523 out_tapes = [QuantumScript(tape_.operations, tape.measurements, tape._prep) for tape_ in tapes]

File c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\mitigate.py:251, in fold_global_tape(circuit, scale_factor)
    248     for meas in circuit.measurements:
    249         apply(meas)
--> 251 return QuantumScript.from_queue(new_circuit_q)

File c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\tape\qscript.py:1331, in QuantumScript.from_queue(cls, queue)
   1328 @classmethod
   1329 def from_queue(cls, queue):
   1330     """Construct a QuantumScript from an AnnotatedQueue."""
-> 1331     return cls(*process_queue(queue))

File c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\queuing.py:525, in process_queue(queue)
    523             current_list = obj._queue_category
    524         elif list_order[obj._queue_category] < list_order[current_list]:
--> 525             raise ValueError(
    526                 f"{obj._queue_category[1:]} operation {obj} must occur prior "
    527                 f"to {current_list[1:]}. Please place earlier in the queue."
    528             )
    529         lists[obj._queue_category].append(obj)
    531 return lists["_ops"], lists["_measurements"], lists["_prep"]

ValueError: prep operation Adjoint(QubitStateVector(tensor([[-0.38310708+0.j,  0.14985063+0.j,  0.08886766+0.j,
          0.14269864+0.j,  0.34669516+0.j, -0.53808762+0.j,
         -0.01665238+0.j,  0.1849713 +0.j,  0.00796543+0.j,
         -0.22028881+0.j,  0.32889664+0.j,  0.18664527+0.j,
         -0.11318396+0.j,  0.19576172+0.j,  0.31751402+0.j,
          0.12139773+0.j]], requires_grad=False), wires=[0, 1, 2, 3])) must occur prior to ops. Please place earlier in the queue.

Thanks for the help! Here is the output of qml.about().

Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning, PennyLane-qiskit

Platform info:           Windows-10-10.0.19045-SP0
Python version:          3.11.2
Numpy version:           1.23.5
Scipy version:           1.10.1
Installed devices:
- qiskit.aer (PennyLane-qiskit-0.34.0)
- qiskit.basicaer (PennyLane-qiskit-0.34.0)
- qiskit.ibmq (PennyLane-qiskit-0.34.0)
- qiskit.ibmq.circuit_runner (PennyLane-qiskit-0.34.0)
- qiskit.ibmq.sampler (PennyLane-qiskit-0.34.0)
- qiskit.remote (PennyLane-qiskit-0.34.0)
- default.gaussian (PennyLane-0.30.0)
- default.mixed (PennyLane-0.30.0)
- default.qubit (PennyLane-0.30.0)
- default.qubit.autograd (PennyLane-0.30.0)
- default.qubit.jax (PennyLane-0.30.0)
- default.qubit.tf (PennyLane-0.30.0)
- default.qubit.torch (PennyLane-0.30.0)
- default.qutrit (PennyLane-0.30.0)
- null.qubit (PennyLane-0.30.0)
- lightning.qubit (PennyLane-Lightning-0.31.0)

Hello,
state preparation must occur before other operation (such as the operations performed by mitigation).

qml.transforms.mitigate_with_zne transform is trying to apply certain mitigations that are not compatible with the order of operations in the circuit containing AmplitudeEmbedding.

Try this:

import pennylane as qml
from pennylane import numpy as qnp
from pennylane.transforms import richardson_extrapolate, fold_global
from functools import partial

# Define a new device class by inheriting from the existing device class
class MyMixedDevice(qml.devices.DefaultMixed):
    def __init__(self, noise_strength, wires, **kwargs):
        super().__init__(wires=wires, **kwargs)
        self.noise_strength = noise_strength

    def apply(self, operations, **kwargs):
        # Apply the DepolarizingChannel noise to each operation
        for operation in operations:
            if isinstance(operation, qml.operation.Observable):
                self.noise_strength = operation.parameters[0] if operation.name == "DepolarizingChannel" else self.noise_strength
                if isinstance(operation, qml.operation.Expectation):
                    operation.return_type = qml.operation.Expectation
        return super().apply(operations, **kwargs)

# Hyperparameters of the circuit
nqbits = 4
depth = 1

# Device definition
dev_ideal = qml.device('default.mixed', wires=nqbits)

# Adding noise with DepolarizingChannel on each wire
dev_mixed = MyMixedDevice(0.05, wires=range(nqbits))

def state_preparation(inputs):
    qml.AmplitudeEmbedding(features=inputs, wires=range(nqbits), normalize=True)

# Applying the transform with functools.partial
mitigated_qnode = partial(qml.transforms.mitigate_with_zne, scale_factors=[1, 2, 3], folding=fold_global, extrapolate=richardson_extrapolate)

@mitigated_qnode
@qml.qnode(dev_mixed)
def mitigated_qnode(inputs, weights):
    state_preparation(inputs)
    qml.templates.StronglyEntanglingLayers(weights, wires=range(nqbits))
    return qml.expval(qml.PauliZ(0))

# Running the circuit with random inputs/weights
inputs = qnp.random.normal(2, 4, (1, 2 ** nqbits), requires_grad=False)
weights = qnp.random.uniform(-1, 1, (depth, nqbits, 3))
result = mitigated_qnode(inputs, weights)
print(result)

Hi Alex, thank you for your help!
I copy pasted your code but I’m still getting the same error message:
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[1], [line 47](vscode-notebook-cell:?execution_count=1&line=47) [45](vscode-notebook-cell:?execution_count=1&line=45) inputs = qnp.random.normal(2, 4, (1, 2 ** nqbits), requires_grad=False) [46](vscode-notebook-cell:?execution_count=1&line=46) weights = qnp.random.uniform(-1, 1, (depth, nqbits, 3)) ---> [47](vscode-notebook-cell:?execution_count=1&line=47) result = mitigated_qnode(inputs, weights) [48](vscode-notebook-cell:?execution_count=1&line=48) print(result) File [c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\batch_transform.py:300](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:300), in batch_transform.default_qnode_wrapper.<locals>._wrapper(*args, **kwargs) [297](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:297) qnode.interface = qml.math.get_interface(*args, *list(kwargs.values())) [299](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:299) qnode.construct(args, kwargs) --> [300](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:300) tapes, processing_fn = self.construct(qnode.qtape, *targs, **tkwargs) [302](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:302) interface = qnode.interface [303](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:303) execute_kwargs = getattr(qnode, "execute_kwargs", {}).copy() File [c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\batch_transform.py:431](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:431), in batch_transform.construct(self, tape, *targs, **tkwargs) [429](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:429) if argnums is not None: [430](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:430) tape.trainable_params = argnums --> [431](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:431) tapes, processing_fn = self.transform_fn(tape, *targs, **tkwargs) [433](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:433) if processing_fn is None: [435](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/batch_transform.py:435) def processing_fn(x): File [c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\mitigate.py:517](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:517), in mitigate_with_zne(circuit, scale_factors, folding, extrapolate, folding_kwargs, extrapolate_kwargs, reps_per_factor) [514](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:514) tape = circuit.expand(stop_at=lambda op: not isinstance(op, QuantumScript)) [515](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:515) script_removed = QuantumScript(tape._ops) --> [517](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:517) tapes = [ [518](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:518) [folding(script_removed, s, **folding_kwargs) for _ in range(reps_per_factor)] [519](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:519) for s in scale_factors [520](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:520) ] [522](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:522) tapes = [tape_ for tapes_ in tapes for tape_ in tapes_] # flattens nested list [523](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:523) out_tapes = [QuantumScript(tape_.operations, tape.measurements, tape._prep) for tape_ in tapes] File [c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\mitigate.py:518](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:518), in <listcomp>(.0) [514](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:514) tape = circuit.expand(stop_at=lambda op: not isinstance(op, QuantumScript)) [515](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:515) script_removed = QuantumScript(tape._ops) [517](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:517) tapes = [ --> [518](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:518) [folding(script_removed, s, **folding_kwargs) for _ in range(reps_per_factor)] [519](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:519) for s in scale_factors [520](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:520) ] [522](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:522) tapes = [tape_ for tapes_ in tapes for tape_ in tapes_] # flattens nested list [523](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:523) out_tapes = [QuantumScript(tape_.operations, tape.measurements, tape._prep) for tape_ in tapes] File [c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\mitigate.py:518](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:518), in <listcomp>(.0) [514](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:514) tape = circuit.expand(stop_at=lambda op: not isinstance(op, QuantumScript)) [515](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:515) script_removed = QuantumScript(tape._ops) [517](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:517) tapes = [ --> [518](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:518) [folding(script_removed, s, **folding_kwargs) for _ in range(reps_per_factor)] [519](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:519) for s in scale_factors [520](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:520) ] [522](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:522) tapes = [tape_ for tapes_ in tapes for tape_ in tapes_] # flattens nested list [523](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:523) out_tapes = [QuantumScript(tape_.operations, tape.measurements, tape._prep) for tape_ in tapes] File [c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\transforms\mitigate.py:251](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:251), in fold_global_tape(circuit, scale_factor) [248](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:248) for meas in circuit.measurements: [249](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:249) apply(meas) --> [251](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/transforms/mitigate.py:251) return QuantumScript.from_queue(new_circuit_q) File [c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\tape\qscript.py:1331](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/tape/qscript.py:1331), in QuantumScript.from_queue(cls, queue) [1328](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/tape/qscript.py:1328) @classmethod [1329](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/tape/qscript.py:1329) def from_queue(cls, queue): [1330](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/tape/qscript.py:1330) """Construct a QuantumScript from an AnnotatedQueue.""" -> [1331](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/tape/qscript.py:1331) return cls(*process_queue(queue)) File [c:\Users\laiad\anaconda3\envs\Quantum3\Lib\site-packages\pennylane\queuing.py:525](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:525), in process_queue(queue) [523](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:523) current_list = obj._queue_category [524](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:524) elif list_order[obj._queue_category] < list_order[current_list]: --> [525](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:525) raise ValueError( [526](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:526) f"{obj._queue_category[1:]} operation {obj} must occur prior " [527](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:527) f"to {current_list[1:]}. Please place earlier in the queue." [528](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:528) ) [529](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:529) lists[obj._queue_category].append(obj) [531](file:///C:/Users/laiad/anaconda3/envs/Quantum3/Lib/site-packages/pennylane/queuing.py:531) return lists["_ops"], lists["_measurements"], lists["_prep"] ValueError: prep operation Adjoint(QubitStateVector(tensor([[ 0.04942569+0.j, 0.24269701+0.j, 0.34812557+0.j, 0.17978282+0.j, 0.1126188 +0.j, 0.33736393+0.j, -0.41157208+0.j, 0.3897833 +0.j, -0.1007921 +0.j, -0.13128589+0.j, -0.26301813+0.j, -0.05402194+0.j, -0.1528719 +0.j, 0.18562809+0.j, 0.30692938+0.j, 0.29291089+0.j]], requires_grad=False), wires=[0, 1, 2, 3])) must occur prior to ops. Please place earlier in the queue.

Is your example working for you? Maybe we have different Pennylane versions?

I’m sorry then.
It worked for me, I installed pennylane in a google colab notebook.
I would probably get a lot of errors if I run locally, but this sample worked for me in colab.

Oh, no worries! Thank you so much for the idea! Could you provide the output of qml.about()in Google Colab?

It turns out that this issue is solved in Pennylane’s version 0.34, so now both codes work! Thank you @Alex for your help! Now I have an issue when creating a keras layer, but I’ll open another discussion topic!

1 Like

Ok, that is good to know. You’re welcome!

1 Like

Hey @Laia_Domingo! Welcome to the forum :slight_smile: