# Circuits acting on subsets of qubits in other circuits

I am trying to figure out what is the best way of dealing with registers while constructing circuits from abstract blocks. Consider the following subcircuit:

$$$$U|x\rangle|y\rangle|z\rangle = \ldots \,,\\$$$$ where neither the sizes nor the order of registers are not known in advance. Assume I want to append $$U(x,y,z)$$ and $$U(y,z,w)$$ to an existing circuit with $$x,y,z,w$$ registers. The following construction would be ideal for me, but it is not supported:

def U(
x : QuantumRegister,
y : QuantumRegister,
z : QuantumRegister,
) -> QuantumCircuit:
qc = QuantumCircuit( list(x) + list(y) + list(z)  )
qc.x(0)
qc.y(1)
qc.cx(z[0],z[1])
return qc

qc = QuantumCircuit(4)
input_circuit = QuantumCircuit( qc.qubits ) # This is more realistic than just qc
x,y,z,w = [ qc.qubits[0] ],\
[ qc.qubits[1] ],\
[ qc.qubits[2], qc.qubits[3] ],\
[ qc.qubits[3], qc.qubits[2] ]
print( U( x, y, z ) )
print( U( x, y, w ) )


However , note that the following code fails to run:

print(
input_circuit + U( x, y, z ) + U( x, y, w )
)


Yet this code works (but with a DeprecationWarning suggesting that I should instead use inequivalent compose(), see below):

print(
qc + U( x, y, z ) + U( x, y, w )
)


In other words, qiskit only works correctly with circuits having a QuantumRegister. But there is no way of assembling QuantumRegister from existing Qubits. Neither can one combine Qubits into a QuantumRegister in an existing circuit.

Instead of + one can try using compose(), but compose() ignores qubit ordering unless provided explicitly. Moreover, the qubits from the second circuit are mapped on those from the first one simply according to the order of qubits in the first one, but not according to their names — unlike the solution with + (which only works if the QuantumRegister is present in the first circuit).

Anyways, let me try to formulate the question precisely. Assume I'm starting from some input_circuit.

What is the best way of coding up functions which return circuits acting on particular subsets of input_circuit.qubits?

You can you QuantumCircuit.append(). This way you can distinguish between how the function U is called, and how the returned circuit will be embedded:
input_circuit.append( U( x, y, z ), x + y + z)

• To my understanding, the way append() interprets the second argument is similar to the way it's done in compose(): the names of qubits in the second circuit are simply ignored, and the qubits are mapped in their order of appearance in the second circuit. Unlike that, "+" is matching qubits with identical names. So I was wondering what would be the best way to implement this behavior. May 25 at 18:25