0
$\begingroup$

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

$\endgroup$

2 Answers 2

0
$\begingroup$

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

Is that an answer? :)

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! :)

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

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.

$\endgroup$
1
  • $\begingroup$ ok, what is the role/use of label in QuantumCircuit.x() ? $\endgroup$ May 10 at 8:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.