# understanding QuantumCircuit.x() function

For Code 1 qc.x(0,1) throws error but not for code 2 . Please help me to understand

code 1

qc = QuantumCircuit(2)
qc.x(0,1)
qc.draw()


The above code throws following error:

Traceback (most recent call last):
Input In [19] in <cell line: 3>
qc.draw()
File /opt/conda/lib/python3.8/site-packages/qiskit/circuit/quantumcircuit.py:1835 in draw
return circuit_drawer(
File /opt/conda/lib/python3.8/site-packages/qiskit/visualization/circuit_visualization.py:231 in circuit_drawer
image = _matplotlib_circuit_drawer(
File /opt/conda/lib/python3.8/site-packages/qiskit/visualization/circuit_visualization.py:601 in _matplotlib_circuit_drawer
return qcd.draw(filename)
File /opt/conda/lib/python3.8/site-packages/qiskit/visualization/matplotlib.py:317 in draw
self._get_layer_widths()
File /opt/conda/lib/python3.8/site-packages/qiskit/visualization/matplotlib.py:433 in _get_layer_widths
and len(gate_text) < 3
TypeError: object of type 'int' has no len()

Use %tb to get the full traceback.


Note: qc.x(1,0) work fine. why is it throwing error for putting X gate at q0?

Code 2

from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

qc = QuantumCircuit(2)
ket = Statevector(qc)
print(ket.draw())
print('-'*50)

qc.x(0,1)
ket = Statevector(qc)
print(ket.draw())
print('-'*50)


output

Statevector([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
dims=(2, 2))
--------------------------------------------------
Statevector([0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],
dims=(2, 2))
--------------------------------------------------


I have gone through the documentation but couldn't find the answer https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.x.html

In Code 1 you are trying to draw QuantumCircuit, not ket.
Error goes directly from code which tries to print quantum circuit in output type 'mpl' (line 231):

    elif output == "mpl":
image = _matplotlib_circuit_drawer(


Normally in draw method you should provide output type (text, latex, mpl ...):

qc.draw('mpl')


But when it is not provided then default value should be taken:

def circuit_drawer(
...
default_output = "text"  # <- here is default output set
if config: # <- there should be some cnfig somewere?
default_output = config.get("circuit_drawer", "text")
if default_output == "auto":
if _optionals.HAS_MATPLOTLIB:
default_output = "mpl"  # <- with config somewhere and default_output == "auto" and _optionals.HAS_MATPLOTLIB default_output is redefined to 'mpl'
else:
default_output = "text"
if output is None:
output = default_output
...
elif output == "mpl":
image = _matplotlib_circuit_drawer(


And the default value should be text.
But what I see from the code is that if there is some config? and default_output is auto? and project uses matplotlib? then default_output is set to 'mpl'?
I am not familiar with Python, neither Qiskit but for debugging I suggest to provide output type explicitly and verify what will happen:

qc.draw('mpl')  # 'text', 'latex', 'latex_source' etc.


So this is how we looked at source code raising error without any knowledge about Python and Qiskit.

But before trying to deep dive in such complex code let's check something simple, first try to define

qc.x(0,1)


as

qc.x(0,'1')


because source code says that the second argument is string and not integer:

    def x(self, qubit: QubitSpecifier, label: Optional[str] = None) -> InstructionSet:
r"""Apply :class:~qiskit.circuit.library.XGate.

For the full matrix form of this gate, see the underlying gate documentation.

Args:
qubit: The qubit(s) to apply the gate to.
label: The string label of the gate in the circuit.


and maybe that is the reason for error that gate can't be visualized as suggested in that line:

  File /opt/conda/lib/python3.8/site-packages/qiskit/visualization/matplotlib.py:433 in _get_layer_widths
and len(gate_text) < 3


Where this string label is used? We can see from the code below:

    def x(self, qubit: QubitSpecifier, label: Optional[str] = None) -> InstructionSet:
r"""Apply :class:~qiskit.circuit.library.XGate.

For the full matrix form of this gate, see the underlying gate documentation.

Args:
qubit: The qubit(s) to apply the gate to.
label: The string label of the gate in the circuit.

Returns:
A handle to the instructions created.
"""
from .library.standard_gates.x import XGate

return self.append(XGate(label=label), [qubit], [])


XGate is defined here:
\qiskit-terra\qiskit\circuit\library\standard_gates\x.py:

    def __init__(self, label: Optional[str] = None):
"""Create new X gate."""
super().__init__("x", 1, [], label=label)
...
def control(
self,
num_ctrl_qubits: int = 1,
label: Optional[str] = None,
ctrl_state: Optional[Union[str, int]] = None,
):
"""Return a (multi-)controlled-X gate.

One control returns a CX gate. Two controls returns a CCX gate.

Args:
num_ctrl_qubits (int): number of control qubits.
label (str or None): An optional label for the gate [Default: None]


So analysing the code above or any next code we will find its usage at some point.

I see inheritance from Gate class where we have label:

class Gate(Instruction):
"""Unitary gate."""

def __init__(
self, name: str, num_qubits: int, params: List, label: Optional[str] = None
) -> None:
"""Create a new gate.

Args:
name: The Qobj name of the gate.
num_qubits: The number of qubits the gate acts on.
params: A list of parameters.
label: An optional label for the gate.


and then in Instruction class label is present too:

class Instruction:
"""Generic quantum instruction."""
...
label (str or None): An optional label for identifying the instruction.
Raises:
CircuitError: when the register is not in the correct format.
TypeError: when the optional label is provided, but it is not a string.


Do you see that?

TypeError: when the optional label is provided, but it is not a string.


We have got to the error in source code :)

Then we have a code that smells ... badly? :)

        # Custom instruction label
# NOTE: The conditional statement checking if the _label attribute is
#       already set is a temporary work around that can be removed after
#       the next stable qiskit-aer release
if not hasattr(self, "_label"):
if label is not None and not isinstance(label, str):
raise TypeError("label expects a string or None")
self._label = label


Well, at that point we need to investigate what is going on because the purpose of that label should be rather obvious when exposed on such a high level of X gate, unless it propagates through all classes just to be used for some specific reason in classes below...
But then it should be commented better on the highest level...

Let's check documentation:
https://qiskit.org/documentation/stubs/qiskit.circuit.library.XGate.html

label¶
Return instruction label

Return type
str


Ok, so it looks like purpose of label is to use in Instruction class.
This is very generic class:

class Instruction:
"""Generic quantum instruction."""

# Class attribute to treat like barrier for transpiler, unroller, drawer
# NOTE: Using this attribute may change in the future (See issue # 5811)
...
def __init__(self, name, num_qubits, num_clbits, params, duration=None, unit="dt", label=None):
"""Create a new instruction.
...
label (str or None): An optional label for identifying the instruction.

Raises:
CircuitError: when the register is not in the correct format.
TypeError: when the optional label is provided, but it is not a string.


Still I do not know how it is uased but after using Google I have found that interesting ticket:
https://github.com/Qiskit/qiskit-terra/issues/3766

MPL drawer should prioritize instruction label over name #3766
When an instruction has a label, the label should be used. If a no-boxing instruction has a label, a box should be used.


I have found yet another interesting link which may suggest that the code we have was created for specific reason:

How to plot custom gate labels in Qiskit?

And the last link where custom gate is using 'label' and for sure inherits from Gate and Instruction classes:

Custom labelling of randomly generated unitaries in Qiskit

Bingo! :)

• I got the code from qiskit textbook.... you are right that 2nd argument should be a string...thanks May 10, 2022 at 8:29
• Ok, but let's investigate what is usage of that optional 'label' argument. May 10, 2022 at 8:39
• Exactly, I am also looking in it....please let me know you get it before me...thanks May 10, 2022 at 8:41
• I think that clarifies usage of 'label' for custom ad-hoc created gates: quantumcomputing.stackexchange.com/questions/18371/… May 10, 2022 at 9:10

The error is thrown by QuantumCircuit.draw() method. And since you didn't call it in the second snippet, the error did not happen.

When you pass two parameters to QuantumCircuit.x(), the second parameter is considered as its label so both qc.x(0, '1') and qc.x(1, '0') should work.