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

How to get the unitary matrix of a given kernel #1822

Open
ACE07-Sev opened this issue Jun 16, 2024 · 9 comments
Open

How to get the unitary matrix of a given kernel #1822

ACE07-Sev opened this issue Jun 16, 2024 · 9 comments
Labels
enhancement New feature or request language Anything related to the CUDA Quantum language specification
Milestone

Comments

@ACE07-Sev
Copy link

Greetings there,

Hope all are well. I would like to know how I can get the unitary matrix of a circuit in cudaq. I've seen .sample() and .get_state() for counts and statevector definitions, but haven't been able to find the unitary matrix definition. Thanks in advance!

@bettinaheim bettinaheim added this to the release 0.8.0 milestone Jul 1, 2024
@schweitzpgi schweitzpgi added enhancement New feature or request language Anything related to the CUDA Quantum language specification labels Jul 5, 2024
@bettinaheim
Copy link
Collaborator

Tentatively moving this to 0.9 for tracking, but this is not yet confirmed as planned.

@zohimchandani
Copy link
Collaborator

+1 for this since we need it for a collaboration, thanks.

@ACE07-Sev
Copy link
Author

ACE07-Sev commented Aug 22, 2024

I would make a few suggestions for this in the interest of performance. To get the unitary we have to do tensor contraction, and it gets expensive real fast as we increase the entanglement. With that being said, I would suggest using sth like cotengra or contengrust to find optimal order of contraction. Frankly, anything by Dr. Gray is usually very good for this type of operation.

Dr. Nguyen mentioned these have to be accessible in C++, so I'll have a look for any alternatives for this in C++.

Ohh, and one thing. It would be great if you don't do this as we add gates. Some packages (I believe qiskit) do this which adds alot of overhead for deep circuits. I imagine it would be better to contract it at the end if the user wants a unitary matrix of the overall circuit. This also makes it easier to use JIT, or GPU-acceleration for performing this.

@ACE07-Sev
Copy link
Author

Greetings there,

Hope all are well. May I ask if there's an expected timeline for when this feature will be done?

@zohimchandani
Copy link
Collaborator

You can use this hack in the meantime if it helps:

import cudaq 
import numpy as np
from typing import List


num_qubits = 2
input_state = [0.0] * (2**num_qubits)  #just input a zero state 
N = 2**num_qubits
U = np.zeros((N, N), dtype=np.complex128)
params = [1 ,2]

@cudaq.kernel
def kernel(params: List[float], input_state: List[complex]):

    qubits = cudaq.qvector(input_state)
    
    rx(params[0], qubits[0])
    ry(params[1], qubits[1])
    
    y.ctrl(qubits[0], qubits[1])
    

for j in range(N): 
    state_j    = np.zeros((N), dtype=np.complex128) 
    state_j[j] = 1.0
    
    U[:, j] = np.array(cudaq.get_state(kernel, params, state_j), copy=False)
    
print(U)

@ACE07-Sev
Copy link
Author

@zohimchandani Thank you!

@ACE07-Sev
Copy link
Author

ACE07-Sev commented Nov 4, 2024

A bit of an unrelated question, sorry (too small to open a ticket for). How can I pass a list of qubits here? It doesn't let me slice nor pass in a list:

# Create a `Kernel` that accepts a qubit as an argument.
# Apply an X-gate on that qubit.
target_kernel, qubit = cudaq.make_kernel(cudaq.qubit)
target_kernel.tdg(qubit)

# Create another `Kernel` that will apply `target_kernel`
# as a controlled operation.
kernel = cudaq.make_kernel()
qubits = kernel.qalloc(3)

# In this case, `control` performs the equivalent of a
# controlled-X gate between `control_qubit` and `target_qubit`.
kernel.control(target_kernel, qubits[:2], qubits[2])

print(cudaq.draw(kernel))

I want to add a controlled Tdg gate, with qubits 0 and 1 being the control indices, and qubit 2 being the target.

@zohimchandani
Copy link
Collaborator

See this for an example and let us know if that helps.

It is recommended that you switch to the new way of creating kernels with the @cudaq.kernel decorator as shown in the example.

@ACE07-Sev
Copy link
Author

Ohh I have read that. I am wrapping cuda-quantum in my package and I use a UI similar to qiskit, hence why I need the addition of the gates to be in form of methods as opposed to all in one with the decorator. Is there a way around it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request language Anything related to the CUDA Quantum language specification
Projects
None yet
Development

No branches or pull requests

4 participants