# Qubit Connectivity of IBM Quantum Computer

When simulating a quantum circuit using qiskit qasm_simulator, the qubits that you assigned to the quantum circuit can be connected to all other qubits, or say, if there are $$n$$ qubits in the quantum circuit, for a single qubit it can interact with all other $$n-1$$ qubits.

This is quite an unpractical hypothesis for real quantum computation. k-local is a common criterion for a quantum computer and the only quantum computer I know that have full qubit-connectivity is this one(apparently I omitted the trivial case, single- or two-qubit quantum computer). In the case of quantum devices that IBM provided online access, e.g., 5-qubit ibmq_santiago, 5-qubit ibmq_5_yorktown, and 15-qubit ibmq_16_melbourne, all provided limited qubit connectivity.

So here arises my question: when designing a quantum circuit we have to take qubit connectivity into consideration, but how qiskit works at this phase? Does it assign the job automatically(so the quantum circuit can still work), or should I pre-assign my logical qubits to the real qubits of the IBM quantum computer one-by-one(and if so, how?)?

You can pass the parameter coupling_map to execute or transpile. This allows to simulate a specific connectivity schema as a list of edges.

The transpiling process (implicit during the execution process) takes care of adapting your circuit to the specific limitations from the backend or to the given limitations such as coupling_map parameter. You can also control parts of that adaptation with parameters like initial_layout (you can define in which physical qubit you want to allocate your circuit).

Take the following example:

from qiskit import *

circuit = QuantumCircuit(3)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.cx(2, 0)
circuit.draw('mpl')


This circuit requires a directed circular connectivity map. By default, transpiling this circuit takes a fully connected map, so it has no changes:

transpiled = transpile(circuit)
transpiled.draw('mpl')


If you want to add the restriction of a particular connectivity map, you can do that with coupling_map. In this case, it is a directed linear connectivity $$0 \rightarrow 1 \rightarrow 2$$:

transpiled = transpile(circuit, coupling_map=[[0,1], [1,2]])
transpiled.draw('mpl')


Notice that a SWAP gate was added and the direction of CNOT was corrected. Also, the qubit allocation is showed in the left-hand side (e.g. $$q_0$$ was allocated in the qubit $$2$$.

You can control the qubit allocation with the parameter initial_layout. In the following example, $$q_0$$ is forced to be allocated in the qubit 0 and so on:

transpiled = transpile(circuit, coupling_map=[[0,1], [1,2]], initial_layout=[0, 1, 2])
transpiled.draw('mpl')


Qiskit usually does the layout automatically, and it will do so by considering the device you are using (i.e. the qubits connectivity), of course the circuit, and the optimisation level. You can see a brief explanation on the Initial Layout part related to the optimisation level here. You will find explanation as well about this in the Mapping circuits to hardware technology part about the importance of a good layout for optimising the circuit and having the best results possible in the end.

You can also do it yourself. Here, you will find all of the layout selections already in Qiskit; as you can see there are a lot of ways to do this. You can also directly put the layout you wish when running your circuit in the execute function.
Maybe if you want to play with those to better understand the difference, I would suggest to either simply try them on real hardware or on a simulator by also adding the CouplingMap and see where this leads you !

I hope this helps :)

Just to add to the other two good answers, we don't just have qubit layout constraint but also available gates. For instance, SWAP gate or an arbitrary two qubit controlled gate is not being implemented directly as a native gate on current hardware. This is something we should take into account when transpiled the circuit as well.

Fr example, let's us take a similar circuit to the one given by @Luciano:

setting basis_gates= ['u1', 'u2', 'u3', 'cx'] in your transpile call, you might get something like this: