Skip to content

create a new branch for upgrading to qiskit 1.3 #295

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .cursorignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
docs/
examples/
figs/
5 changes: 3 additions & 2 deletions examples/QuantumNAS/quantumnas.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -4056,7 +4056,8 @@
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"display_name": "torchquantum",
"language": "python",
"name": "python3"
},
"language_info": {
Expand All @@ -4069,7 +4070,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.16"
"version": "3.9.20"
},
"widgets": {
"application/vnd.jupyter.widget-state+json": {
Expand Down
7 changes: 4 additions & 3 deletions test/qiskit_plugin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
get_expectations_from_counts,
find_global_phase,
)
from test.static_mode_test import QLayer as AllRandomLayer
from static_mode_test import QLayer as AllRandomLayer
from torchquantum.plugin import tq2qiskit
from torchquantum.macro import F_DTYPE

Expand All @@ -54,11 +54,12 @@ def unitary_tq_vs_qiskit_test():
qiskit_compatible=True,
)

unitary_tq = q_layer.get_unitary(q_dev, x)
# unitary_tq = q_layer.get_unitary(q_dev, x)
unitary_tq = q_layer.get_unitary(x)
unitary_tq = switch_little_big_endian_matrix(unitary_tq.data.numpy())

# qiskit
circ = tq2qiskit(q_layer, x)
circ = tq2qiskit(q_dev, q_layer, x)
simulator = Aer.get_backend("unitary_simulator")
result = execute(circ, simulator).result()
unitary_qiskit = result.get_unitary(circ)
Expand Down
20 changes: 17 additions & 3 deletions test/static_mode_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,20 @@ def build_random_funcs(self):
cnt = 0
while cnt < self.n_funcs:
func = np.random.choice(self.funcs)
n_func_wires = op_name_dict[func]().num_wires
# print(f"Selected function: {func}")

"""
ORIGINAL: n_func_wires = op_name_dict[func]().num_wires
Changed to avoid initialization error with QubitUnitaryFast which requires
parameters during instantiation. Instead, we access num_wires directly
from the class since it's a class attribute.
"""

op_class = op_name_dict[func]
# print(f"Operator class: {op_class}")
# print(f"Number of wires: {op_class.num_wires}")
n_func_wires = op_class.num_wires

if n_func_wires > self.n_wires:
continue
cnt += 1
Expand Down Expand Up @@ -191,8 +204,9 @@ def forward(self, q_device: tq.QuantumDevice, x):
self.func_list, self.func_wires_list, self.func_inverse
):
n_func_wires = len(func_wires)
n_func_params = op_name_dict[func]().num_params

op_class = op_name_dict[func]
# n_func_params = op_name_dict[func]().num_params
n_func_params = op_class.num_params
if n_func_params == 0:
if func in ["multicnot", "multixcnot"]:
func_name_dict[func](
Expand Down
4 changes: 2 additions & 2 deletions torchquantum/functional/u1.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def u1(

"""
name = "u1"
mat = mat_dict[name]
mat = _u1_mat_dict[name]
gate_wrapper(
name=name,
mat=mat,
Expand Down Expand Up @@ -157,7 +157,7 @@ def cu1(

"""
name = "cu1"
mat = mat_dict[name]
mat = _u1_mat_dict[name]
gate_wrapper(
name=name,
mat=mat,
Expand Down
4 changes: 2 additions & 2 deletions torchquantum/functional/u2.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def u2(

"""
name = "u2"
mat = mat_dict[name]
mat = _u2_mat_dict[name]
gate_wrapper(
name=name,
mat=mat,
Expand Down Expand Up @@ -156,7 +156,7 @@ def cu2(

"""
name = "cu2"
mat = mat_dict[name]
mat = _u2_mat_dict[name]
gate_wrapper(
name=name,
mat=mat,
Expand Down
15 changes: 11 additions & 4 deletions torchquantum/graph/graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,17 @@ def add_func(
if not self.is_list_finish:
# graph construction is not finished, build a new operation and
# add the operation to the graph
op = tq.op_name_dict[name]()
op.params = params
op.n_wires = n_wires
op.wires = wires
print(tq.op_name_dict[name])
# op = tq.op_name_dict[name]()
op_class = tq.op_name_dict[name]
op = op_class(has_params=True if params is not None else False,
trainable=False,
init_params=params,
n_wires=n_wires,
wires=wires)
# op.params = params
# op.n_wires = n_wires
# op.wires = wires
op.graph = tq.QuantumGraph()
op.parent_graph = parent_graph
op.static_mode = True
Expand Down
16 changes: 15 additions & 1 deletion torchquantum/measurement/measurements.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,22 @@ def measure(qdev, n_shots=1024, draw_id=None):
Returns:
distribution of bitstrings
"""
bitstring_candidates = gen_bitstrings(qdev.n_wires)

"""
In measure function, the statevector is copied to the CPU and
a list of all possible 2^n bitstrings is constructed to do the sampling.
This is again a huge CPU memory and runtime overhead since sampling can done on the GPU directly and efficiently.
Here is a sketch of how that might look like in PyTorch using Inverse transform sampling method:
Calculate squared amplitudes on GPU using troch.abs and troch.square.
Calculate the cumulative distribution function using troch.cumsum.
Generate random numbers (as many as the required number of samples) between 0 and 1 using torch.rand.
Find the index of each random number inside the cumulative distribution using troch.searchsorted.
Copy the indices to the CPU and convert each number to its bitstring binary representation.
"""

bitstring_candidates = gen_bitstrings(qdev.n_wires) # length is 2 to the power of n_wires
if isinstance(qdev, tq.QuantumDevice):
# length is 2 to the power of n_wires
state_mag = qdev.get_states_1d().abs().detach().cpu().numpy()
elif isinstance(qdev, tq.NoiseDevice):
'''
Expand Down
5 changes: 5 additions & 0 deletions torchquantum/operator/op_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
import torchquantum as tq
import torchquantum.functional.functionals as tqf
import numpy as np
import logging
from abc import ABCMeta
from ..macro import C_DTYPE, F_DTYPE
from typing import Iterable, Union, List
from enum import IntEnum


# Add logging init
logger = logging.getLogger(__name__)

__all__ = [
"Operator",
"Operation",
Expand Down
Loading