I would like to use the following method:
- qml.ControlledSequence(Grover_Iter(qubits = Orcl_Qubits), Ctrl_Qubits)
but I’m not sure how to define the unitary operator Grover_Iter. The problem is not Grover but the way that the unitary operator for the ControlledSequence has to be defined.
def Grover_Iter(qubits):
# Oracle for Grover -- totally arbitrary
qml.PauliX (qubits[-2])
qml.PauliX (qubits[-1])
qml.Hadamard (qubits[-1])
qml.Toffoli (qubits[-3:])
qml.Hadamard (qubits[-1])
qml.PauliX (qubits[-1])
qml.PauliX (qubits[-2])
# Grover Diffuser
for q in qubits:
qml.Hadamard(q)
qml.PauliX(q)
control_wires = qubits[:-1]
qml.Hadamard(qubits[-1])
qml.MultiControlledX(wires=(*control_wires, qubits[-1]))
qml.Hadamard(qubits[-1])
for q in qubits:
qml.PauliX(q)
qml.Hadamard(q)
return (qml.Identity(qubits[0]))
At the beginning, I didn’t return anything. I got the error: AttributeError: ‘NoneType’ object has no attribute ‘wires’.
Based on this implementation, my counting program based on QPE is not working as expected.
Hi @jmrobert How great that you are working on this!
qml.ControlledSequence
expects you to send an operation but you are sending a quantum function. If you add
@qml.prod
decorating your quantum function Grover_Iter
, it will work
Let me know if you have any issue
Hi @jmrobert welcome to the Forum!
It’s great to see you exploring PennyLane. I have two suggestions with code examples that can help you.
Option 1
We have a GroverOperator template which can be exactly what you’re looking for. Below is a code example of how to use it.
n_wires = 3
dev = qml.device('default.qubit', wires=n_wires)
@qml.qnode(dev)
def circuit():
qml.ControlledSequence(qml.templates.GroverOperator(wires=range(1,n_wires)), 0)
return qml.probs()
qml.draw_mpl(circuit, expansion_strategy='device', decimals=1)();
Option 2
Now if instead you want to do the controlled sequence for the full quantum function that you had before, in that case you must use an operator. One way of turning your quantum function into an operator is first obtaining the matrix representation of the circuit and then using qml.QubitUnitary to turn it into an operator. The code example below should help you understand this:
def Grover_Iter(qubits):
# Oracle for Grover -- totally arbitrary
qml.PauliX (qubits[-2])
qml.PauliX (qubits[-1])
qml.Hadamard (qubits[-1])
qml.Toffoli (qubits[-3:])
qml.Hadamard (qubits[-1])
qml.PauliX (qubits[-1])
qml.PauliX (qubits[-2])
# Grover Diffuser
for q in qubits:
qml.Hadamard(q)
qml.PauliX(q)
control_wires = qubits[:-1]
qml.Hadamard(qubits[-1])
qml.MultiControlledX(wires=(*control_wires, qubits[-1]))
qml.Hadamard(qubits[-1])
for q in qubits:
qml.PauliX(q)
qml.Hadamard(q)
n_wires = 6
# Draw your original circuit
qml.draw_mpl(Grover_Iter)(qubits = [3,4,5])
# Turn it into a matrix
mat = qml.matrix(Grover_Iter,wire_order=[3,4,5])(qubits = [3,4,5])
# Turn the matrix into an operator
op = qml.QubitUnitary(mat, wires=[3,4,5])
# Use the operator within your QNode to create your controlled sequence
dev = qml.device('default.qubit', wires=n_wires)
@qml.qnode(dev)
def example_circuit():
qml.ControlledSequence(op, [0,1,2])
return qml.expval(qml.Z(0))
# Draw your controlled sequence
qml.draw_mpl(example_circuit,expansion_strategy='device')();
Please let me know if this answers your question and let me know if you have any others!
Ah I just saw @Guillermo_Alonso’s answer. That’s a great solution too! Probably the best one overall.