Is there an easy and general way to copy quantum operations changing their parameters?

In a @transform I would like to go through a tape and change the parameters of some types of gates. I thought this should be easy but it is not, or I am too stupid…

The general structure of my transform is as follows:

    new_operations = list()
    for operation in tape.operations:
        update_operation = [...]
        new_operations.append(update_operation)

        new_tape = type(tape)(new_operations, tape.measurements, shots=tape.shots)

    def postprocessing(results):
        return np.array(results)[0]

    return [new_tape], postprocessing

My problem is with the update_operation = [...] part. I would like this to work for general operations that have a single parameter.

My first idea was to simply make a copy of operation with copy.deepcopy() and then modify its .parameters, but the property cannot be set.

My second idea was to call the constructor of the class of operation with something like:

operation.__class__(
                        *new_parameters,
                        **operation.hyperparameters,
                        wires=operation.wires,
                    )

But this does not work for Adjoint operations. Of course I can add a if statement to treat that case (not elegant), but then it still does not work for controlled operations like qml.CRX because

print(qml.CRX(0.2, [0, 1]).hyperparameters)
{'control_wires': Wires([0]), 'control_values': [True], 'work_wires': Wires([]), 'base': RX(0.2, wires=[1])}

Is there an elegant way to take any operation that can appear on a tape and get a copy with modified parameters?

This is a good question @cvjjm, not stupid at all.

I’ll check with the team and get back to you.

Good news @cvjjm !

There’s a function qml.ops.functions.bind_new_parameters that for some reason doesn’t show up in the docs but it should work. You can use it as: bind_new_parameters(op, new_data). Here it is on GitHub.

Alternatively you could try flattening and unflattening:

struct, data = qml.pytrees.flatten(op) 
qml.pytrees.unflatten(struct, new_data)

Let me know if this solves your issue!