-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcheck_eq.py
151 lines (120 loc) · 4.24 KB
/
check_eq.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import os
import json
import time
from glob import glob
from pathlib import Path
from termcolor import colored
from pytket import Circuit
from pytket.qasm import circuit_from_qasm_str
from pytket.extensions.cutensornet import TensorNetwork
import cuquantum as cq
import numpy as np
def test_equivalence(circ1, circ2):
n_qubits = circ1.n_qubits
assert n_qubits == circ2.n_qubits
bell_states = Circuit(2 * n_qubits)
for q in range(n_qubits):
bell_states.H(q)
for q in range(n_qubits):
bell_states.CX(q, q + n_qubits)
ket_circ = bell_states.copy()
ket_circ.add_circuit(circ1, qubits=[q for q in range(n_qubits)])
bra_circ = bell_states
bra_circ.add_circuit(circ2, qubits=[q for q in range(n_qubits)])
# Create the TNs of the circuits
ket_net = TensorNetwork(ket_circ)
bra_net = TensorNetwork(bra_circ)
# Concatenate one with the other, netB is the adjoint
overlap_net = ket_net.vdot(bra_net)
# Run the contraction
overlap = cq.contract(*overlap_net)
return np.isclose(overlap, 1)
def run(max_qubits, results):
old_circs = "bef"
new_circs = "aft"
n_skipped = 0
n_success = 0
n_fail = 0
global_start_time = time.time()
for name in os.listdir(old_circs):
old_circ_f = os.path.join(old_circs, name)
name = Path(name).stem
try:
old_circ = load_circuit(old_circ_f)
except ValueError:
# Ignore this file
# We only support tket1 json and qasm files
continue
json_new_circs = glob(os.path.join(new_circs, name + "*.json"))
qasm_new_circs = glob(os.path.join(new_circs, name + "*.qasm"))
if not json_new_circs and not qasm_new_circs:
continue
print(
f"Checking equivalence for {old_circ_f} ({old_circ.n_qubits} qb, {old_circ.n_gates} gates)"
)
for new_circ_f in json_new_circs + qasm_new_circs:
new_circ = load_circuit(new_circ_f)
print(f"\t{new_circ_f} ({new_circ.n_gates} gates): ", end="")
if new_circ.n_qubits != old_circ.n_qubits:
print(
colored("FAIL", "red"), f"Invalid qubit count {new_circ.n_qubits}"
)
n_fail += 1
continue
if new_circ.n_qubits > max_qubits:
print(colored("Skip", "yellow"))
n_skipped += 1
continue
start_time = time.time()
is_eq = test_equivalence(new_circ, old_circ)
end_time = time.time()
elapsed_time = end_time - start_time
if is_eq:
print(colored("OK", "green"), f"({elapsed_time:.2f}s)")
n_success += 1
else:
print(colored("FAIL", "red"), f"({elapsed_time:.2f}s)")
n_fail += 1
results.append((name, is_eq, elapsed_time))
global_time = time.time() - global_start_time
print(
f"Finished in {global_time:.2f}s. Success/Fail/Skipped (" +
colored(n_success, "green") +
"/" +
colored(n_fail, "red") +
"/" +
colored(n_skipped, "yellow") +
")."
)
def load_circuit(file):
"""Load a circuit from a tket1 json or qasm file."""
file = Path(file)
# Check the extension
if file.suffix == ".json":
with open(file, "r") as f:
json_circ = json.load(f)
# Ignore classical registers
json_circ["bits"] = []
circ = Circuit.from_dict(json_circ)
elif file.suffix == ".qasm":
with open(file, "r") as f:
# Ignore classical registers
qasm = "".join(line for line in f if "creg" not in line)
circ = circuit_from_qasm_str(qasm)
else:
raise ValueError(f"Unknown file extension: {file.suffix}")
return circ
if __name__ == "__main__":
import csv
results = []
MAX_QUBITS = 40
print("Starting")
try:
run(MAX_QUBITS, results)
finally:
# Save results to CSV file
with open("results.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["Name", "Success", "Elapsed Time"])
for row in results:
writer.writerow(row)