NVIDIA/cuda-quantum

Circuit drawer retains qubits from previously printed kernel(s)

Closed this issue · 6 comments

Required prerequisites

  • Consult the security policy. If reporting a security vulnerability, do not report the bug using this form. Use the process described in the policy to report the issue.
  • Make sure you've read the documentation. Your issue may be addressed there.
  • Search the issue tracker to verify that this hasn't already been reported. +1 or comment there if it has.
  • If possible, make a PR with a failing test to give us a starting point to work on!

Describe the bug

When using cudaq.draw API to print kernels, the qubits from previously drawn kernel are retained.
Redrawing the same kernel repeatedly also keeps concatenating to the qubit count.

Steps to reproduce the bug

import cudaq

@cudaq.kernel
def bell_pair():
    q = cudaq.qvector(2)
    h(q[0])
    cx(q[0], q[1])
    mz(q)


@cudaq.kernel
def kernel(angle:float):
    q = cudaq.qubit()
    h(q)
    ry(angle, q)

   
print(cudaq.draw(kernel, 0.59))
print(cudaq.draw(kernel, 0.59))
print(cudaq.draw(bell_pair))

Output:

root@b601c80e7f07:/workspaces/cuda-quantum/build# python3 test_draw.py 
     ╭───╮╭──────────╮
q0 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯

                      
q0 : ─────────────────
     ╭───╮╭──────────╮
q1 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯

               
q0 : ──────────
               
q1 : ──────────
     ╭───╮     
q2 : ┤ h ├──●──
     ╰───╯╭─┴─╮
q3 : ─────┤ x ├
          ╰───╯

Expected behavior

Expected output:

root@b601c80e7f07:/workspaces/cuda-quantum/build# python3 test_draw.py 
     ╭───╮╭──────────╮
q0 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯
          
     ╭───╮╭──────────╮
q0 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯

     ╭───╮     
q0 : ┤ h ├──●──
     ╰───╯╭─┴─╮
q1 : ─────┤ x ├
          ╰───╯

Is this a regression? If it is, put the last known working version (or commit) here.

Not a regression

Environment

  • CUDA Quantum version: main as of commit 30e1d3b
  • Python version: 3.10.12
  • C++ compiler:
  • Operating system: Ubuntu 22.04

Suggestions

No response

Reference C++ sample

#include <cudaq.h>
#include <cudaq/algorithms/draw.h>

#include <iostream>

auto bell_pair = []() __qpu__ {
  cudaq::qvector q(2);
  h(q[0]);
  x<cudaq::ctrl>(q[0], q[1]);
  mz(q);
};

auto kernel = [](float angle) __qpu__ {
  cudaq::qvector q(1);
  h(q[0]);
  ry(angle, q[0]);
};

int main() {
  std::cout << cudaq::draw(kernel, 0.59);
  std::cout << cudaq::draw(bell_pair);
  std::cout << cudaq::draw(kernel, 0.59);
  return 0;
}

Output:

     ╭───╮╭──────────╮
q0 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯
     ╭───╮     
q0 : ┤ h ├──●──
     ╰───╯╭─┴─╮
q1 : ─────┤ x ├
          ╰───╯
     ╭───╮╭──────────╮
q0 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯

I believe that this issue (or something similar to this issue) may also be preventing us from adding tests to the end of python/tests/kernel/test_kernel_features.py, so any fix to this issue should probably try to add tests like test_no_valueerror_np_array to the end of that file.

Update: The same behavior is seen in C++ when not in library mode.

Test code:

#include <cudaq.h>
#include <cudaq/algorithms/draw.h>

#include <iostream>

auto kernel = [](float angle) __qpu__ {
  cudaq::qvector q(1);
  h(q[0]);
  ry(angle, q[0]);
};

int main() {
  std::cout << cudaq::draw(kernel, 0.59);
  std::cout << cudaq::draw(kernel, 0.59);
  return 0;
}

Set LIBRARY_MODE=false in nvq++ and compile.

root@84c6eaffe15a:/workspaces/cuda-quantum/build# ./a.out 
     ╭───╮╭──────────╮
q0 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯
                      
q0 : ─────────────────
     ╭───╮╭──────────╮
q1 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯

I've experienced this again using version 0.8.0.

This time the incorrect circuits are slightly different than the example above.

incorrect output:
Image


@cudaq.kernel
def bell_pair():
    q = cudaq.qvector(2)
    h(q[0])
    cx(q[0], q[1])
    mz(q)


@cudaq.kernel
def kernel(angle:float):
    q = cudaq.qubit()
    h(q)
    ry(angle, q)

   
print(cudaq.draw(kernel, 0.59))
print(cudaq.draw(kernel, 0.59))
print(cudaq.draw(bell_pair))


restarting the python kernel seems to eliminate the error.