Open cvjjm opened 3 months ago
Thanks @cvjjm, definitely something we want to improve down the line!
Are there any particular ones in the list that have come up which you would find useful?
They all would have been useful at some point to me and some of them I had also implemented at some point...
For the merging/deleting of the global phase I still have this code lying around:
@transform
def merge_global_phase(tape: QuantumTape, remove=False) -> (Sequence[QuantumTape], Callable):
filtered_operations = list()
global_phase = 0
for operation in tape.operations:
if isinstance(operation, qml.GlobalPhase):
global_phase += operation.parameters[0]
else:
filtered_operations.append(operation)
if remove is False and global_phase != 0:
filtered_operations.append(qml.GlobalPhase(global_phase))
if compatibility_mode:
new_tape = type(tape)(filtered_operations, tape.measurements)
else:
new_tape = type(tape)(filtered_operations, tape.measurements, shots=tape.shots)
def postprocessing(results):
return np.array(results)[0]
return [new_tape], postprocessing
Note that qml.simplify
does simplify adjoints where possible:
@qml.simplify
@qml.qnode(qml.device('default.qubit'))
def circuit(x):
qml.adjoint(qml.RX(x,0))
qml.adjoint(qml.X(0))
return qml.state()
qml.draw(circuit, level=1)(0.5)
0: ──RX(12.07)──X─┤ State
Though it will also perform other simplications.
Note that
qml.simplify
does simplify adjoints where possible:@qml.simplify @qml.qnode(qml.device('default.qubit')) def circuit(x): qml.adjoint(qml.RX(x,0)) qml.adjoint(qml.X(0)) return qml.state() qml.draw(circuit, level=1)(0.5)
0: ──RX(12.07)──X─┤ State
Though it will also perform other simplications.
To avoid oversimplifying, you can also set the lazy
keyword argument of qml.adjoint
to False
, which will cause the operators to eagerly replace Adjoint
with updated parameters.
@qml.qnode(qml.device('default.qubit'))
def circuit(x):
qml.adjoint(qml.RX(x,0), lazy=False)
qml.adjoint(qml.X(0), lazy=False)
return qml.state()
print(qml.draw(circuit, level=1)(0.5))
0: ──RX(-0.50)──X─┤ State
I must say that a transform with an "obscure" name such as simplify that does not really tell me what it does and potentially does things I do not want, which I then have to switch off with another option with an obscure name such as "lazy" is less useful than a collection of transforms with descriptive names (so that they can be found easily via search or by glancing over the list) that do exactly one thing and do it well, and which I can then chain together in exactly the order I want.
Here are a two more for the wish list:
0: ─╭●─────────────────────┤
1: ─│─────────╭●─╭●────────┤
2: ─╰RY(0.10)─╰X─│─────────┤
3: ──────────────╰RY(0.50)─┤
into
0: ─╭●─────────────────────┤
1: ─│─────────╭●────────╭●─┤
2: ─╰RY(0.10)─│─────────╰X─┤
3: ───────────╰RY(0.50)────┤ ```
Further it would be nice if the transforms would get a dedicated page in the documentation. Currently they are a bit hidden as a subsection of the API part.
Hi @cvjjm , you raise some very good points. Thank you very much for these suggestions. Would any of the things in the wish list have higher priority for you than the others?
Feature details
PennyLane ships a few useful transform, but some obvious one that would be nice to have are missing. These include for example transforms that:
While I understand that it will never be possible to cover all transforms a user could ever want, an added benefit of a slightly larger library of transforms would that there are more templates for users to start implementing their own transforms from.
Implementation
No response
How important would you say this feature is?
1: Not important. Would be nice to have.
Additional information
No response