Closed nabe98 closed 11 months ago
Could you change the measure
method in the StatevectorBackend
to trace out measured qubits individually?
Thank you for reviewing!
Could you add more test cases? At least include the following measurement commands
- measure into |0>
- measure into |1>
- non-Pauli measurement
I added test_measurement_into_each_XYZ_basis
to test these.
Could you change the
measure
method in theStatevectorBackend
to trace out measured qubits individually?
I also added test_with_rand_circuit_sim
to test for this simulation.
Thanks for your commitment! Your code looks great, but I would like to mention one minor point: the state vector backend should not depend on the pattern or circuit simulator. Therefore, it's preferable to avoid them in the unit tests. So, I have removed the random circuit check.
@nabe98 Before merging, can you write the changes to CHANGELOG.md?
@nabe98 please let me know once you updated CHANGELOG.md. Please do not merge yet.
Also remember we always prefer squash and merge
to keep the commit history concise on master branch :)
@shinich1 also updated CHANGELOG.md
. Please check them!
I've conducted benchmarks for the new method.
[Environment] CPU: intel i7-12700K RAM: 64GB (DDR4-3200) OS: Ubuntu 20.04 (WSL)
The following graph shows a performance comparison between reduce_qubit
and ptrace
when simulating n (width) x n (depth) random square circuits.
I also benchmarked shallow (depth=1) random circuits, only changing the number of qubits.
I used the following random circuit generator
def random_circuit(nqubit, depth, seed=None):
r"""Generate a random circuit.
This function generates a random circuit with nqubit qubits and depth layers.
The circuit is generated by CNOT gates and RZ gates.
Parameters
----------
nqubit : int
number of qubits
depth : int
number of layers
seed : int
random seed
Returns
-------
circuit : graphix.transpiler.Circuit object
generated circuit
"""
if seed is not None:
random.seed(seed)
qubit_index = [i for i in range(nqubit)]
circuit = Circuit(nqubit)
for _ in range(depth):
random.shuffle(qubit_index)
for j in range(len(qubit_index) // 2):
circuit.cnot(qubit_index[2 * j], qubit_index[2 * j + 1])
for j in range(len(qubit_index)):
circuit.rz(qubit_index[j], 2 * np.pi * random.random())
return circuit
I pasted the benchmark code below. I didn't perform pauli measurement processing by Pattern.perform_pauli_measurements()
because Pattern.minimize_space()
for a graph with gflow sometimes doesn't work well.
# %%
from graphix.generator import random_circuit
import matplotlib.pyplot as plt
from time import perf_counter
# %%
test_cases = [(i, 1) for i in range(2, 30, 2)]
score_time = []
circuit_time = []
# %%
for case in test_cases:
nqubit, depth = case
circuit = random_circuit(nqubit, depth)
pattern = circuit.transpile()
pattern.standardize()
pattern.minimize_space()
print(f"max space for nqubit={nqubit} circuit is ", pattern.max_space())
start = perf_counter()
pattern.simulate_pattern()
end = perf_counter()
print(f"nqubit: {nqubit}, depth: {depth}, time: {end - start}")
score_time.append(end - start)
start = perf_counter()
circuit.simulate_statevector()
end = perf_counter()
circuit_time.append(end - start)
# %%
# plot the score_time
plt.scatter([case[0] for case in test_cases], score_time, label="score_time")
plt.scatter([case[0] for case in test_cases],
circuit_time, label="circuit_time")
plt.xlabel("nqubit")
plt.ylabel("time (s)")
# plt.xscale("log")
plt.yscale("log")
plt.title("Time to simulate square random circuits")
plt.legend()
plt.show()
# %%
# write to file
with open("score_time.txt", "w") as f:
for item in score_time:
f.write(f"{item}\n")
# %%
# write circuit_time to file
with open("circuit_time.txt", "w") as f:
for item in circuit_time:
f.write(f"{item}\n")
@nabe98 can you squash and merge?
Before submitting, please check the following:
pytest
)black -l 120 <filename>
Then, please fill in below:
Context (if applicable):
ptrace
method was implemented by using density matrix. But for separable states (states that measured), using DM is unnecessary.Description of the change:
truncate_one_qubit
method toStatevec
.directly truncate the specified qubit.
Related issue:
73
also see that checks (github actions) pass. If lint check keeps failing, try installing black==22.8.0 as behavior seems to vary across versions.