Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GlobalPhaseGate causing circuit.depth() error #12426

Closed
ACE07-Sev opened this issue May 17, 2024 · 2 comments · Fixed by #12429
Closed

GlobalPhaseGate causing circuit.depth() error #12426

ACE07-Sev opened this issue May 17, 2024 · 2 comments · Fixed by #12429
Labels
bug Something isn't working mod: circuit Related to the core of the `QuantumCircuit` class or the circuit library
Milestone

Comments

@ACE07-Sev
Copy link

Environment

  • Qiskit version: 1.0.2
  • Python version: 3.11.9
  • Operating system: Windows

What is happening?

Greetings,

Hope all are well. I have noticed that when you apply the GlobalPhaseGate to a circuit, and then try to retrieve the depth of the circuit, it causes an error due to the GlobalPhaseGate instruction not using any qubit indices. I think this should be fixed inside the .depth() method as perhaps a special case.

How can we reproduce the issue?

from qiskit import QuantumCircuit, transpile
from qiskit.circuit.library import GlobalPhaseGate


qc_qiskit = QuantumCircuit(2, 2)

qc_qiskit.cx(0, 1)

transpiled_qc = transpile(qc_qiskit,
                          basis_gates=['u3', 'cx'],
                          optimization_level=3,
                          seed_transpiler=0)

transpiled_qc.append(GlobalPhaseGate(2.5928519981876477), [], [])

transpiled_qc.global_phase

transpiled_qc.depth()

This will output the following error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[15], [line 19](vscode-notebook-cell:?execution_count=15&line=19)
     [15](vscode-notebook-cell:?execution_count=15&line=15) transpiled_qc.append(GlobalPhaseGate(2.5928519981876477), [], [])
     [17](vscode-notebook-cell:?execution_count=15&line=17) transpiled_qc.global_phase
---> [19](vscode-notebook-cell:?execution_count=15&line=19) transpiled_qc.depth()

File c:\Users\A.C.EA\OneDrive\Documents\GitHub\QICKIT\.venv\Lib\site-packages\qiskit\circuit\quantumcircuit.py:1909, in QuantumCircuit.depth(self, filter_function)
   [1906](file:///C:/Users/A.C.EA/OneDrive/Documents/GitHub/QICKIT/.venv/Lib/site-packages/qiskit/circuit/quantumcircuit.py:1906)             reg_ints.append(idx)
   [1907](file:///C:/Users/A.C.EA/OneDrive/Documents/GitHub/QICKIT/.venv/Lib/site-packages/qiskit/circuit/quantumcircuit.py:1907)             levels.append(op_stack[idx] + 1)
-> [1909](file:///C:/Users/A.C.EA/OneDrive/Documents/GitHub/QICKIT/.venv/Lib/site-packages/qiskit/circuit/quantumcircuit.py:1909) max_level = max(levels)
   [1910](file:///C:/Users/A.C.EA/OneDrive/Documents/GitHub/QICKIT/.venv/Lib/site-packages/qiskit/circuit/quantumcircuit.py:1910) for ind in reg_ints:
   [1911](file:///C:/Users/A.C.EA/OneDrive/Documents/GitHub/QICKIT/.venv/Lib/site-packages/qiskit/circuit/quantumcircuit.py:1911)     op_stack[ind] = max_level

ValueError: max() arg is an empty sequence

What should happen?

Inside the .depth() method, the code should simply pass when the instruction is a GlobalPhaseGate. Since it's not, because GlobalPhaseGate has no qubit index as parameter, it causes the levels variable to be [], thus raising the error.

Any suggestions?

I tried this and it worked:

def depth(
        self,
        filter_function: Callable[..., int] = lambda x: not getattr(
            x.operation, "_directive", False
        ),
    ) -> int:
        """Return circuit depth (i.e., length of critical path).

        Args:
            filter_function (callable): A function to filter instructions.
                Should take as input a tuple of (Instruction, list(Qubit), list(Clbit)).
                Instructions for which the function returns False are ignored in the
                computation of the circuit depth.
                By default filters out "directives", such as barrier or snapshot.

        Returns:
            int: Depth of circuit.

        Notes:
            The circuit depth and the DAG depth need not be the
            same.
        """
        # Assign each bit in the circuit a unique integer
        # to index into op_stack.
        bit_indices: dict[Qubit | Clbit, int] = {
            bit: idx for idx, bit in enumerate(self.qubits + self.clbits)
        }

        # If no bits, return 0
        if not bit_indices:
            return 0

        # A list that holds the height of each qubit
        # and classical bit.
        op_stack = [0] * len(bit_indices)

        # Here we are playing a modified version of
        # Tetris where we stack gates, but multi-qubit
        # gates, or measurements have a block for each
        # qubit or cbit that are connected by a virtual
        # line so that they all stacked at the same depth.
        # Conditional gates act on all cbits in the register
        # they are conditioned on.
        # The max stack height is the circuit depth.
        for instruction in self._data:
            levels = []
            reg_ints = []
            for ind, reg in enumerate(instruction.qubits + instruction.clbits):
                # Add to the stacks of the qubits and
                # cbits used in the gate.
                reg_ints.append(bit_indices[reg])
                if filter_function(instruction):
                    levels.append(op_stack[reg_ints[ind]] + 1)
                else:
                    levels.append(op_stack[reg_ints[ind]])
            # Assuming here that there is no conditional
            # snapshots or barriers ever.
            if getattr(instruction.operation, "condition", None):
                # Controls operate over all bits of a classical register
                # or over a single bit
                if isinstance(instruction.operation.condition[0], Clbit):
                    condition_bits = [instruction.operation.condition[0]]
                else:
                    condition_bits = instruction.operation.condition[0]
                for cbit in condition_bits:
                    idx = bit_indices[cbit]
                    if idx not in reg_ints:
                        reg_ints.append(idx)
                        levels.append(op_stack[idx] + 1)

            if getattr(instruction.operation, 'name') == 'global_phase':
                levels = [0]

            max_level = max(levels)
            for ind in reg_ints:
                op_stack[ind] = max_level

        return max(op_stack)
@ACE07-Sev ACE07-Sev added the bug Something isn't working label May 17, 2024
@t-imamichi t-imamichi added the mod: circuit Related to the core of the `QuantumCircuit` class or the circuit library label May 17, 2024
@jakelishman jakelishman added this to the 1.1.1 milestone May 17, 2024
@jakelishman
Copy link
Member

Thanks for the report - this looks like a clear mistake in depth. I can post a PR in a sec that does a little bit of tidying up of the function and makes it handle a few other things it's currently missing.

@ACE07-Sev
Copy link
Author

Greetings dear @jakelishman,

Hope you are well. May I ask when the commit will be merged so that I can pip install it in my environment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working mod: circuit Related to the core of the `QuantumCircuit` class or the circuit library
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants