diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..faf6568 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__ +venv +challenge.pdf +writeup/.texpadtmp \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2fca79a --- /dev/null +++ b/README.md @@ -0,0 +1,141 @@ +# iQuHack 2026: Superquantum Challenge + +**Team Name:** 67 Qubits +**Team Members:** Adam Godel, Yebin Song, Nico Jackson, Travis Meyer, Timothy Wright +**Affiliation:** Boston University, Boston, MA + +--- + +## Project Write-up & Presentation Slides + +Our complete technical writeup is available in the `writeup/` directory: + +- **PDF**: [`writeup/main.pdf`](writeup/main.pdf) - **Start here!** This is the compiled document with all our implementations, optimizations, and experimental results. + +- **Slides**: Access our slides [here!](https://docs.google.com/presentation/d/1q9z32plF9qOmsmKggezTibO6qC0Dm3mvM3ZvNwCfbd8/edit?usp=sharing) + +## Project Overview + +This repository contains our implementations of **12 unitary operators** using the **Clifford + T gate set**, where the T gate is the most computationally expensive gate to execute. Our goal was to optimize quantum circuits by: + +1. **Minimizing T-gate count** - Reducing the "quantumness" and computational cost +2. **Minimizing approximation error** - Achieving high fidelity to target unitaries +3. **Exploring the tradeoff** - Balancing these competing objectives + +--- + +## Repository Structure + +### `unitary/` - Circuit Implementations + +Contains Python implementations for all 12 unitaries: + +- **`unitary1.py` through `unitary12.py`**: Individual implementations for each target unitary +- **`optim.py`**: Main optimization framework for building and synthesizing circuits +- **`utils.py`**: Utility functions for rotation gates (Rz, Ry, Rx) +- **`test.py`**: Testing framework with expected unitary matrices and distance calculations +- **`plot.py`**: Plotting utilities for T-count vs. distance analysis +- **`plot7_mp.py`**: Plotting utilities for T-count vs. Fidelity in Unitary 7 +- **`plot10.py`**: Plotting utilities for T-count vs. distance analysis in Unitary 10 +- **`parser.py`**: Parsing utility for converting qasm to quantum gates + +### `qasm/` - QASM Circuit Files + +Contains OpenQASM 3.0 representations of all optimized circuits: + +``` +qasm/unitary1.qasm +qasm/unitary2.qasm +... +qasm/unitary12.qasm +``` + +These files can be loaded into Qiskit or other quantum computing frameworks. + +### `plots/` - Visualization Results + +Contains generated plots showing the T-count vs. distance tradeoffs: + +- `unitary_2_distance_vs_tcount.png` +- `unitary_3_distance_vs_tcount.png` +- `unitary_4_distance_vs_tcount.png` +- `unitary_6_distance_vs_tcount.png` +- `unitary7_plot.png` (fidelity-based) +- `unitary10_distance_vs_tcount.png` + +### `writeup/` - Technical Documentation + +The complete LaTeX writeup. + +--- + +## How to Use + +### Prerequisites + +```bash +pip install qiskit +pip install gridsynth +pip install rmsynth +pip install numpy matplotlib scipy +``` + +### Running Individual Unitaries + +Each unitary can be executed independently: + +```bash +cd unitary +python3 unitary2.py # Controlled-Ry(π/7) gate +python3 unitary7.py # State preparation +python3 unitary11.py # Four-qubit diagonal unitary +``` + +### Running Optimizations + +To optimize a specific unitary with custom parameters: + +```bash +cd unitary +python3 optim.py +``` + +Edit the file to select which unitary to optimize and adjust epsilon values. + +### Generating Plots + +To generate T-count vs. distance plots: + +```bash +cd unitary +python3 plot.py +``` + +Modify the `constructions_to_analyze` list in the `if __name__ == "__main__"` block to select which unitaries to plot. + +### Testing Implementations + +To verify circuit correctness: + +```bash +cd unitary +python3 test.py +``` + +This will load QASM files, compute circuit unitaries, and compare them against expected results. + +--- + +## References + +- **Gridsynth**: Ross, N. J., & Selinger, P. (2014). Optimal ancilla-free Clifford+T approximation of z-rotations. +- **Rmsynth**: Superquantum rmsynth package for phase polynomial optimization +- **Qiskit**: IBM's open-source quantum computing framework + +## License + +This project was created for the iQuHack 2026 hackathon. See individual package licenses for gridsynth, rmsynth, and Qiskit. + +--- + +**For questions or issues, please open an issue on GitHub or contact the team.** diff --git a/challenge.pdf b/challenge.pdf index b623c26..3fcbee2 100644 Binary files a/challenge.pdf and b/challenge.pdf differ diff --git a/plots/unitary10_distance_vs_tcount.png b/plots/unitary10_distance_vs_tcount.png new file mode 100644 index 0000000..b5d750b Binary files /dev/null and b/plots/unitary10_distance_vs_tcount.png differ diff --git a/plots/unitary7_plot.png b/plots/unitary7_plot.png new file mode 100644 index 0000000..a36909f Binary files /dev/null and b/plots/unitary7_plot.png differ diff --git a/plots/unitary_11_distance_vs_tcount.png b/plots/unitary_11_distance_vs_tcount.png new file mode 100644 index 0000000..34816d8 Binary files /dev/null and b/plots/unitary_11_distance_vs_tcount.png differ diff --git a/plots/unitary_2_distance_vs_tcount.png b/plots/unitary_2_distance_vs_tcount.png new file mode 100644 index 0000000..5309d28 Binary files /dev/null and b/plots/unitary_2_distance_vs_tcount.png differ diff --git a/plots/unitary_3_distance_vs_tcount.png b/plots/unitary_3_distance_vs_tcount.png new file mode 100644 index 0000000..babe44d Binary files /dev/null and b/plots/unitary_3_distance_vs_tcount.png differ diff --git a/plots/unitary_4_distance_vs_tcount.png b/plots/unitary_4_distance_vs_tcount.png new file mode 100644 index 0000000..2e847f2 Binary files /dev/null and b/plots/unitary_4_distance_vs_tcount.png differ diff --git a/plots/unitary_5_distance_vs_tcount.png b/plots/unitary_5_distance_vs_tcount.png new file mode 100644 index 0000000..0044db6 Binary files /dev/null and b/plots/unitary_5_distance_vs_tcount.png differ diff --git a/plots/unitary_6_distance_vs_tcount.png b/plots/unitary_6_distance_vs_tcount.png new file mode 100644 index 0000000..572c43e Binary files /dev/null and b/plots/unitary_6_distance_vs_tcount.png differ diff --git a/plots/unitary_8_distance_vs_tcount.png b/plots/unitary_8_distance_vs_tcount.png new file mode 100644 index 0000000..1f168bb Binary files /dev/null and b/plots/unitary_8_distance_vs_tcount.png differ diff --git a/plots/unitary_9_distance_vs_tcount.png b/plots/unitary_9_distance_vs_tcount.png new file mode 100644 index 0000000..ca5382b Binary files /dev/null and b/plots/unitary_9_distance_vs_tcount.png differ diff --git a/qasm/parser.py b/qasm/parser.py new file mode 100644 index 0000000..27f2fad --- /dev/null +++ b/qasm/parser.py @@ -0,0 +1,76 @@ +import re +from pathlib import Path + +GATE = re.compile(r'gate\s+(\w+)\s+([A-Za-z_]\w*(?:\s*,\s*[A-Za-z_]\w*)*)\s*\{(.*?)\}', re.S) +CALL = re.compile(r'^\s*(\w+)\s+([^;]+);\s*$') +QDECL = re.compile(r'^\s*qubit\[(\d+)\]\s+q\s*;\s*$', re.M) + +def parse_ops(block): + return [ln.strip() for ln in block.splitlines() if ln.strip() and ln.strip().endswith(";")] + +def expand_line(line, env, gates, out): + m = CALL.match(line) + if not m: return + name, args = m.group(1), [a.strip() for a in m.group(2).split(",")] + + # map args through env (so gate-local names become q[i], etc.) + args = [env.get(a, a) for a in args] + + # builtin op -> emit + if name not in gates: + out.append(f"{name} {', '.join(args)};") + return + + # custom gate -> inline with new env + formal_args, body_ops = gates[name] + new_env = dict(env) + for fa, aa in zip(formal_args, args): + new_env[fa] = aa + for op in body_ops: + expand_line(op, new_env, gates, out) + +def reformat(in_file): + p = Path(in_file) + s = p.read_text(encoding="utf-8") + + # collect includes (keep them) + includes = "\n".join(re.findall(r'^\s*include\s+"[^"]+"\s*;\s*$', s, re.M)) + if not includes: + includes = 'include "stdgates.inc";' + + # parse gates + gates = {} + for name, argstr, body in GATE.findall(s): + gates[name] = ([a.strip() for a in argstr.split(",")], parse_ops(body)) + + # find main program start: after qubit[...] q; + qm = QDECL.search(s) + if not qm: + raise SystemExit("No 'qubit[n] q;' found.") + n = int(qm.group(1)) + main = s[qm.end():] + main_ops = parse_ops(main) + + # expand main ops + out_ops = [] + for op in main_ops: + expand_line(op, {}, gates, out_ops) + + # output name unitaryX.qasm next to input + m = re.search(r'unitary(\d+)\.qasm$', p.name) + X = m.group(1) if m else "0" + out_path = p.with_name(f"unitary{X}.qasm") + + out_path.write_text( + "OPENQASM 3.0;\n" + f"{includes}\n" + f"qubit[{n}] q;\n" + + "\n".join(out_ops) + + "\n", + encoding="utf-8", + ) + print(out_path) + +if __name__ == "__main__": + import sys + reformat(sys.argv[1]) diff --git a/qasm/unitary1.qasm b/qasm/unitary1.qasm new file mode 100644 index 0000000..6373645 --- /dev/null +++ b/qasm/unitary1.qasm @@ -0,0 +1,6 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +sdg q[0]; +cx q[1], q[0]; +s q[0]; diff --git a/qasm/unitary10.qasm b/qasm/unitary10.qasm new file mode 100644 index 0000000..65035a0 --- /dev/null +++ b/qasm/unitary10.qasm @@ -0,0 +1,1208 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +sdg q[0]; +h q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +h q[0]; +s q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +h q[0]; +s q[0]; +s q[0]; +h q[0]; +s q[1]; +s q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +sdg q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +h q[1]; +s q[1]; +s q[1]; +s q[1]; +s q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +cx q[0], q[1]; +s q[0]; +sdg q[0]; +h q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +sdg q[0]; +s q[1]; +s q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +sdg q[1]; +h q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +h q[1]; +s q[1]; +s q[1]; +s q[1]; +s q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +cx q[0], q[1]; +s q[0]; +sdg q[0]; +h q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +h q[0]; +s q[0]; +sdg q[0]; +sdg q[0]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +sdg q[1]; +sdg q[1]; +sdg q[1]; +h q[1]; +s q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +s q[1]; +s q[1]; +s q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +cx q[0], q[1]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +sdg q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +h q[0]; +s q[0]; +s q[0]; +h q[0]; +s q[0]; +s q[0]; +h q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +t q[0]; +h q[0]; +s q[0]; +t q[0]; +h q[0]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +sdg q[1]; +sdg q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +h q[1]; +s q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +sdg q[1]; +sdg q[1]; +sdg q[1]; diff --git a/qasm/unitary11.qasm b/qasm/unitary11.qasm new file mode 100644 index 0000000..a5a38ac --- /dev/null +++ b/qasm/unitary11.qasm @@ -0,0 +1,52 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[4] q; +s q[0]; +s q[1]; +cx q[0], q[1]; +s q[1]; +cx q[0], q[1]; +s q[2]; +cx q[0], q[2]; +s q[2]; +cx q[0], q[2]; +cx q[1], q[2]; +s q[2]; +cx q[1], q[2]; +cx q[0], q[2]; +cx q[1], q[2]; +t q[2]; +cx q[1], q[2]; +cx q[0], q[2]; +s q[3]; +cx q[0], q[3]; +s q[3]; +cx q[0], q[3]; +cx q[1], q[3]; +s q[3]; +cx q[1], q[3]; +cx q[0], q[3]; +cx q[1], q[3]; +t q[3]; +cx q[1], q[3]; +cx q[0], q[3]; +cx q[2], q[3]; +s q[3]; +cx q[2], q[3]; +cx q[0], q[3]; +cx q[2], q[3]; +t q[3]; +cx q[2], q[3]; +cx q[0], q[3]; +cx q[1], q[3]; +cx q[2], q[3]; +s q[3]; +cx q[2], q[3]; +cx q[1], q[3]; +cx q[0], q[3]; +cx q[1], q[3]; +cx q[2], q[3]; +t q[3]; +cx q[2], q[3]; +cx q[1], q[3]; +cx q[0], q[3]; diff --git a/qasm/unitary12.qasm b/qasm/unitary12.qasm new file mode 100644 index 0000000..5de6f81 --- /dev/null +++ b/qasm/unitary12.qasm @@ -0,0 +1,2144 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[9] q; +tdg q[0]; +tdg q[0]; +h q[0]; +tdg q[1]; +tdg q[1]; +h q[1]; +h q[4]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +tdg q[4]; +tdg q[4]; +h q[4]; +h q[6]; +h q[8]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +h q[2]; +h q[4]; +h q[5]; +h q[7]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[5], q[2]; +cx q[6], q[2]; +cx q[7], q[2]; +h q[3]; +tdg q[4]; +tdg q[4]; +h q[4]; +h q[5]; +tdg q[6]; +tdg q[6]; +h q[6]; +h q[7]; +tdg q[8]; +tdg q[8]; +h q[8]; +cx q[4], q[3]; +cx q[5], q[3]; +cx q[6], q[3]; +cx q[7], q[3]; +cx q[8], q[3]; +h q[4]; +cx q[5], q[4]; +cx q[7], q[4]; +h q[5]; +tdg q[6]; +tdg q[6]; +h q[6]; +cx q[6], q[5]; +cx q[7], q[5]; +tdg q[6]; +tdg q[6]; +h q[6]; +h q[8]; +t q[5]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +tdg q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[2], q[1]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +tdg q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[7], q[1]; +t q[1]; +cx q[7], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +t q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +tdg q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[5], q[2]; +cx q[6], q[2]; +cx q[7], q[2]; +tdg q[2]; +cx q[7], q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[5], q[2]; +cx q[7], q[2]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[2]; +cx q[7], q[2]; +cx q[5], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[3], q[2]; +cx q[5], q[2]; +cx q[6], q[2]; +cx q[7], q[2]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[2]; +cx q[7], q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[3], q[2]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +tdg q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +t q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[6], q[2]; +cx q[7], q[2]; +tdg q[2]; +cx q[7], q[2]; +cx q[6], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[4], q[3]; +cx q[5], q[3]; +cx q[6], q[3]; +cx q[7], q[3]; +tdg q[3]; +cx q[7], q[3]; +cx q[6], q[3]; +cx q[5], q[3]; +cx q[4], q[3]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[6], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[6], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[2], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[2], q[1]; +cx q[1], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[5], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[5], q[1]; +cx q[2], q[1]; +cx q[2], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[2], q[1]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[1], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[1], q[0]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +t q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +tdg q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +tdg q[3]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +t q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[5], q[2]; +cx q[6], q[2]; +tdg q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[7], q[1]; +t q[1]; +cx q[7], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[7], q[1]; +t q[1]; +cx q[7], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[2], q[0]; +cx q[3], q[2]; +cx q[5], q[2]; +cx q[6], q[2]; +cx q[7], q[2]; +t q[2]; +cx q[7], q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[3], q[2]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[6], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[6], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[4], q[3]; +cx q[5], q[3]; +cx q[6], q[3]; +cx q[8], q[3]; +tdg q[3]; +cx q[8], q[3]; +cx q[6], q[3]; +cx q[5], q[3]; +cx q[4], q[3]; +cx q[2], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +t q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +tdg q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[1], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +t q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[6], q[2]; +cx q[8], q[2]; +tdg q[2]; +cx q[8], q[2]; +cx q[6], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[4], q[2]; +cx q[5], q[2]; +cx q[7], q[2]; +cx q[8], q[2]; +tdg q[2]; +cx q[8], q[2]; +cx q[7], q[2]; +cx q[5], q[2]; +cx q[4], q[2]; +cx q[4], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[5], q[3]; +cx q[6], q[3]; +cx q[7], q[3]; +cx q[8], q[3]; +t q[3]; +cx q[8], q[3]; +cx q[7], q[3]; +cx q[6], q[3]; +cx q[5], q[3]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +t q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[2], q[0]; +cx q[5], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[5], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[6], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[6], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[4], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[4], q[2]; +cx q[5], q[2]; +cx q[6], q[2]; +t q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[4], q[2]; +cx q[2], q[0]; +cx q[4], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +t q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[4], q[3]; +cx q[5], q[3]; +cx q[7], q[3]; +t q[3]; +cx q[7], q[3]; +cx q[5], q[3]; +cx q[4], q[3]; +cx q[2], q[1]; +cx q[6], q[1]; +cx q[7], q[1]; +tdg q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[2], q[1]; +cx q[4], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[2], q[1]; +cx q[5], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[5], q[1]; +cx q[2], q[1]; +cx q[5], q[2]; +cx q[6], q[2]; +cx q[8], q[2]; +tdg q[2]; +cx q[8], q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[5], q[4]; +cx q[6], q[4]; +cx q[8], q[4]; +t q[4]; +cx q[8], q[4]; +cx q[6], q[4]; +cx q[5], q[4]; +cx q[2], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +t q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[3], q[2]; +cx q[6], q[2]; +cx q[7], q[2]; +t q[2]; +cx q[7], q[2]; +cx q[6], q[2]; +cx q[3], q[2]; +cx q[5], q[3]; +cx q[6], q[3]; +cx q[7], q[3]; +t q[3]; +cx q[7], q[3]; +cx q[6], q[3]; +cx q[5], q[3]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[4], q[3]; +cx q[5], q[3]; +cx q[8], q[3]; +t q[3]; +cx q[8], q[3]; +cx q[5], q[3]; +cx q[4], q[3]; +cx q[4], q[2]; +cx q[6], q[2]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[2]; +cx q[6], q[2]; +cx q[4], q[2]; +cx q[5], q[2]; +cx q[7], q[2]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[2]; +cx q[7], q[2]; +cx q[5], q[2]; +cx q[6], q[4]; +cx q[7], q[4]; +cx q[8], q[4]; +t q[4]; +cx q[8], q[4]; +cx q[7], q[4]; +cx q[6], q[4]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[6], q[2]; +tdg q[2]; +cx q[6], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[3], q[2]; +cx q[5], q[2]; +cx q[6], q[2]; +t q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[3], q[2]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[5], q[0]; +tdg q[0]; +cx q[5], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[7], q[1]; +tdg q[1]; +cx q[7], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[3], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[1], q[0]; +cx q[5], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[5], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[3], q[2]; +cx q[6], q[2]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[2]; +cx q[6], q[2]; +cx q[3], q[2]; +cx q[5], q[4]; +cx q[7], q[4]; +cx q[8], q[4]; +tdg q[4]; +cx q[8], q[4]; +cx q[7], q[4]; +cx q[5], q[4]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[5], q[0]; +t q[0]; +cx q[5], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[3], q[1]; +cx q[5], q[1]; +cx q[6], q[1]; +t q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[3], q[1]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[5], q[2]; +t q[2]; +cx q[5], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[2], q[1]; +cx q[3], q[1]; +cx q[7], q[1]; +tdg q[1]; +cx q[7], q[1]; +cx q[3], q[1]; +cx q[2], q[1]; +cx q[3], q[2]; +cx q[4], q[2]; +cx q[7], q[2]; +t q[2]; +cx q[7], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[3], q[1]; +cx q[5], q[1]; +cx q[7], q[1]; +tdg q[1]; +cx q[7], q[1]; +cx q[5], q[1]; +cx q[3], q[1]; +cx q[3], q[2]; +cx q[5], q[2]; +cx q[7], q[2]; +tdg q[2]; +cx q[7], q[2]; +cx q[5], q[2]; +cx q[3], q[2]; +cx q[3], q[1]; +cx q[4], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[3], q[2]; +cx q[5], q[2]; +cx q[8], q[2]; +tdg q[2]; +cx q[8], q[2]; +cx q[5], q[2]; +cx q[3], q[2]; +cx q[5], q[0]; +cx q[6], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[4], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[4], q[1]; +cx q[4], q[2]; +cx q[7], q[2]; +cx q[8], q[2]; +tdg q[2]; +cx q[8], q[2]; +cx q[7], q[2]; +cx q[4], q[2]; +cx q[5], q[3]; +cx q[7], q[3]; +cx q[8], q[3]; +tdg q[3]; +cx q[8], q[3]; +cx q[7], q[3]; +cx q[5], q[3]; +cx q[5], q[4]; +tdg q[4]; +cx q[5], q[4]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +tdg q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +cx q[4], q[1]; +cx q[5], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[4], q[3]; +cx q[6], q[3]; +cx q[8], q[3]; +tdg q[3]; +cx q[8], q[3]; +cx q[6], q[3]; +cx q[4], q[3]; +cx q[4], q[3]; +cx q[7], q[3]; +cx q[8], q[3]; +t q[3]; +cx q[8], q[3]; +cx q[7], q[3]; +cx q[4], q[3]; +cx q[5], q[1]; +cx q[7], q[1]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[5], q[1]; +cx q[6], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[5], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[1], q[0]; +cx q[4], q[0]; +cx q[5], q[0]; +t q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[6], q[0]; +cx q[7], q[0]; +t q[0]; +cx q[7], q[0]; +cx q[6], q[0]; +cx q[1], q[0]; +cx q[1], q[0]; +cx q[7], q[0]; +cx q[8], q[0]; +tdg q[0]; +cx q[8], q[0]; +cx q[7], q[0]; +cx q[1], q[0]; +cx q[2], q[0]; +cx q[4], q[0]; +t q[0]; +cx q[4], q[0]; +cx q[2], q[0]; +cx q[5], q[4]; +cx q[6], q[4]; +t q[4]; +cx q[6], q[4]; +cx q[5], q[4]; +cx q[4], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[3], q[0]; +cx q[4], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[4], q[0]; +cx q[5], q[2]; +cx q[6], q[2]; +tdg q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[4], q[3]; +cx q[5], q[3]; +t q[3]; +cx q[5], q[3]; +cx q[4], q[3]; +cx q[1], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[1], q[0]; +cx q[3], q[2]; +cx q[6], q[2]; +t q[2]; +cx q[6], q[2]; +cx q[3], q[2]; +cx q[3], q[1]; +cx q[4], q[1]; +t q[1]; +cx q[4], q[1]; +cx q[3], q[1]; +cx q[6], q[4]; +cx q[7], q[4]; +t q[4]; +cx q[7], q[4]; +cx q[6], q[4]; +cx q[2], q[0]; +cx q[5], q[0]; +tdg q[0]; +cx q[5], q[0]; +cx q[2], q[0]; +cx q[4], q[2]; +cx q[5], q[2]; +tdg q[2]; +cx q[5], q[2]; +cx q[4], q[2]; +cx q[2], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[2], q[0]; +cx q[5], q[0]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[6], q[4]; +cx q[8], q[4]; +t q[4]; +cx q[8], q[4]; +cx q[6], q[4]; +cx q[5], q[0]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[5], q[0]; +cx q[3], q[2]; +cx q[4], q[2]; +t q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +cx q[6], q[0]; +t q[0]; +cx q[6], q[0]; +cx q[7], q[4]; +cx q[8], q[4]; +tdg q[4]; +cx q[8], q[4]; +cx q[7], q[4]; +cx q[5], q[1]; +cx q[6], q[1]; +tdg q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[1], q[0]; +cx q[4], q[0]; +t q[0]; +cx q[4], q[0]; +cx q[1], q[0]; +cx q[5], q[2]; +t q[2]; +cx q[5], q[2]; +cx q[5], q[3]; +cx q[8], q[3]; +tdg q[3]; +cx q[8], q[3]; +cx q[5], q[3]; +cx q[6], q[5]; +cx q[8], q[5]; +tdg q[5]; +cx q[8], q[5]; +cx q[6], q[5]; +cx q[1], q[0]; +cx q[5], q[0]; +tdg q[0]; +cx q[5], q[0]; +cx q[1], q[0]; +cx q[3], q[0]; +cx q[6], q[0]; +tdg q[0]; +cx q[6], q[0]; +cx q[3], q[0]; +cx q[3], q[1]; +cx q[6], q[1]; +t q[1]; +cx q[6], q[1]; +cx q[3], q[1]; +tdg q[0]; +cx q[3], q[1]; +cx q[5], q[1]; +tdg q[1]; +cx q[5], q[1]; +cx q[3], q[1]; +cx q[5], q[2]; +cx q[7], q[2]; +t q[2]; +cx q[7], q[2]; +cx q[5], q[2]; +cx q[4], q[1]; +cx q[6], q[1]; +t q[1]; +cx q[6], q[1]; +cx q[4], q[1]; +cx q[3], q[2]; +cx q[7], q[2]; +tdg q[2]; +cx q[7], q[2]; +cx q[3], q[2]; +cx q[4], q[1]; +cx q[7], q[1]; +tdg q[1]; +cx q[7], q[1]; +cx q[4], q[1]; +cx q[6], q[0]; +cx q[8], q[0]; +t q[0]; +cx q[8], q[0]; +cx q[6], q[0]; +cx q[3], q[2]; +cx q[5], q[2]; +tdg q[2]; +cx q[5], q[2]; +cx q[3], q[2]; +cx q[6], q[3]; +cx q[8], q[3]; +t q[3]; +cx q[8], q[3]; +cx q[6], q[3]; +cx q[7], q[6]; +cx q[8], q[6]; +tdg q[6]; +cx q[8], q[6]; +cx q[7], q[6]; +cx q[2], q[0]; +tdg q[0]; +cx q[2], q[0]; +cx q[5], q[1]; +cx q[7], q[1]; +t q[1]; +cx q[7], q[1]; +cx q[5], q[1]; +cx q[8], q[2]; +t q[2]; +cx q[8], q[2]; +cx q[6], q[1]; +cx q[8], q[1]; +tdg q[1]; +cx q[8], q[1]; +cx q[6], q[1]; +cx q[7], q[3]; +cx q[8], q[3]; +tdg q[3]; +cx q[8], q[3]; +cx q[7], q[3]; +cx q[4], q[2]; +tdg q[2]; +cx q[4], q[2]; +cx q[4], q[3]; +t q[3]; +cx q[4], q[3]; +t q[1]; +cx q[3], q[0]; +t q[0]; +cx q[3], q[0]; +cx q[7], q[4]; +tdg q[4]; +cx q[7], q[4]; +cx q[8], q[4]; +tdg q[4]; +cx q[8], q[4]; +cx q[3], q[2]; +tdg q[2]; +cx q[3], q[2]; +t q[7]; +cx q[7], q[0]; +tdg q[0]; +cx q[7], q[0]; +cx q[7], q[2]; +t q[2]; +cx q[7], q[2]; +cx q[7], q[6]; +tdg q[6]; +cx q[7], q[6]; +cx q[1], q[0]; +tdg q[0]; +cx q[1], q[0]; +cx q[7], q[5]; +t q[5]; +cx q[7], q[5]; +cx q[8], q[6]; +tdg q[6]; +cx q[8], q[6]; +cx q[4], q[1]; +tdg q[1]; +cx q[4], q[1]; +t q[2]; +cx q[8], q[1]; +t q[1]; +cx q[8], q[1]; +cx q[8], q[7]; +t q[7]; +cx q[8], q[7]; +t q[8]; +h q[8]; +h q[6]; +t q[6]; +t q[6]; +cx q[7], q[5]; +cx q[6], q[5]; +h q[6]; +t q[6]; +t q[6]; +h q[5]; +cx q[7], q[4]; +cx q[5], q[4]; +h q[4]; +cx q[8], q[3]; +cx q[7], q[3]; +cx q[6], q[3]; +cx q[5], q[3]; +cx q[4], q[3]; +h q[8]; +t q[8]; +t q[8]; +h q[7]; +h q[6]; +t q[6]; +t q[6]; +h q[5]; +h q[4]; +t q[4]; +t q[4]; +h q[3]; +cx q[7], q[2]; +cx q[6], q[2]; +cx q[5], q[2]; +cx q[4], q[2]; +cx q[3], q[2]; +h q[7]; +h q[5]; +h q[4]; +h q[2]; +cx q[8], q[1]; +cx q[7], q[1]; +cx q[6], q[1]; +cx q[5], q[1]; +cx q[4], q[1]; +cx q[2], q[1]; +h q[8]; +h q[6]; +h q[4]; +t q[4]; +t q[4]; +cx q[7], q[0]; +cx q[5], q[0]; +cx q[4], q[0]; +cx q[3], q[0]; +cx q[2], q[0]; +cx q[1], q[0]; +h q[4]; +h q[1]; +t q[1]; +t q[1]; +h q[0]; +t q[0]; +t q[0]; diff --git a/qasm/unitary2.qasm b/qasm/unitary2.qasm new file mode 100644 index 0000000..325021a --- /dev/null +++ b/qasm/unitary2.qasm @@ -0,0 +1,97 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +sdg q[1]; +h q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +s q[1]; +t q[1]; +h q[1]; +t q[1]; +h q[1]; +h q[1]; +s q[1]; +cx q[0], q[1]; +sdg q[1]; +h q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +h q[1]; +s q[1]; +cx q[0], q[1]; diff --git a/qasm/unitary3.qasm b/qasm/unitary3.qasm new file mode 100644 index 0000000..dabd164 --- /dev/null +++ b/qasm/unitary3.qasm @@ -0,0 +1,210 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +cx q[0], q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +sdg q[1]; +cx q[0], q[1]; diff --git a/qasm/unitary4.qasm b/qasm/unitary4.qasm new file mode 100644 index 0000000..197edff --- /dev/null +++ b/qasm/unitary4.qasm @@ -0,0 +1,433 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +h q[0]; +h q[1]; +s q[0]; +s q[1]; +h q[0]; +h q[1]; +cx q[0], q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +sdg q[1]; +cx q[0], q[1]; +h q[0]; +h q[1]; +sdg q[0]; +sdg q[1]; +h q[0]; +h q[1]; +h q[0]; +h q[1]; +cx q[0], q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +sdg q[1]; +cx q[0], q[1]; +h q[0]; +h q[1]; diff --git a/qasm/unitary5.qasm b/qasm/unitary5.qasm new file mode 100644 index 0000000..e50ec73 --- /dev/null +++ b/qasm/unitary5.qasm @@ -0,0 +1,6 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +cx q[0], q[1]; +cx q[1], q[0]; +cx q[0], q[1]; diff --git a/qasm/unitary6.qasm b/qasm/unitary6.qasm new file mode 100644 index 0000000..b545389 --- /dev/null +++ b/qasm/unitary6.qasm @@ -0,0 +1,624 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +h q[0]; +h q[1]; +cx q[0], q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +sdg q[1]; +cx q[0], q[1]; +h q[0]; +h q[1]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +sdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +tdg q[0]; +h q[0]; +h q[0]; +s q[0]; +s q[0]; +h q[0]; +sdg q[0]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +sdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +tdg q[1]; +h q[1]; +h q[1]; +s q[1]; +s q[1]; +h q[1]; +sdg q[1]; diff --git a/qasm/unitary7.qasm b/qasm/unitary7.qasm new file mode 100644 index 0000000..417a718 --- /dev/null +++ b/qasm/unitary7.qasm @@ -0,0 +1,1416 @@ +OPENQASM 3.0; +include "stdgates.inc"; +gate _circuit_42 _gate_q_0 { + sdg _gate_q_0; + sdg _gate_q_0; +} +gate _circuit_46 _gate_q_0 { + s _gate_q_0; + h _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_45 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + _circuit_46 _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_51 _gate_q_0 { + s _gate_q_0; + h _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_54 _gate_q_0 { +} +gate _circuit_58 _gate_q_0 { + s _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_57 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + _circuit_58 _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_63 _gate_q_0 { + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_66 _gate_q_0 { + s _gate_q_0; +} +gate _circuit_70 _gate_q_0 { + s _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_69 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + _circuit_70 _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_75 _gate_q_0 { + sdg _gate_q_0; +} +gate _circuit_78 _gate_q_0 { + h _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_82 _gate_q_0 { + h _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_81 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + _circuit_82 _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_87 _gate_q_0 { + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_90 _gate_q_0 { + s _gate_q_0; +} +gate _circuit_94 _gate_q_0 { + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_93 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + _circuit_94 _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_99 _gate_q_0 { + sdg _gate_q_0; + sdg _gate_q_0; +} +gate _circuit_102 _gate_q_0 { + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + sdg _gate_q_0; + sdg _gate_q_0; + sdg _gate_q_0; +} +gate _circuit_106 _gate_q_0 { + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_105 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + _circuit_106 _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_111 _gate_q_0 { + s _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_114 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + h _gate_q_0; + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + sdg _gate_q_0; +} +gate _circuit_118 _gate_q_0 { + s _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_117 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + _circuit_118 _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_123 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + sdg _gate_q_0; + sdg _gate_q_0; +} +gate _circuit_126 _gate_q_0 { + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_130 _gate_q_0 { + s _gate_q_0; + s _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; + s _gate_q_0; + t _gate_q_0; + h _gate_q_0; + t _gate_q_0; + h _gate_q_0; +} +gate _circuit_129 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + _circuit_130 _gate_q_0; + h _gate_q_0; + s _gate_q_0; +} +gate _circuit_135 _gate_q_0 { + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + sdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + tdg _gate_q_0; + h _gate_q_0; + sdg _gate_q_0; + sdg _gate_q_0; +} +qubit[2] q; +_circuit_42 q[0]; +_circuit_45 q[0]; +_circuit_51 q[0]; +_circuit_54 q[1]; +_circuit_57 q[1]; +_circuit_63 q[1]; +cx q[0], q[1]; +_circuit_66 q[0]; +_circuit_69 q[0]; +_circuit_75 q[0]; +_circuit_78 q[1]; +_circuit_81 q[1]; +_circuit_87 q[1]; +cx q[0], q[1]; +_circuit_90 q[0]; +_circuit_93 q[0]; +_circuit_99 q[0]; +_circuit_102 q[1]; +_circuit_105 q[1]; +_circuit_111 q[1]; +cx q[0], q[1]; +_circuit_114 q[0]; +_circuit_117 q[0]; +_circuit_123 q[0]; +_circuit_126 q[1]; +_circuit_129 q[1]; +_circuit_135 q[1]; diff --git a/qasm/unitary8.qasm b/qasm/unitary8.qasm new file mode 100644 index 0000000..5660f66 --- /dev/null +++ b/qasm/unitary8.qasm @@ -0,0 +1,13 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +h q[1]; +t q[0]; +t q[1]; +cx q[0], q[1]; +tdg q[1]; +cx q[0], q[1]; +h q[0]; +cx q[0], q[1]; +cx q[1], q[0]; +cx q[0], q[1]; diff --git a/qasm/unitary9.qasm b/qasm/unitary9.qasm new file mode 100644 index 0000000..84a4961 --- /dev/null +++ b/qasm/unitary9.qasm @@ -0,0 +1,16 @@ +OPENQASM 3.0; +include "stdgates.inc"; +qubit[2] q; +h q[0]; +t q[0]; +t q[1]; +cx q[1], q[0]; +tdg q[0]; +cx q[1], q[0]; +h q[0]; +s q[0]; +s q[1]; +t q[1]; +cx q[0], q[1]; +cx q[1], q[0]; +cx q[0], q[1]; diff --git a/unitary/optim.py b/unitary/optim.py new file mode 100644 index 0000000..1ec0d98 --- /dev/null +++ b/unitary/optim.py @@ -0,0 +1,128 @@ +import numpy as np +import math +from qiskit import QuantumCircuit +from qiskit.quantum_info import Operator +from qiskit.qasm3 import dumps as dumps3 + +from utils import Ry +from utils import Rz +from utils import Rx +from test import count_t_gates_manual, distance_global_phase, expected as EXPECTED_DICT + +def run_optimization(unitary_id, theta): + if unitary_id not in EXPECTED_DICT: + print(f"Error: Unitary {unitary_id} not found in test.py expected dict.") + return + + expected_u = EXPECTED_DICT[unitary_id] + epsilons = [10**(-i/2) for i in range(2, 15)] + + print(f"Optimizing Unitary {unitary_id}, theta={theta:.3f}") + print(f"{'Epsilon':<10} | {'T-Count':<8} | {'Distance':<10}") + print("-" * 45) + + best_eps, best_t, best_dist = None, float('inf'), float('inf') + + for eps in epsilons: + qc = QuantumCircuit(2) + + if unitary_id == 2: + + qc.append(Ry(theta/2, eps).to_gate(), [1]) + qc.cx(0, 1) + qc.append(Ry(-theta/2, eps).to_gate(), [1]) + qc.cx(0, 1) + + elif unitary_id == 3: + + qc.cx(0, 1) + qc.append(Rz(-2*theta, eps).to_gate(), [1]) + qc.cx(0, 1) + + elif unitary_id == 4: + qc.h(0); qc.h(1) + qc.s(0); qc.s(1) + qc.h(0); qc.h(1) + qc.cx(0, 1) + qc.append(Rz(-2*theta, eps).to_gate(), [1]) + qc.cx(0, 1) + qc.h(0); qc.h(1) + qc.sdg(0); qc.sdg(1) + qc.h(0); qc.h(1) + + qc.h(0); qc.h(1) + qc.cx(0, 1) + qc.append(Rz(-2*theta, eps).to_gate(), [1]) + qc.cx(0, 1) + qc.h(0); qc.h(1) + + elif unitary_id == 6: + qc.h(0); qc.h(1) + qc.cx(0, 1) + qc.append(Rz(-2*theta, eps).to_gate(), [1]) + qc.cx(0, 1) + qc.h(0); qc.h(1) + + qc.append(Rz(-theta, eps).to_gate(), [0]) + qc.append(Rz(-theta, eps).to_gate(), [1]) + + # Add more unitary cases as needed + qasm_str = dumps3(qc) + + t_count = count_t_gates_manual(qasm_str) + + actual = Operator(qc).data + aligned = distance_global_phase(actual, expected_u) + dist = np.linalg.norm(aligned - expected_u) + + if t_count > 0 and (t_count < best_t or (t_count == best_t and dist < best_dist)): + best_eps, best_t, best_dist = eps, t_count, dist + + print(f"{eps:.1e} | {t_count:<8} | {dist:.2e}") + + print("-" * 45) + if best_eps: + print(f"Best Result: eps={best_eps:.1e}, T-count={best_t}, dist={best_dist:.2e}") + else: + print("No valid circuits generated. Check your Ry function.") + +if __name__ == "__main__": + # change to run w diff unitarys + run_optimization(6, math.pi/7) + + +#Shared functions + +def _synthesize(axis, angle, eps, _cache): + """Synthesize one rotation into Clifford+T. Returns (gate, t_count).""" + key = (axis, angle, eps) + if key in _cache: + return _cache[key] + sub = {"rz": Rz, "ry": Ry, "rx": Rx}[axis](angle, eps) + gate = sub.to_gate() + tc = count_t_gates_manual(dumps3(sub)) + _cache[key] = (gate, tc) + return gate, tc + +def normalize_angle(a): + """Reduce angle to (-π, π].""" + return float((a + np.pi) % (2 * np.pi) - np.pi) + +def build_circuit(ops, eps_list, _cache): + """Assemble the full 2-qubit Clifford+T circuit.""" + qc = QuantumCircuit(2) + rot_idx = 0 + for op in ops: + if op[0] == "cx": + qc.cx(op[1], op[2]) + else: + gate, _ = _synthesize(op[0], op[2], eps_list[rot_idx], _cache) + qc.append(gate, [op[1]]) + rot_idx += 1 + return qc + +def total_t_count(ops, rotation_indices, eps_list, _cache): + return sum( + _synthesize(ops[idx][0], ops[idx][2], eps_list[j], _cache)[1] + for j, idx in enumerate(rotation_indices) + ) \ No newline at end of file diff --git a/unitary/plot.py b/unitary/plot.py new file mode 100644 index 0000000..ec65450 --- /dev/null +++ b/unitary/plot.py @@ -0,0 +1,423 @@ +import numpy as np +import math +import matplotlib.pyplot as plt +from qiskit import QuantumCircuit +from qiskit import quantum_info +from qiskit.quantum_info import Operator +from qiskit.qasm3 import dumps as dumps3 + +from utils import Ry, Rz +from test import count_t_gates_manual, distance_global_phase, expected as EXPECTED_DICT +from unitary7 import generate_candidates, optimize_candidate_ops + +from plot10 import apply_scientific_style + +def smart_rz(qc, angle, eps, qubit, use_exact=True): + """ + Intelligently choose between exact T/S gates and synthesized Rz. + If use_exact=True and angle is a multiple of pi/4, use exact gates. + Otherwise, synthesize with given epsilon. + """ + norm_angle = angle % (2 * math.pi) + + if use_exact: + # Check for exact gate possibilities (zero T-cost or minimal T-cost) + if np.isclose(norm_angle, 0, atol=1e-10): + return # Identity, do nothing + elif np.isclose(norm_angle, math.pi/2, atol=1e-10): + qc.s(qubit) + return + elif np.isclose(norm_angle, math.pi, atol=1e-10): + qc.z(qubit) + return + elif np.isclose(norm_angle, 3*math.pi/2, atol=1e-10): + qc.sdg(qubit) + return + elif np.isclose(norm_angle, math.pi/4, atol=1e-10): + qc.t(qubit) + return + elif np.isclose(norm_angle, 7*math.pi/4, atol=1e-10): + qc.tdg(qubit) + return + + # Fallback to synthesized Rz gate + qc.append(Rz(angle, eps).to_gate(), [qubit]) + +def smart_ry(qc, angle, eps, qubit, use_exact=True): + """ + Intelligently choose between exact gates and synthesized Ry. + """ + norm_angle = angle % (2 * math.pi) + + if use_exact: + if np.isclose(norm_angle, 0, atol=1e-10): + return # Identity + elif np.isclose(norm_angle, math.pi, atol=1e-10): + qc.y(qubit) + return + + # Fallback to synthesized Ry gate + qc.append(Ry(angle, eps).to_gate(), [qubit]) + + +def get_circuit_construction(uid, theta, eps, optimization_level=0): + """ + Constructions from optim.py with configurable optimization. + + optimization_level: + 0 = Always use synthesized Rz/Ry gates + 1 = Use exact T/S gates when angles align with pi/4 multiples + """ + qc = QuantumCircuit(2) + use_exact = (optimization_level >= 1) + + if uid == 2: + smart_ry(qc, theta/2, eps, 1, use_exact) + qc.cx(0, 1) + smart_ry(qc, -theta/2, eps, 1, use_exact) + qc.cx(0, 1) + + elif uid == 3: + qc.cx(0, 1) + smart_rz(qc, -2*theta, eps, 1, use_exact) + qc.cx(0, 1) + + elif uid == 4: + qc.h(0); qc.h(1) + qc.s(0); qc.s(1) + qc.h(0); qc.h(1) + qc.cx(0, 1) + smart_rz(qc, -2*theta, eps, 1, use_exact) + qc.cx(0, 1) + qc.h(0); qc.h(1) + qc.sdg(0); qc.sdg(1) + qc.h(0); qc.h(1) + + qc.h(0); qc.h(1) + qc.cx(0, 1) + smart_rz(qc, -2*theta, eps, 1, use_exact) + qc.cx(0, 1) + qc.h(0); qc.h(1) + + elif uid == 6: + qc.h(0); qc.h(1) + qc.cx(0, 1) + smart_rz(qc, -2*theta, eps, 1, use_exact) + qc.cx(0, 1) + qc.h(0); qc.h(1) + + smart_rz(qc, -theta, eps, 0, use_exact) + smart_rz(qc, -theta, eps, 1, use_exact) + + elif uid == 5: + # Unitary 5: Simple SWAP-like construction (no rotation needed) + qc.cx(0, 1) + qc.cx(1, 0) + qc.cx(0, 1) + + elif uid == 8: + # Unitary 8: Fixed gate construction with T gates + qc.h(1) + + qc.t(0) + qc.t(1) + qc.cx(0, 1) + qc.tdg(1) + qc.cx(0, 1) + + qc.h(0) + + qc.cx(0, 1) + qc.cx(1, 0) + qc.cx(0, 1) + + elif uid == 9: + # Unitary 9: Fixed gate construction with T and S gates + qc.h(0) + + qc.t(0) + qc.t(1) + qc.cx(1, 0) + qc.tdg(0) + qc.cx(1, 0) + + qc.h(0) + + qc.s(0) + qc.s(1) + qc.t(1) + + qc.cx(0, 1) + qc.cx(1, 0) + qc.cx(0, 1) + + elif uid == 7: + # ── target (must match test.py case 7) ───────────────────────────────────── + statevector = quantum_info.random_statevector(4, seed=42).data + + # ── tuning knobs ─────────────────────────────────────────────────────────── + N_CANDIDATES = 50 + CANDIDATE_SEED = 42 + TARGET_FIDELITY = 0.9999 + ANGLE_TOL = 1e-9 + + EPS_COARSE = [10**(-i/2) for i in range(2, 18)] + + RELAXATION_FACTORS = [100, 50, 30, 20, 15, 10, 7, 5, 3, 2, 1.5, 1.3, 1.2, 1.1, 1.05, 1.02] + + candidates = generate_candidates(statevector, N_CANDIDATES, CANDIDATE_SEED) + + print(f"Statevector: {np.round(statevector, 6)}") + print(f"Candidates: {N_CANDIDATES} | fidelity threshold: {TARGET_FIDELITY}") + print("=" * 60) + + best = None # (t_count, fidelity, qc, cid, ops, rotation_indices, eps_list) + + for i, cand in enumerate(candidates): + result = optimize_candidate(cand, statevector, i) + if result is None: + continue + qc, tc, fid, ops, rot_idx, eps_list = result + if best is None or tc < best[0] or (tc == best[0] and fid > best[1]): + best = (tc, fid, qc, i, ops, rot_idx, eps_list) + + if best is None: + print("\nERROR: no candidate met the fidelity target.") + else: + tc, fid, qc, cid, ops, rot_idx, eps_list = best + + qasm3_str = dumps3(qc) + verified_t = count_t_gates_manual(qasm3_str) + + + elif uid == 10: + # Unitary 10: Not defined in expected dict + pass + + elif uid == 11: + pass + + return qc + + +def run_plot(unitary_ids, theta, show_individual=True, show_combined=False): + """ + Creates simple T-count vs Distance plots for each construction. + + Args: + unitary_ids: List of unitary IDs to analyze + theta: Angle parameter for constructions + show_individual: If True, create individual plots for each construction + show_combined: If True, create a combined comparison plot (deprecated) + """ + # Apply scientific plotting style + apply_scientific_style() + + # Wide epsilon range to explore the full tradeoff curve + epsilons = [10**(-i/2) for i in range(2, 20)] # More granular range + + # Fixed constructions that don't depend on epsilon + fixed_unitaries = {5, 8, 9, 11} + + all_results = {} + + for uid in unitary_ids: + if uid not in EXPECTED_DICT: + print(f"Warning: Unitary {uid} not in EXPECTED_DICT, skipping...") + continue + + print(f"\n{'='*60}") + print(f"Analyzing Unitary {uid} (theta={theta:.4f} rad = {theta*180/math.pi:.2f}°)") + print(f"{'='*60}") + + target_u = EXPECTED_DICT[uid] + results = [] + + # For fixed unitaries, only compute once + if uid in fixed_unitaries: + qc = get_circuit_construction(uid, theta, epsilons[0], optimization_level=1) + + if qc.num_qubits == 0: + print(f" Construction not implemented for Unitary {uid}") + continue + + qasm_str = dumps3(qc) + t_count = count_t_gates_manual(qasm_str) + + # Distance calculation with global phase alignment + actual = Operator(qc).data + aligned = distance_global_phase(actual, target_u) + dist = np.linalg.norm(aligned - target_u) + d_val = float(dist) if hasattr(dist, '__len__') else dist + + # Add single result + results.append((epsilons[0], t_count, d_val)) + + print(f" Fixed construction: T-count={t_count}, Distance={d_val:.2e}") + print(f" Note: This is a fixed circuit (epsilon does not affect T-count or distance)") + + else: + # For variable unitaries, scan all epsilon values + for eps in epsilons: + qc = get_circuit_construction(uid, theta, eps, optimization_level=1) + + # Skip if construction not implemented + if qc.num_qubits == 0: + continue + + qasm_str = dumps3(qc) + t_count = count_t_gates_manual(qasm_str) + + # Distance calculation with global phase alignment + actual = Operator(qc).data + aligned = distance_global_phase(actual, target_u) + dist = np.linalg.norm(aligned - target_u) + + # Convert distance to scalar if it's an array + d_val = float(dist) if hasattr(dist, '__len__') else dist + + results.append((eps, t_count, d_val)) + + if results: + # Print summary + print(f" Epsilon range: {min(r[0] for r in results):.2e} to {max(r[0] for r in results):.2e}") + print(f" T-count range: {min(r[1] for r in results)} to {max(r[1] for r in results)}") + print(f" Distance range: {min(r[2] for r in results):.2e} to {max(r[2] for r in results):.2e}") + + if not results: + print(f" No results generated for Unitary {uid}") + continue + + all_results[uid] = results + + # Create individual plot for this construction + if show_individual: + # For fixed unitaries with single point, create a simple marker plot + if uid in fixed_unitaries and len(results) == 1: + eps, t_count, d_val = results[0] + apply_scientific_style() + plt.figure(figsize=(6.8, 4.8)) + + plt.scatter([t_count], [d_val], s=90, marker='o', + facecolors='white', edgecolors='black', + linewidths=1.2, zorder=5, label=f'Unitary {uid} (Fixed)') + + plt.yscale('log') + plt.xscale('log') + plt.xlabel('T-Count (Gates)', fontsize=12, fontweight='bold') + plt.ylabel('Distance to Target (Error)', fontsize=12, fontweight='bold') + plt.title(f'Unitary {uid}: Fixed Construction\n(T-count={t_count}, Distance={d_val:.2e})', + fontsize=13, fontweight='bold') + plt.grid(True, which="both") + plt.legend(loc='best', fontsize=11) + + # Add annotation + plt.annotate( + f'T={t_count}\nDist={d_val:.2e}', + xy=(t_count, d_val), + xytext=(10, 10), + textcoords='offset points', + fontsize=10, + bbox=dict(boxstyle='round', facecolor='white', edgecolor='0.6', alpha=0.9), + arrowprops=dict(arrowstyle='->', color='0.4', lw=0.8), + ) + + plt.tight_layout() + filename = f'unitary_{uid}_distance_vs_tcount.png' + plt.savefig(filename, dpi=150, bbox_inches='tight') + print(f" Saved plot: {filename}") + plt.close() + + else: + # For variable unitaries, filter and plot normally + # Filter: Keep best distance for each unique T-count + best_points = {} + for eps, t, d in results: + if t not in best_points or d < best_points[t]: + best_points[t] = d + + sorted_t = sorted(best_points.keys()) + sorted_d = [best_points[t] for t in sorted_t] + + # Create simple plot + apply_scientific_style() + plt.figure(figsize=(6.8, 4.8)) + + plt.plot( + sorted_t, + sorted_d, + marker='o', + linewidth=1.6, + markersize=5, + color='black', + markerfacecolor='white', + markeredgecolor='black', + label=f'Unitary {uid}', + ) + + plt.yscale('log') + plt.xscale('log') + plt.xlabel('T-Count (Gates)', fontsize=12, fontweight='bold') + plt.ylabel('Distance to Target (Error)', fontsize=12, fontweight='bold') + plt.title(f'Unitary {uid}: Distance vs T-Count\n(θ = {theta:.4f} rad = {theta*180/math.pi:.2f}°)', + fontsize=13, fontweight='bold') + plt.grid(True, which="both") + plt.legend(loc='best', fontsize=11) + + # Annotate a small, non-overlapping subset of points (left-biased) + ax = plt.gca() + if sorted_t: + idx_min_d = int(np.argmin(sorted_d)) + idx_max_d = int(np.argmax(sorted_d)) + label_indices = sorted(set([0, len(sorted_t) - 1, idx_min_d, idx_max_d])) + offsets = [(-28, 12), (-28, -12), (-36, 18), (-36, -18)] + for k, idx in enumerate(label_indices): + t_val = sorted_t[idx] + d_val = sorted_d[idx] + dx, dy = offsets[k % len(offsets)] + va = 'bottom' if dy > 0 else 'top' + ax.annotate( + f'{d_val:.2e}', + xy=(t_val, d_val), + xytext=(dx, dy), + textcoords='offset points', + fontsize=9, + horizontalalignment='right', + verticalalignment=va, + bbox=dict(boxstyle='round', facecolor='white', alpha=0.7), + arrowprops=dict(arrowstyle='->', color='0.4', lw=0.8), + ) + + # Add text with best and worst points + if sorted_t: + min_t_idx = 0 + max_t_idx = len(sorted_t) - 1 + textstr = f'Min T: {sorted_t[min_t_idx]} (dist={sorted_d[min_t_idx]:.2e})\n' + textstr += f'Max T: {sorted_t[max_t_idx]} (dist={sorted_d[max_t_idx]:.2e})' + plt.text(0.5, 0.05, textstr, transform=plt.gca().transAxes, + fontsize=9, verticalalignment='bottom', + bbox=dict(boxstyle='round', facecolor='white', edgecolor='0.6', alpha=0.9)) + + plt.tight_layout() + filename = f'unitary_{uid}_distance_vs_tcount.png' + plt.savefig(filename, dpi=150, bbox_inches='tight') + print(f" Saved plot: {filename}") + plt.close() # Close the figure to free memory + + print(f"\n{'='*60}") + print(f"Analysis complete! Generated {len(all_results)} individual plots.") + print(f"{'='*60}") + +if __name__ == "__main__": + # List all constructions you want to investigate + # Unitaries 5, 8, 9 don't use theta parameter (fixed constructions) + constructions_to_analyze = [10] + + theta_value = math.pi / 7 + + print(f"Running analysis for θ = {theta_value:.4f} rad = {theta_value*180/math.pi:.2f}°") + print(f"Constructions: {constructions_to_analyze}") + print(f"Note: Unitaries 5, 8, 9 are fixed constructions (don't depend on theta or epsilon)") + print(f"\nThis will generate individual T-count vs Distance plots for each construction.") + + run_plot(constructions_to_analyze, theta_value, show_individual=True) diff --git a/unitary/plot10.py b/unitary/plot10.py new file mode 100644 index 0000000..f150927 --- /dev/null +++ b/unitary/plot10.py @@ -0,0 +1,286 @@ +""" +plot10.py -- plot T-count vs distance for unitary10 optimization + +This mirrors the plotting structure in plot.py but uses the unitary10 +optimization logic (uniform sweep + greedy per-rotation relaxation) and +plots the final (T, distance) point for each target distance. +""" + +# --- perf hygiene: avoid each process spawning many BLAS threads ----------- +import os as _os +_os.environ.setdefault("OMP_NUM_THREADS", "1") +_os.environ.setdefault("MKL_NUM_THREADS", "1") +_os.environ.setdefault("OPENBLAS_NUM_THREADS", "1") +_os.environ.setdefault("NUMEXPR_NUM_THREADS", "1") + +import os +import argparse +import multiprocessing as mp +import numpy as np +import matplotlib.pyplot as plt +from qiskit import QuantumCircuit, quantum_info, transpile +from qiskit.quantum_info import Operator +from qiskit.circuit.library import UnitaryGate + +from optim import _synthesize, normalize_angle, build_circuit, total_t_count + +# --- Configuration (same values as unitary10.py) --- +ANGLE_TOL = 1e-9 + +TARGET_DISTANCES = [ + 1e-1, 7e-2, 5e-2, 3e-2, 2e-2, 1e-2, 7e-3, 5e-3, 3e-3, 2e-3, 1e-3 +] + +# Ultra-granular epsilon sweep: 100 points from 1e-1 to 1e-9 +EPS_COARSE_SWEEP = np.logspace(-1, -9, 100) + +RELAXATION_FACTORS = [ + 100, 50, 30, 20, 15, 10, 7, 5, 3, 2, 1.5, 1.3, 1.2, 1.1, 1.05, 1.02 +] + + +def apply_scientific_style(): + plt.rcParams.update({ + "font.family": "serif", + "font.size": 12, + "axes.titlesize": 13, + "axes.labelsize": 12, + "axes.linewidth": 1.0, + "xtick.direction": "in", + "ytick.direction": "in", + "xtick.major.size": 4, + "ytick.major.size": 4, + "xtick.minor.size": 2, + "ytick.minor.size": 2, + "xtick.top": True, + "ytick.right": True, + "grid.color": "0.85", + "grid.linestyle": "-", + "grid.linewidth": 0.6, + "legend.frameon": False, + "figure.dpi": 120, + "savefig.dpi": 200, + }) + + +def operator_distance(actual, reference): + d = actual.shape[0] + inner = np.trace(actual.conj().T @ reference) + return float(np.sqrt(max(2 * d - 2 * np.abs(inner), 0.0))) + + +def extract_ops(target_matrix): + template_qc = QuantumCircuit(2) + template_qc.append(UnitaryGate(target_matrix), [0, 1]) + template = transpile( + template_qc, + basis_gates=["u3", "cx"], + optimization_level=2, + seed_transpiler=0, + ) + + ops = [] + for inst in template.data: + name = inst.operation.name + qubits = [template.find_bit(q).index for q in inst.qubits] + if name == "cx": + ops.append(("cx", qubits[0], qubits[1])) + elif name in ("u3", "u"): + theta, phi, lam = [float(p) for p in inst.operation.params] + q = qubits[0] + for axis, angle in [("rz", lam), ("ry", theta), ("rz", phi)]: + a = normalize_angle(angle) + if abs(a) > ANGLE_TOL: + ops.append((axis, q, a)) + elif name in ("rz", "ry", "rx"): + a = normalize_angle(float(inst.operation.params[0])) + if abs(a) > ANGLE_TOL: + ops.append((name, qubits[0], a)) + elif name == "p": + a = normalize_angle(float(inst.operation.params[0])) + if abs(a) > ANGLE_TOL: + ops.append(("rz", qubits[0], a)) + # unknown/ignored ops are skipped to match unitary10.py behavior + + return ops + + +def optimize_for_target(target_dist, ops, rotation_indices, target): + n_rotations = len(rotation_indices) + cache = {} + + # Phase 1: Uniform sweep + best_uniform_eps = None + for eps in EPS_COARSE_SWEEP: + eps_list = [float(eps)] * n_rotations + qc = build_circuit(ops, eps_list, cache) + dist = operator_distance(Operator(qc).data, target) + if dist < target_dist: + best_uniform_eps = float(eps) + break + + if best_uniform_eps is None: + return False, None, None + + # Phase 2: Per-rotation relaxation + current_eps = [best_uniform_eps] * n_rotations + current_t = total_t_count(ops, rotation_indices, current_eps, cache) + current_dist = operator_distance(Operator(build_circuit(ops, current_eps, cache)).data, target) + + while True: + any_improved = False + for j in range(n_rotations): + idx = rotation_indices[j] + axis, angle, orig_eps = ops[idx][0], ops[idx][2], current_eps[j] + _, orig_tc_j = _synthesize(axis, angle, orig_eps, cache) + + for factor in RELAXATION_FACTORS: + trial_eps = orig_eps * factor + if trial_eps > 0.5: + continue + + _, trial_tc_j = _synthesize(axis, angle, trial_eps, cache) + if trial_tc_j >= orig_tc_j: + continue + + trial_eps_list = current_eps.copy() + trial_eps_list[j] = trial_eps + trial_dist = operator_distance( + Operator(build_circuit(ops, trial_eps_list, cache)).data, target + ) + + if trial_dist < target_dist: + current_t = current_t - orig_tc_j + trial_tc_j + current_eps[j] = trial_eps + current_dist = trial_dist + any_improved = True + break + if not any_improved: + break + + final_qc = build_circuit(ops, current_eps, cache) + final_t = total_t_count(ops, rotation_indices, current_eps, cache) + final_dist = operator_distance(Operator(final_qc).data, target) + + return True, final_t, final_dist + + +def _worker_task(args): + target_dist, ops, rotation_indices, target = args + success, final_t, final_dist = optimize_for_target( + target_dist, ops, rotation_indices, target + ) + return (target_dist, success, final_t, final_dist) + + +def run_plot(target_distances, show_plot=True, workers=1, mp_start="spawn"): + unitary = quantum_info.random_unitary(4, seed=42) + target = unitary.data + + ops = extract_ops(target) + rotation_indices = [i for i, op in enumerate(ops) if op[0] in ("rx", "ry", "rz")] + + print(f"Rotations to optimize: {len(rotation_indices)}") + + results = [] + tasks = [(td, ops, rotation_indices, target) for td in target_distances] + + if workers is None: + workers = os.cpu_count() or 1 + + if workers > 1: + ctx = mp.get_context(mp_start) + with ctx.Pool(processes=workers) as pool: + raw_results = list(pool.imap_unordered(_worker_task, tasks, chunksize=1)) + else: + raw_results = [_worker_task(task) for task in tasks] + + for target_dist, success, final_t, final_dist in sorted(raw_results, key=lambda r: r[0]): + print("\n" + "=" * 60) + print(f"RUNNING OPTIMIZATION FOR TARGET DISTANCE: {target_dist}") + print("=" * 60) + if not success: + print(f"Warning: Target distance {target_dist} not reachable in sweep.") + continue + + print(f"DONE -> Target: {target_dist} | Final T: {final_t} | Final Dist: {final_dist:.6e}") + results.append((target_dist, final_t, final_dist)) + + if not results: + print("\nNo results to plot.") + return + + if show_plot: + apply_scientific_style() + # Plot T-count vs distance for each target distance + results_sorted = sorted(results, key=lambda r: r[1]) + t_vals = [r[1] for r in results_sorted] + d_vals = [r[2] for r in results_sorted] + labels = [r[0] for r in results_sorted] + + plt.figure(figsize=(6.8, 4.8)) + plt.plot( + t_vals, + d_vals, + marker="o", + linewidth=1.6, + markersize=5, + color="black", + markerfacecolor="white", + markeredgecolor="black", + ) + plt.yscale("log") + plt.xscale("log") + plt.xlabel("T-Count (Gates)", fontsize=12, fontweight="bold") + plt.ylabel("Distance to Target (Error)", fontsize=12, fontweight="bold") + plt.title("Unitary 10: Distance vs T-Count", fontsize=13, fontweight="bold") + plt.grid(True, which="both") + + # Annotate points with their target distance + for t, d, td in zip(t_vals, d_vals, labels): + plt.annotate( + f"{td:.1e}", + xy=(t, d), + xytext=(6, 5), + textcoords="offset points", + fontsize=9, + bbox=dict(boxstyle="square,pad=0.2", facecolor="white", edgecolor="0.6", alpha=0.9), + ) + + plt.tight_layout() + filename = "unitary10_distance_vs_tcount.png" + plt.savefig(filename, dpi=150, bbox_inches="tight") + print(f"\nSaved plot: {filename}") + plt.close() + + print("\nAll target optimizations complete.") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--workers", + type=int, + default=os.cpu_count() or 1, + help="Number of worker processes (default: os.cpu_count()).", + ) + parser.add_argument( + "--mp-start", + type=str, + default="spawn", + choices=["spawn", "fork", "forkserver"], + help="Multiprocessing start method (default: spawn).", + ) + parser.add_argument( + "--no-plot", + action="store_true", + help="Skip saving the plot and only print results.", + ) + args = parser.parse_args() + + run_plot( + TARGET_DISTANCES, + show_plot=not args.no_plot, + workers=args.workers, + mp_start=args.mp_start, + ) diff --git a/unitary/plot7_mp.py b/unitary/plot7_mp.py new file mode 100644 index 0000000..05b198d --- /dev/null +++ b/unitary/plot7_mp.py @@ -0,0 +1,209 @@ +""" +plot7_mp.py -- multiprocessing plot for unitary 7 (state preparation) + +Generates a T-count vs infidelity (1 - fidelity) plot using the same +visual style as plot10.py. +""" + +# --- perf hygiene: avoid each process spawning many BLAS threads ----------- +import os as _os +_os.environ.setdefault("OMP_NUM_THREADS", "1") +_os.environ.setdefault("MKL_NUM_THREADS", "1") +_os.environ.setdefault("OPENBLAS_NUM_THREADS", "1") +_os.environ.setdefault("NUMEXPR_NUM_THREADS", "1") + +import os +import argparse +import multiprocessing as mp +import numpy as np + +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +from matplotlib.ticker import ScalarFormatter + +from plot10 import apply_scientific_style +from unitary7 import ( + generate_candidates, + extract_ops, + optimize_candidate_ops, + _target_sv, + N_CANDIDATES, + CANDIDATE_SEED, + TARGET_FIDELITY, +) + + +def _worker_task(args): + cid, cand_matrix = args + ops = extract_ops(cand_matrix) + return optimize_candidate_ops(ops, cid) + + +def _collect_points(candidates, workers, mp_start): + ctx = mp.get_context(mp_start) + tasks = [(i, candidates[i]) for i in range(len(candidates))] + results = [] + + if workers == 1: + for task in tasks: + results.append(_worker_task(task)) + else: + with ctx.Pool(processes=workers) as pool: + for res in pool.imap_unordered(_worker_task, tasks, chunksize=1): + results.append(res) + + points = [] + for cid, res in results: + if res is None: + continue + tc, fid, _, _, _ = res + points.append((int(tc), float(fid))) + + return points + + +def plot_unitary7(out_path, n_candidates, seed, workers, mp_start): + candidates = generate_candidates(_target_sv, n_candidates, seed) + points = _collect_points(candidates, workers, mp_start) + + if not points: + print("No candidates met the fidelity target; no plot generated.") + return + + best_points = {} + for t, fid in points: + if t not in best_points or fid > best_points[t]: + best_points[t] = fid + + sorted_t = sorted(best_points.keys()) + sorted_fid = [best_points[t] for t in sorted_t] + + apply_scientific_style() + plt.figure(figsize=(6.8, 4.8)) + + plt.plot( + sorted_t, + sorted_fid, + marker="o", + linewidth=1.6, + markersize=5, + color="black", + markerfacecolor="white", + markeredgecolor="black", + label="Unitary 7", + ) + + plt.xscale("log") + plt.xlabel("T-Count (Gates)", fontsize=12, fontweight="bold") + plt.ylabel("Fidelity", fontsize=12, fontweight="bold") + plt.title( + f"Unitary 7: Fidelity vs T-Count\n(target fidelity >= {TARGET_FIDELITY:.6f})", + fontsize=13, + fontweight="bold", + ) + plt.grid(True, which="both") + plt.legend(loc="best", fontsize=11) + fid_min = float(np.min(sorted_fid)) + fid_max = float(np.max(sorted_fid)) + if fid_max == fid_min: + pad = max(1e-12, fid_min * 1e-9) + else: + pad = 0.10 * (fid_max - fid_min) + fid_min = max(0.0, fid_min - pad) + fid_max = min(1.0, fid_max + pad) + plt.ylim(fid_min, fid_max) + ax = plt.gca() + ax.yaxis.set_major_formatter(ScalarFormatter(useOffset=False)) + ax.ticklabel_format(axis="y", style="plain") + + if sorted_t: + min_t_idx = 0 + max_t_idx = len(sorted_t) - 1 + textstr = f"Min T: {sorted_t[min_t_idx]} (fid={sorted_fid[min_t_idx]:.9f})\n" + textstr += f"Max T: {sorted_t[max_t_idx]} (fid={sorted_fid[max_t_idx]:.9f})" + plt.text( + 0.08, + 0.05, + textstr, + transform=plt.gca().transAxes, + fontsize=9, + verticalalignment="bottom", + bbox=dict(boxstyle="round", facecolor="white", edgecolor="0.6", alpha=0.9), + ) + + # Annotate three analytical points: min T, max T, best fidelity + max_fid_idx = int(np.argmax(sorted_fid)) + label_indices = [] + for idx in (min_t_idx, max_t_idx, max_fid_idx): + if idx not in label_indices: + label_indices.append(idx) + if len(label_indices) == 3: + break + offsets = [(-18, 12), (-18, -12), (-26, 16)] + for k, idx in enumerate(label_indices): + t_val = sorted_t[idx] + fid_val = sorted_fid[idx] + dx, dy = offsets[k % len(offsets)] + plt.annotate( + f"{fid_val:.9f}", + xy=(t_val, fid_val), + xytext=(dx, dy), + textcoords="offset points", + fontsize=9, + bbox=dict(boxstyle="round", facecolor="white", edgecolor="0.6", alpha=0.9), + arrowprops=dict(arrowstyle="->", color="0.4", lw=0.8), + ) + + plt.tight_layout() + plt.savefig(out_path, dpi=150, bbox_inches="tight") + plt.close() + print(f"Saved plot: {out_path}") + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--candidates", + type=int, + default=N_CANDIDATES, + help=f"Number of candidates (default: {N_CANDIDATES}).", + ) + parser.add_argument( + "--seed", + type=int, + default=CANDIDATE_SEED, + help=f"Candidate RNG seed (default: {CANDIDATE_SEED}).", + ) + parser.add_argument( + "--workers", + type=int, + default=os.cpu_count() or 1, + help="Number of worker processes (default: os.cpu_count()).", + ) + parser.add_argument( + "--mp-start", + type=str, + default="spawn", + choices=["spawn", "fork", "forkserver"], + help="Multiprocessing start method (default: spawn).", + ) + parser.add_argument( + "--out", + type=str, + default="unitary_7_distance_vs_tcount.png", + help="Output image file.", + ) + args = parser.parse_args() + + plot_unitary7( + out_path=args.out, + n_candidates=args.candidates, + seed=args.seed, + workers=args.workers, + mp_start=args.mp_start, + ) + + +if __name__ == "__main__": + main() diff --git a/unitary/plot_all_mp.py b/unitary/plot_all_mp.py new file mode 100644 index 0000000..c9520f8 --- /dev/null +++ b/unitary/plot_all_mp.py @@ -0,0 +1,313 @@ +""" +plot_all_mp.py -- multiprocessing plot generation for multiple unitaries + +Uses the same visual style as plot10.py (scientific look, black line with +white markers) and writes one image per unitary. +""" + +# Was not used in production code, but kept for reference for multiprocessing setup +import os as _os +_os.environ.setdefault("OMP_NUM_THREADS", "1") +_os.environ.setdefault("MKL_NUM_THREADS", "1") +_os.environ.setdefault("OPENBLAS_NUM_THREADS", "1") +_os.environ.setdefault("NUMEXPR_NUM_THREADS", "1") + +import os +import math +import argparse +import multiprocessing as mp +import time +import numpy as np + +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt + +from qiskit import QuantumCircuit +from qiskit import quantum_info +from qiskit.quantum_info import Operator +from qiskit.qasm3 import dumps as dumps3 + +from utils import Ry, Rz +from test import count_t_gates_manual, distance_global_phase, expected as EXPECTED_DICT +from plot10 import apply_scientific_style + +ANGLE_TOL = 1e-9 +EPSILONS = [10**(-i/2) for i in range(2, 20)] + +FIXED_UNITARIES = {5, 8, 9} +SUPPORTED_UNITARIES = {2, 3, 4, 5, 6, 8, 9} + + +def smart_rz(qc, angle, eps, qubit, use_exact=True): + norm_angle = angle % (2 * math.pi) + if use_exact: + if np.isclose(norm_angle, 0, atol=1e-10): + return + if np.isclose(norm_angle, math.pi/2, atol=1e-10): + qc.s(qubit) + return + if np.isclose(norm_angle, math.pi, atol=1e-10): + qc.z(qubit) + return + if np.isclose(norm_angle, 3*math.pi/2, atol=1e-10): + qc.sdg(qubit) + return + if np.isclose(norm_angle, math.pi/4, atol=1e-10): + qc.t(qubit) + return + if np.isclose(norm_angle, 7*math.pi/4, atol=1e-10): + qc.tdg(qubit) + return + qc.append(Rz(angle, eps).to_gate(), [qubit]) + + +def smart_ry(qc, angle, eps, qubit, use_exact=True): + norm_angle = angle % (2 * math.pi) + if use_exact: + if np.isclose(norm_angle, 0, atol=1e-10): + return + if np.isclose(norm_angle, math.pi, atol=1e-10): + qc.y(qubit) + return + qc.append(Ry(angle, eps).to_gate(), [qubit]) + + +def get_circuit_construction(uid, theta, eps, optimization_level=1): + qc = QuantumCircuit(2) + use_exact = (optimization_level >= 1) + + if uid == 2: + smart_ry(qc, theta/2, eps, 1, use_exact) + qc.cx(0, 1) + smart_ry(qc, -theta/2, eps, 1, use_exact) + qc.cx(0, 1) + elif uid == 3: + qc.cx(0, 1) + smart_rz(qc, -2*theta, eps, 1, use_exact) + qc.cx(0, 1) + elif uid == 4: + qc.h(0); qc.h(1) + qc.s(0); qc.s(1) + qc.h(0); qc.h(1) + qc.cx(0, 1) + smart_rz(qc, -2*theta, eps, 1, use_exact) + qc.cx(0, 1) + qc.h(0); qc.h(1) + qc.sdg(0); qc.sdg(1) + qc.h(0); qc.h(1) + + qc.h(0); qc.h(1) + qc.cx(0, 1) + smart_rz(qc, -2*theta, eps, 1, use_exact) + qc.cx(0, 1) + qc.h(0); qc.h(1) + elif uid == 6: + qc.h(0); qc.h(1) + qc.cx(0, 1) + smart_rz(qc, -2*theta, eps, 1, use_exact) + qc.cx(0, 1) + qc.h(0); qc.h(1) + + smart_rz(qc, -theta, eps, 0, use_exact) + smart_rz(qc, -theta, eps, 1, use_exact) + elif uid == 5: + qc.cx(0, 1) + qc.cx(1, 0) + qc.cx(0, 1) + elif uid == 8: + qc.h(1) + qc.t(0) + qc.t(1) + qc.cx(0, 1) + qc.tdg(1) + qc.cx(0, 1) + qc.h(0) + qc.cx(0, 1) + qc.cx(1, 0) + qc.cx(0, 1) + elif uid == 9: + qc.h(0) + qc.t(0) + qc.t(1) + qc.cx(1, 0) + qc.tdg(0) + qc.cx(1, 0) + qc.h(0) + qc.s(0) + qc.s(1) + qc.t(1) + qc.cx(0, 1) + qc.cx(1, 0) + qc.cx(0, 1) + else: + return QuantumCircuit(0) + + return qc + + +def compute_results(uid, theta): + if uid not in EXPECTED_DICT: + return (uid, False, "not in expected dict", None) + if uid not in SUPPORTED_UNITARIES: + return (uid, False, "no construction for this unitary", None) + + target_u = EXPECTED_DICT[uid] + results = [] + + if uid in FIXED_UNITARIES: + qc = get_circuit_construction(uid, theta, EPSILONS[0], optimization_level=1) + if qc.num_qubits == 0: + return (uid, False, "construction returned empty circuit", None) + qasm_str = dumps3(qc) + t_count = count_t_gates_manual(qasm_str) + actual = Operator(qc).data + aligned = distance_global_phase(actual, target_u) + dist = np.linalg.norm(aligned - target_u) + d_val = float(dist) if hasattr(dist, "__len__") else dist + results.append((EPSILONS[0], t_count, d_val)) + else: + for eps in EPSILONS: + qc = get_circuit_construction(uid, theta, eps, optimization_level=1) + if qc.num_qubits == 0: + continue + qasm_str = dumps3(qc) + t_count = count_t_gates_manual(qasm_str) + actual = Operator(qc).data + aligned = distance_global_phase(actual, target_u) + dist = np.linalg.norm(aligned - target_u) + d_val = float(dist) if hasattr(dist, "__len__") else dist + results.append((eps, t_count, d_val)) + + if not results: + return (uid, False, "no results generated", None) + + best_points = {} + for _, t, d in results: + if t not in best_points or d < best_points[t]: + best_points[t] = d + + sorted_t = sorted(best_points.keys()) + sorted_d = [best_points[t] for t in sorted_t] + return (uid, True, None, (sorted_t, sorted_d)) + + +def plot_unitary(uid, theta, out_dir, run_tag): + uid, ok, reason, payload = compute_results(uid, theta) + if not ok: + return (uid, False, reason) + + sorted_t, sorted_d = payload + apply_scientific_style() + plt.figure(figsize=(6.8, 4.8)) + + plt.plot( + sorted_t, + sorted_d, + marker="o", + linewidth=1.6, + markersize=5, + color="black", + markerfacecolor="white", + markeredgecolor="black", + label=f"Unitary {uid}", + ) + + plt.yscale("log") + plt.xscale("log") + plt.xlabel("T-Count (Gates)", fontsize=12, fontweight="bold") + plt.ylabel("Distance to Target (Error)", fontsize=12, fontweight="bold") + plt.title( + f"Unitary {uid}: Distance vs T-Count\n(theta = {theta:.4f} rad = {theta*180/math.pi:.2f} deg)", + fontsize=13, + fontweight="bold", + ) + plt.grid(True, which="both") + plt.legend(loc="best", fontsize=11) + + if sorted_t: + min_t_idx = 0 + max_t_idx = len(sorted_t) - 1 + textstr = f"Min T: {sorted_t[min_t_idx]} (dist={sorted_d[min_t_idx]:.2e})\n" + textstr += f"Max T: {sorted_t[max_t_idx]} (dist={sorted_d[max_t_idx]:.2e})" + plt.text( + 0.08, + 0.05, + textstr, + transform=plt.gca().transAxes, + fontsize=9, + verticalalignment="bottom", + bbox=dict(boxstyle="round", facecolor="white", edgecolor="0.6", alpha=0.9), + ) + + plt.tight_layout() + filename = os.path.join(out_dir, f"unitary_{uid}_distance_vs_tcount_{run_tag}.png") + plt.savefig(filename, dpi=150, bbox_inches="tight") + plt.close() + return (uid, True, filename) + + +def _worker_task(args): + uid, theta, out_dir, run_tag = args + return plot_unitary(uid, theta, out_dir, run_tag) + + +def _parse_unitary_list(text): + if text.strip().lower() == "all": + return sorted(EXPECTED_DICT.keys()) + parts = [p.strip() for p in text.split(",") if p.strip()] + return [int(p) for p in parts] + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--unitaries", + type=str, + default="2,3,4,5,6,8,9", + help="Comma-separated unitary IDs, or 'all'. Default: 2,3,4,5,6,8,9", + ) + parser.add_argument( + "--theta", + type=float, + default=math.pi / 7, + help="Theta parameter for constructions (default: pi/7).", + ) + parser.add_argument( + "--out-dir", + type=str, + default=".", + help="Output directory for images (default: current directory).", + ) + parser.add_argument( + "--workers", + type=int, + default=os.cpu_count() or 1, + help="Number of worker processes (default: os.cpu_count()).", + ) + parser.add_argument( + "--mp-start", + type=str, + default="spawn", + choices=["spawn", "fork", "forkserver"], + help="Multiprocessing start method (default: spawn).", + ) + args = parser.parse_args() + + unitary_ids = _parse_unitary_list(args.unitaries) + os.makedirs(args.out_dir, exist_ok=True) + + run_tag = time.strftime("%Y%m%d_%H%M%S") + tasks = [(uid, args.theta, args.out_dir, run_tag) for uid in unitary_ids] + ctx = mp.get_context(args.mp_start) + + with ctx.Pool(processes=args.workers) as pool: + for uid, ok, info in pool.imap_unordered(_worker_task, tasks, chunksize=1): + if ok: + print(f"[unitary {uid}] saved: {info}") + else: + print(f"[unitary {uid}] skipped: {info}") + + +if __name__ == "__main__": + main() diff --git a/unitary/test.py b/unitary/test.py new file mode 100644 index 0000000..9435b52 --- /dev/null +++ b/unitary/test.py @@ -0,0 +1,257 @@ +import argparse +import json +import os +import re +import numpy as np +import scipy.linalg + +from qiskit import QuantumCircuit, quantum_info +from qiskit.quantum_info import Operator +from qiskit.qasm3 import loads +from scipy.linalg import expm + +X = np.array([[0, 1], [1, 0]]) +Y = np.array([[0, -1j], [1j, 0]]) +Z = np.array([[1, 0], [0, -1]]) + +RY = lambda theta: np.array([[np.cos(theta/2), -np.sin(theta/2)], [np.sin(theta/2), np.cos(theta/2)]]) +RZ = lambda theta: np.array([[np.exp(-1j*theta/2), 0], [0, np.exp(1j*theta/2)]]) + +def parity(x: int, idxs: tuple[int, ...]) -> int: + p = 0 + for i in idxs: + p ^= (x >> i) & 1 + return p + +def hamiltonian_from_xor_phase_poly(n: int, poly: dict, global_phase=0.0): + dim = 1 << n + H = np.zeros((dim, dim), dtype=float) + + for x in range(dim): + phase = global_phase + for idxs, angle in poly.items(): + if parity(x, idxs): + phase += angle + H[x, x] = phase + + return H + +def make_unitary(poly): + H = hamiltonian_from_xor_phase_poly(4, poly) + U_expm = expm(1j * H) + return U_expm + +def unitary_from_state(state: np.ndarray) -> np.ndarray: + state = np.asarray(state, dtype=complex).reshape(-1) + norm = np.linalg.norm(state) + if norm == 0: + raise ValueError("State vector must be non-zero.") + state = state / norm + + basis = [state] + dim = state.size + for i in range(dim): + v = np.zeros(dim, dtype=complex) + v[i] = 1.0 + for b in basis: + v = v - np.vdot(b, v) * b + v_norm = np.linalg.norm(v) + if v_norm > 1e-12: + basis.append(v / v_norm) + if len(basis) == dim: + break + + if len(basis) != dim: + raise ValueError("Failed to construct a full orthonormal basis.") + + return np.column_stack(basis) + +def _compute_challenge12(): + """U = ∏ exp(-i π k/8 P) for all terms in challenge12.json.""" + _pm = {'I': np.eye(2, dtype=complex), 'X': X, 'Y': Y, 'Z': Z} + _path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'challenge12.json') + with open(_path) as f: + _data = json.load(f) + _n = _data['n'] + _dim = 1 << _n + _U = np.eye(_dim, dtype=complex) + for _term in _data['terms']: + # Kron in reversed order so qubit 0 is LSB (Qiskit convention) + _P = _pm[_term['pauli'][-1]] + for _i in range(len(_term['pauli']) - 2, -1, -1): + _P = np.kron(_P, _pm[_term['pauli'][_i]]) + _theta = np.pi * _term['k'] / 8 + # exp(-i θ P) = cos θ · I − i sin θ · P (P² = I) + _U = (np.cos(_theta) * np.eye(_dim) - 1j * np.sin(_theta) * _P) @ _U + return _U + +expected = { + 1: np.block([ + [np.eye(2), np.zeros((2,2))], + [np.zeros((2,2)), Y] + ]), + 2: np.block([ + [np.eye(2), np.zeros((2,2))], + [np.zeros((2,2)), RY(np.pi/7)] + ]), + 3: scipy.linalg.expm(1j*np.pi/7*(np.kron(Z,Z))), + 4: scipy.linalg.expm(1j*np.pi/7*(np.kron(X,X)+np.kron(Y,Y))), + 5: scipy.linalg.expm(1j*np.pi/4*(np.kron(X,X)+np.kron(Y,Y)+np.kron(Z,Z))), + 6: scipy.linalg.expm(1j*np.pi/7*(np.kron(X,X)+np.kron(Z,np.eye(2))+np.kron(np.eye(2),Z))), + 7: unitary_from_state(np.array([ + 0.1061479384 - 0.679641467j, + -0.3622775887 - 0.453613136j, + 0.2614190429 + 0.0445330969j, + 0.3276449279 - 0.1101628411j, + ], dtype=complex)), + 8: np.block([ + [0.5, 0.5, 0.5, 0.5], + [0.5, 0.5j, -0.5, -0.5j], + [0.5, -0.5, 0.5, -0.5], + [0.5, -0.5j, -0.5, 0.5j] + ]), + 9: np.array([ + [1, 0, 0, 0], + [0, 0, -0.5+0.5j, 0.5+0.5j], + [0, 1j, 0, 0], + [0, 0, -0.5+0.5j, -0.5-0.5j] + ]), + 10: quantum_info.random_unitary(4, seed=42).data, + 11: make_unitary({(0,): np.pi/4, (1,): np.pi/4, (2,): np.pi/4, (3,): np.pi/4, + (0,1): np.pi/4, (0,2): np.pi/4, (0,3): np.pi/4, + (1,2): np.pi/4, (1,3): np.pi/4, (2,3): np.pi/4, + (1,2,3): np.pi/4}), + 12: _compute_challenge12(), +} + +def load_qasm_circuit(path: str) -> tuple[QuantumCircuit, str]: + with open(path, "r", encoding="utf-8") as f: + qasm3_src = f.read() + + qc = loads(qasm3_src) + return qc, qasm3_src + + +def circuit_unitary(qc: QuantumCircuit) -> np.ndarray: + return Operator(qc).data + +def distance_global_phase(actual: np.ndarray, expected: np.ndarray) -> np.ndarray: + best_phase = 1.0 + 0.0j + min_dist = float('inf') + + for phase in np.arange(-2 * np.pi, 2 * np.pi, .0001): + phase_factor = np.exp(1j * phase) + dist = np.linalg.norm((phase_factor * actual) - expected) + + if dist < min_dist: + min_dist = dist + best_phase = phase_factor + + print(f"Best phase found: {best_phase:.4f} (Distance: {min_dist:.2e})") + aligned_matrix = best_phase * actual + + return aligned_matrix + + +def parse_unitary_id_from_filename(path: str) -> int: + base = os.path.basename(path) + m = re.search(r"(\d+)", base) + if not m: + raise ValueError(f"Could not infer unitary id from filename: {base}. Use --id.") + return int(m.group(1)) + +def count_t_gates_manual(qasm_str: str) -> int: + gate_t_counts = {} + + gate_defs = re.findall(r"gate\s+(\w+).*?\{(.*?)\}", qasm_str, re.DOTALL) + + for _ in range(5): + for name, body in gate_defs: + current_count = len(re.findall(r"\b(t|tdg)\b", body)) + + for other_name, other_count in gate_t_counts.items(): + if other_name != name: + calls = len(re.findall(rf"\b{other_name}\b", body)) + current_count += (calls * other_count) + + gate_t_counts[name] = current_count + + main_body = re.sub(r"gate.*?\{.*?\}", "", qasm_str, flags=re.DOTALL) + + total_t = len(re.findall(r"\b(t|tdg)\b", main_body)) + + for name, count in gate_t_counts.items(): + calls = len(re.findall(rf"\b{name}\b", main_body)) + total_t += (calls * count) + + return total_t + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("qasm_file", help="Path to QASM file (e.g., unitary1.qasm)") + args = parser.parse_args() + + unitary_id = parse_unitary_id_from_filename(args.qasm_file) + + if unitary_id not in expected: + raise KeyError( + f"Unitary id {unitary_id} not found in expected dict. " + f"Available keys: {sorted(expected.keys())}" + ) + + U_expected = np.asarray(expected[unitary_id], dtype=complex) + + qc, qasm_src = load_qasm_circuit(args.qasm_file) + + if qc.num_clbits > 0: + inst_names = [inst.operation.name for inst in qc.data] + if "measure" in inst_names or "reset" in inst_names: + raise ValueError("Circuit contains measure/reset; cannot form a single unitary Operator.") + + U_qasm = circuit_unitary(qc) + + if U_qasm.shape != U_expected.shape: + raise ValueError( + f"Shape mismatch:\n" + f" from QASM: {U_qasm.shape}\n" + f" expected dict: {U_expected.shape}\n" + f"QASM qubits: {qc.num_qubits} -> expected dimension {2**qc.num_qubits}" + ) + + if unitary_id == 7: + psi_expected = U_expected[:, 0] + psi_actual = U_qasm[:, 0] + + print("Expected state:") + print(np.round(psi_expected, 6)) + print() + + overlap = np.vdot(psi_expected, psi_actual) + best_phase = np.conj(overlap) / abs(overlap) if abs(overlap) > 0 else 1.0 + 0.0j + aligned_state = best_phase * psi_actual + + print("Actual state (phase-aligned U|00⟩):") + print(np.round(aligned_state, 6)) + print() + + fidelity = abs(overlap) ** 2 + print(f"Fidelity |⟨ψ|U|00⟩|²: {fidelity:.10f}") + else: + print("Expected matrix:") + print(np.round(U_expected, 6)) + print() + + aligned = distance_global_phase(U_qasm, U_expected) + + print("Best-aligned actual matrix (phase * actual, rounded to 6 decimals):") + print(np.round(aligned, 6)) + print() + + err = np.linalg.norm(aligned - U_expected) + print(f"Min |Δ|: {err:.3e}") + + t_count = count_t_gates_manual(qasm_src) + print(f"T-gate count: {t_count}") + +if __name__ == "__main__": + main() diff --git a/unitary/unitary1.py b/unitary/unitary1.py new file mode 100644 index 0000000..96a8c7f --- /dev/null +++ b/unitary/unitary1.py @@ -0,0 +1,11 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 + +qc = QuantumCircuit(2) +qc.sdg(0) +qc.cx(1, 0) +qc.s(0) + +qasm3_str = dumps3(qc) +with open("qasm/unitary1.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/unitary10.py b/unitary/unitary10.py new file mode 100644 index 0000000..670a46f --- /dev/null +++ b/unitary/unitary10.py @@ -0,0 +1,234 @@ +""" +unitary10_multicore.py -- multiprocessing across target distances + +This keeps the same optimization logic as unitary10.py, but evaluates each +TARGET_DISTANCE in a separate process to improve CPU utilization. Results are +printed in ascending target order to match the sequential script's output order. +""" + +import os as _os +_os.environ.setdefault("OMP_NUM_THREADS", "1") +_os.environ.setdefault("MKL_NUM_THREADS", "1") +_os.environ.setdefault("OPENBLAS_NUM_THREADS", "1") +_os.environ.setdefault("NUMEXPR_NUM_THREADS", "1") + +import os +import argparse +import multiprocessing as mp +import numpy as np + +from qiskit import QuantumCircuit, quantum_info, transpile +from qiskit.quantum_info import Operator +from qiskit.qasm3 import dumps as dumps3 +from qiskit.circuit.library import UnitaryGate + +from optim import _synthesize, normalize_angle, build_circuit, total_t_count + +ANGLE_TOL = 1e-1 + +TARGET_DISTANCES = [ + 1e-1, 7e-2, 5e-2, 3e-2, 2e-2, 1e-2, 7e-3, 5e-3, 3e-3, 2e-3, 1e-3 +] + +# Ultra-granular epsilon sweep: 100 points from 1e-1 to 1e-9 +EPS_COARSE_SWEEP = np.logspace(-1, -9, 100) + +RELAXATION_FACTORS = [ + 100, 50, 30, 20, 15, 10, 7, 5, 3, 2, 1.5, 1.3, 1.2, 1.1, 1.05, 1.02 +] + + +def operator_distance(actual, reference): + d = actual.shape[0] + inner = np.trace(actual.conj().T @ reference) + return float(np.sqrt(max(2 * d - 2 * np.abs(inner), 0.0))) + + +def extract_ops(target_matrix): + template_qc = QuantumCircuit(2) + template_qc.append(UnitaryGate(target_matrix), [0, 1]) + template = transpile( + template_qc, + basis_gates=["u3", "cx"], + optimization_level=2, + seed_transpiler=0, + ) + + ops = [] + for inst in template.data: + name = inst.operation.name + qubits = [template.find_bit(q).index for q in inst.qubits] + if name == "cx": + ops.append(("cx", qubits[0], qubits[1])) + elif name in ("u3", "u"): + theta, phi, lam = [float(p) for p in inst.operation.params] + q = qubits[0] + for axis, angle in [("rz", lam), ("ry", theta), ("rz", phi)]: + a = normalize_angle(angle) + if abs(a) > ANGLE_TOL: + ops.append((axis, q, a)) + elif name in ("rz", "ry", "rx"): + a = normalize_angle(float(inst.operation.params[0])) + if abs(a) > ANGLE_TOL: + ops.append((name, qubits[0], a)) + elif name == "p": + a = normalize_angle(float(inst.operation.params[0])) + if abs(a) > ANGLE_TOL: + ops.append(("rz", qubits[0], a)) + + return ops + + +def optimize_for_target(args): + target_dist, ops, rotation_indices, target = args + n_rotations = len(rotation_indices) + cache = {} + + # Phase 1: Uniform sweep + best_uniform_eps = None + for eps in EPS_COARSE_SWEEP: + eps_list = [float(eps)] * n_rotations + qc = build_circuit(ops, eps_list, cache) + dist = operator_distance(Operator(qc).data, target) + if dist < target_dist: + best_uniform_eps = float(eps) + break + + if best_uniform_eps is None: + return (target_dist, False, None, None, None) + + # Phase 2: Per-rotation relaxation + current_eps = [best_uniform_eps] * n_rotations + current_t = total_t_count(ops, rotation_indices, current_eps, cache) + current_dist = operator_distance(Operator(build_circuit(ops, current_eps, cache)).data, target) + + while True: + any_improved = False + for j in range(n_rotations): + idx = rotation_indices[j] + axis, angle, orig_eps = ops[idx][0], ops[idx][2], current_eps[j] + _, orig_tc_j = _synthesize(axis, angle, orig_eps, cache) + + for factor in RELAXATION_FACTORS: + trial_eps = orig_eps * factor + if trial_eps > 0.5: + continue + + _, trial_tc_j = _synthesize(axis, angle, trial_eps, cache) + if trial_tc_j >= orig_tc_j: + continue + + trial_eps_list = current_eps.copy() + trial_eps_list[j] = trial_eps + trial_dist = operator_distance( + Operator(build_circuit(ops, trial_eps_list, cache)).data, target + ) + + if trial_dist < target_dist: + current_t = current_t - orig_tc_j + trial_tc_j + current_eps[j] = trial_eps + current_dist = trial_dist + any_improved = True + break + if not any_improved: + break + + final_qc = build_circuit(ops, current_eps, cache) + final_t = total_t_count(ops, rotation_indices, current_eps, cache) + final_dist = operator_distance(Operator(final_qc).data, target) + + qasm_str = dumps3(final_qc) + return (target_dist, True, final_t, final_dist, qasm_str) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--workers", + type=int, + default=os.cpu_count() or 1, + help="Number of worker processes (default: os.cpu_count()).", + ) + parser.add_argument( + "--mp-start", + type=str, + default="spawn", + choices=["spawn", "fork", "forkserver"], + help="Multiprocessing start method (default: spawn).", + ) + args = parser.parse_args() + + if not os.path.exists("qasm"): + os.makedirs("qasm") + + unitary = quantum_info.random_unitary(4, seed=42) + target = unitary.data + + ops = extract_ops(target) + rotation_indices = [i for i, op in enumerate(ops) if op[0] in ("rx", "ry", "rz")] + n_rotations = len(rotation_indices) + + print(f"Rotations to optimize: {n_rotations}") + + tasks = [(td, ops, rotation_indices, target) for td in TARGET_DISTANCES] + + ctx = mp.get_context(args.mp_start) + with ctx.Pool(processes=args.workers) as pool: + results = list(pool.imap_unordered(optimize_for_target, tasks, chunksize=1)) + + for target_dist, success, final_t, final_dist, qasm_str in sorted(results, key=lambda r: r[0]): + print("\n" + "=" * 60) + print(f"RUNNING OPTIMIZATION FOR TARGET DISTANCE: {target_dist}") + print("=" * 60) + if not success: + print(f"Warning: Target distance {target_dist} not reachable in sweep.") + continue + print(f"DONE -> Target: {target_dist} | Final T: {final_t} | Final Dist: {final_dist:.6e}") + + # Pick a single "balanced" result: normalize T-count and distance, then + # minimize a 50/50 composite score. + candidates = [ + (target_dist, final_t, final_dist, qasm_str) + for target_dist, success, final_t, final_dist, qasm_str in results + if success and qasm_str + ] + + if not candidates: + print("\nNo successful candidates; no QASM file written.") + return + + t_values = [c[1] for c in candidates] + d_values = [c[2] for c in candidates] + t_min, t_max = min(t_values), max(t_values) + d_min, d_max = min(d_values), max(d_values) + + def _norm(val, vmin, vmax): + if vmax == vmin: + return 0.0 + return (val - vmin) / (vmax - vmin) + + best = None + for target_dist, final_t, final_dist, qasm_str in candidates: + t_norm = _norm(final_t, t_min, t_max) + d_norm = _norm(final_dist, d_min, d_max) + score = 0.5 * t_norm + 0.5 * d_norm + key = (score, final_t, final_dist) + if best is None or key < best[0]: + best = (key, target_dist, final_t, final_dist, qasm_str) + + _, best_target, best_t, best_dist, best_qasm = best + + qasm_path = os.path.join("qasm", "unitary10.qasm") + with open(qasm_path, "w") as f: + f.write(best_qasm) + print("\n" + "=" * 60) + print("SAVED SINGLE BALANCED RESULT") + print("=" * 60) + print(f"Selected target: {best_target} | T: {best_t} | Dist: {best_dist:.6e}") + print(f"Saved to {qasm_path}") + + print("\nAll target optimizations complete.") + + +if __name__ == "__main__": + main() diff --git a/unitary/unitary11.py b/unitary/unitary11.py new file mode 100644 index 0000000..666283c --- /dev/null +++ b/unitary/unitary11.py @@ -0,0 +1,50 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 + +from rmsynth import Circuit, Optimizer +from rmsynth.core import extract_phase_coeffs + +circ = Circuit(4) +circ.add_phase(0, 1); circ.add_phase(1, 1); circ.add_phase(2, 1); circ.add_phase(3, 1) +circ.add_cnot(0, 1); circ.add_phase(1, 1); circ.add_cnot(0, 1) +circ.add_cnot(0, 2); circ.add_phase(2, 1); circ.add_cnot(0, 2) +circ.add_cnot(0, 3); circ.add_phase(3, 1); circ.add_cnot(0, 3) + +circ.add_cnot(1, 2); circ.add_phase(2, 1); circ.add_cnot(1, 2) +circ.add_cnot(1, 3); circ.add_phase(3, 1); circ.add_cnot(1, 3) + +circ.add_cnot(2, 3); circ.add_phase(3, 1); circ.add_cnot(2, 3) + +circ.add_cnot(1, 3) +circ.add_cnot(2, 3) +circ.add_phase(3, 1) +circ.add_cnot(2, 3) +circ.add_cnot(1, 3) + +opt = Optimizer(decoder="rpa", effort=3, policy="distance+depth", policy_lambda=5) +new_circ, rep = opt.optimize(circ) + +n = new_circ.n +a = extract_phase_coeffs(new_circ) + +qc = QuantumCircuit(4) + +for key in range(1, 2**n): + val = a.get(key, 0) + if val == 0: + continue + qubits = [i for i in range(n) if key & (1 << i)] + target = qubits[-1] + controls = qubits[:-1] + for c in controls: + qc.cx(c, target) + for _ in range(val // 2): + qc.s(target) + if val % 2: + qc.t(target) + for c in reversed(controls): + qc.cx(c, target) + +qasm3_str = dumps3(qc) +with open("qasm/unitary11.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/unitary12.py b/unitary/unitary12.py new file mode 100644 index 0000000..ffc6a8b --- /dev/null +++ b/unitary/unitary12.py @@ -0,0 +1,244 @@ +import json +import numpy as np +from functools import reduce +from rmsynth.core import coeffs_to_vec, synthesize_from_coeffs +from rmsynth import Optimizer +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 + +with open('./challenge12.json') as f: + data = json.load(f) + +n = data['n'] # 9 +terms = data['terms'] +m = len(terms) # 255 +pauli_strings = [t['pauli'] for t in terms] +ks = [t['k'] for t in terms] + +I2 = np.eye(2, dtype=complex) +X = np.array([[0, 1], [1, 0]], dtype=complex) +Y = np.array([[0, -1j], [1j, 0]], dtype=complex) +Z = np.array([[1, 0], [0, -1]], dtype=complex) +_pauli = {'I': I2, 'X': X, 'Y': Y, 'Z': Z} + +CNOT_TABLE = { + ('I','I'):('I','I', 1), ('I','X'):('I','X', 1), + ('I','Y'):('Z','Y', 1), ('I','Z'):('Z','Z', 1), + ('X','I'):('X','X', 1), ('X','X'):('X','I', 1), + ('X','Y'):('Y','Z', 1), ('X','Z'):('Y','Y',-1), + ('Y','I'):('Y','X', 1), ('Y','X'):('Y','I', 1), + ('Y','Y'):('X','Z',-1), ('Y','Z'):('X','Y', 1), + ('Z','I'):('Z','I', 1), ('Z','X'):('Z','X', 1), + ('Z','Y'):('I','Y', 1), ('Z','Z'):('I','Z', 1), +} + +def apply_H(chars, signs, q): + """H: X<->Z, Y->-Y""" + for j in range(len(chars)): + c = chars[j][q] + if c == 'X': chars[j][q] = 'Z' + elif c == 'Z': chars[j][q] = 'X' + elif c == 'Y': signs[j] *= -1 + +def apply_Sdg(chars, signs, q): + """S†: X->-Y, Y->X, Z->Z, I->I""" + for j in range(len(chars)): + c = chars[j][q] + if c == 'X': chars[j][q] = 'Y'; signs[j] *= -1 + elif c == 'Y': chars[j][q] = 'X' + +def apply_CX(chars, signs, ctrl, tgt): + """CNOT(ctrl, tgt) conjugation.""" + for j in range(len(chars)): + nc, nt, s = CNOT_TABLE[(chars[j][ctrl], chars[j][tgt])] + chars[j][ctrl] = nc + chars[j][tgt] = nt + signs[j] *= s + +def find_basis(pauli_strings, n_qubits): + """Row-reduce the symplectic matrix to find independent generators.""" + m = len(pauli_strings) + M = np.zeros((m, 2*n_qubits), dtype=int) + for j, p in enumerate(pauli_strings): + for i, c in enumerate(p): + if c in ('X','Y'): M[j, i] = 1 + if c in ('Z','Y'): M[j, i+n_qubits] = 1 + indices = list(range(m)) + current = 0 + for col in range(2*n_qubits): + pivot = -1 + for row in range(current, m): + if M[row, col] == 1: + pivot = row; break + if pivot == -1: + continue + if pivot != current: + M[[current, pivot]] = M[[pivot, current]] + indices[current], indices[pivot] = indices[pivot], indices[current] + for row in range(m): + if row != current and M[row, col] == 1: + M[row] = (M[row] + M[current]) % 2 + current += 1 + return indices[:current], current + +def find_diag_gates(pauli_strings, n_qubits): + """ + Find Clifford gates that simultaneously diagonalize all commuting Paulis. + Uses internal row operations to guide gate selection. + Returns only the gate list (no row-op side effects leak out). + """ + m = len(pauli_strings) + chars = [list(p) for p in pauli_strings] + signs = [1] * m + + basis_indices, rank = find_basis(pauli_strings, n_qubits) + print(f" Symplectic rank: {rank}") + + gates = [] + diag_info = [] + + for gen_idx in basis_indices: + for (used_q, diag_idx) in diag_info: + ch = chars[gen_idx][used_q] + assert ch in ('I', 'Z'), \ + f"Commutativity violated: gen {gen_idx} has {ch} at used qubit {used_q}" + if ch == 'Z': + chars[gen_idx][used_q] = 'I' + signs[gen_idx] *= signs[diag_idx] + + non_I = [i for i in range(n_qubits) if chars[gen_idx][i] != 'I'] + if not non_I: + continue + + for q in non_I: + c = chars[gen_idx][q] + if c == 'X': + gates.append(('H', q)) + apply_H(chars, signs, q) + elif c == 'Y': + gates.append(('Sdg', q)) + apply_Sdg(chars, signs, q) + gates.append(('H', q)) + apply_H(chars, signs, q) + + z_qubits = [i for i in range(n_qubits) if chars[gen_idx][i] == 'Z'] + target = z_qubits[0] + for q in z_qubits[1:]: + gates.append(('CX', q, target)) + apply_CX(chars, signs, q, target) + + diag_info.append((target, gen_idx)) + + return gates + +def apply_clifford(pauli_strings, gates): + m = len(pauli_strings) + chars = [list(p) for p in pauli_strings] + signs = [1] * m + for g in gates: + if g[0] == 'H': apply_H(chars, signs, g[1]) + elif g[0] == 'Sdg': apply_Sdg(chars, signs, g[1]) + elif g[0] == 'CX': apply_CX(chars, signs, g[1], g[2]) + return chars, signs + +print("=== Challenge 12: Commuting Pauli Phase Program ===\n") + +print("Step 1: Finding simultaneous diagonalizing Clifford...") +gates = find_diag_gates(pauli_strings, n) +print(f" Clifford circuit: {len(gates)} gates") + +print("Step 2: Computing Z-strings and signs...") +final_chars, final_signs = apply_clifford(pauli_strings, gates) + +for j in range(m): + for i in range(n): + assert final_chars[j][i] in ('I', 'Z'), \ + f"Term {j} ({pauli_strings[j]}) has {final_chars[j][i]} at qubit {i}: {''.join(final_chars[j])}" +print(" ✓ All 255 terms are I/Z after Clifford") + +print("Step 3: Computing phase polynomial...") +phase_coeffs = {} +for j in range(m): + support = sum(1 << i for i in range(n) if final_chars[j][i] == 'Z') + assert support > 0, f"Term {j} mapped to identity" + coeff = (ks[j] * final_signs[j]) % 8 + assert support not in phase_coeffs, f"Duplicate support {support:09b} from terms" + phase_coeffs[support] = coeff + +n1 = sum(1 for v in phase_coeffs.values() if v == 1) +n7 = sum(1 for v in phase_coeffs.values() if v == 7) +print(f" {len(phase_coeffs)} terms: {n1} T-gates (coeff=1), {n7} T†-gates (coeff=7)") + +print("Step 4: Synthesizing CNOT-optimised phase polynomial...") +vec = coeffs_to_vec(phase_coeffs, n) +synth_circ = synthesize_from_coeffs(vec, n, use_schedule=True) +opt = Optimizer(decoder="rpa", effort=3, policy="distance", policy_lambda=5) +circ_opt, _ = opt.optimize(synth_circ) +print(f" Phase polynomial T-count: {circ_opt.t_count()}") +print(f" Phase polynomial CNOT count: {sum(1 for op in circ_opt.ops if op.kind=='cnot')}") + +print("Step 7: Building Qiskit circuit (C + phase_poly + C†)...") +qc = QuantumCircuit(n) + +for g in gates: + if g[0] == 'H': qc.h(g[1]) + elif g[0] == 'Sdg': + qc.tdg(g[1]); qc.tdg(g[1]) + elif g[0] == 'CX': qc.cx(g[1], g[2]) + +for op in circ_opt.ops: + if op.kind == 'cnot': + qc.cx(op.ctrl, op.tgt) + elif op.kind == 'phase': + k = op.k % 8 + if k == 0: + continue + if k <= 4: + for _ in range(k): qc.t(op.q) + else: + for _ in range(8 - k): qc.tdg(op.q) + +for g in reversed(gates): + if g[0] == 'H': qc.h(g[1]) + elif g[0] == 'Sdg': + qc.t(g[1]); qc.t(g[1]) + elif g[0] == 'CX': qc.cx(g[1], g[2]) + +n_sdg = sum(1 for g in gates if g[0] == 'Sdg') +t_clifford = 4 * n_sdg +t_poly = circ_opt.t_count() +print(f" T from Clifford: {t_clifford} ({n_sdg} Sdg gates × 4)") +print(f" T from phase poly: {t_poly}") +print(f" Total T-gate count: {t_clifford + t_poly}") + +# Step 8: Save QASM +print("Step 8: Saving QASM...") +qasm3_str = dumps3(qc) +with open('../qasm/unitary12.qasm', 'w') as f: + f.write(qasm3_str) +print(" Saved qasm/unitary12.qasm") + +print("\n=== Verification ===") +from qiskit.quantum_info import Operator + +U_circuit = Operator(qc).data + +print("Computing target unitary...") +dim = 2**n +U_target = np.eye(dim, dtype=complex) +for term in terms: + P = reduce(np.kron, [_pauli[ch] for ch in reversed(term['pauli'])]) + theta = np.pi * term['k'] / 8 + U_target = (np.cos(theta) * np.eye(dim) - 1j * np.sin(theta) * P) @ U_target + +tr = np.trace(U_circuit.conj().T @ U_target) +phase = tr / abs(tr) if abs(tr) > 1e-12 else 1.0 +U_aligned = phase * U_circuit + +err = np.linalg.norm(U_aligned - U_target) / np.sqrt(dim) +print(f"Normalized Frobenius distance: {err:.6e}") +if err < 1e-6: + print("✓ Circuit matches target unitary!") +else: + print("✗ Circuit does NOT match target unitary!") + print(f" Max element-wise error: {np.max(np.abs(U_aligned - U_target)):.6e}") diff --git a/unitary/unitary2.py b/unitary/unitary2.py new file mode 100644 index 0000000..5503e00 --- /dev/null +++ b/unitary/unitary2.py @@ -0,0 +1,17 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 +from utils import Ry +import math + +theta = math.pi / 7 +epsilon = 3.16e-01 + +qc = QuantumCircuit(2) +qc.append(Ry(theta/2, epsilon).to_gate(), [1]) +qc.cx(0, 1) +qc.append(Ry(-theta/2, epsilon).to_gate(), [1]) +qc.cx(0, 1) + +qasm3_str = dumps3(qc) +with open("qasm/unitary2.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/unitary3.py b/unitary/unitary3.py new file mode 100644 index 0000000..00b3d82 --- /dev/null +++ b/unitary/unitary3.py @@ -0,0 +1,16 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 +from utils import Rz +import math + +theta = math.pi / 7 +epsilon = 3.16e-10 + +qc = QuantumCircuit(2) +qc.cx(0, 1) +qc.append(Rz(-2*theta, epsilon).to_gate(), [1]) +qc.cx(0, 1) + +qasm3_str = dumps3(qc) +with open("qasm/unitary3.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/unitary4.py b/unitary/unitary4.py new file mode 100644 index 0000000..6804c14 --- /dev/null +++ b/unitary/unitary4.py @@ -0,0 +1,29 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 +from utils import Rz +import math + +theta = math.pi / 7 +epsilon = 3.16e-10 + +qc = QuantumCircuit(2) + +qc.h(0); qc.h(1) +qc.s(0); qc.s(1) +qc.h(0); qc.h(1) +qc.cx(0, 1) +qc.append(Rz(-2*theta, epsilon).to_gate(), [1]) +qc.cx(0, 1) +qc.h(0); qc.h(1) +qc.sdg(0); qc.sdg(1) +qc.h(0); qc.h(1) + +qc.h(0); qc.h(1) +qc.cx(0, 1) +qc.append(Rz(-2*theta, epsilon).to_gate(), [1]) +qc.cx(0, 1) +qc.h(0); qc.h(1) + +qasm3_str = dumps3(qc) +with open("qasm/unitary4.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/unitary5.py b/unitary/unitary5.py new file mode 100644 index 0000000..43118ba --- /dev/null +++ b/unitary/unitary5.py @@ -0,0 +1,11 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 + +qc = QuantumCircuit(2) +qc.cx(0, 1) +qc.cx(1, 0) +qc.cx(0, 1) + +qasm3_str = dumps3(qc) +with open("qasm/unitary5.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/unitary6.py b/unitary/unitary6.py new file mode 100644 index 0000000..660f7d2 --- /dev/null +++ b/unitary/unitary6.py @@ -0,0 +1,22 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 +from utils import Rz +import math + +theta = math.pi / 7 +epsilon = 3.16e-10 + +qc = QuantumCircuit(2) + +qc.h(0); qc.h(1) +qc.cx(0, 1) +qc.append(Rz(-2*theta, epsilon).to_gate(), [1]) +qc.cx(0, 1) +qc.h(0); qc.h(1) + +qc.append(Rz(-2*theta, epsilon).to_gate(), [0]) +qc.append(Rz(-2*theta, epsilon).to_gate(), [1]) + +qasm3_str = dumps3(qc) +with open("qasm/unitary6.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/unitary7.py b/unitary/unitary7.py new file mode 100644 index 0000000..62f46d6 --- /dev/null +++ b/unitary/unitary7.py @@ -0,0 +1,404 @@ +import os as _os +_os.environ.setdefault("OMP_NUM_THREADS", "1") +_os.environ.setdefault("MKL_NUM_THREADS", "1") +_os.environ.setdefault("OPENBLAS_NUM_THREADS", "1") +_os.environ.setdefault("NUMEXPR_NUM_THREADS", "1") + +import time +import argparse +import numpy as np +import multiprocessing as mp + +from qiskit import QuantumCircuit, quantum_info, transpile +from qiskit.quantum_info import Operator, Statevector +from qiskit.qasm3 import dumps as dumps3 +from qiskit.circuit.library import UnitaryGate + +from utils import Rz, Ry, Rx +from test import count_t_gates_manual + +statevector = quantum_info.random_statevector(4, seed=42).data +_target_sv = np.asarray(statevector, dtype=complex).flatten() +_target_sv_conj = np.conj(_target_sv) + +N_CANDIDATES = 200 +CANDIDATE_SEED = 42 +TARGET_FIDELITY = 0.999999 +ANGLE_TOL = 1e-9 + +EPS_COARSE = [10**(-i/2) for i in range(2, 18)] +RELAXATION_FACTORS = [100, 50, 30, 20, 15, 10, 7, 5, 3, 2, 1.5, 1.3, 1.2, 1.1, 1.05, 1.02] + +FIDELITY_MARGIN = 5e-11 + +_SV0 = Statevector.from_int(0, 4) + +_CX_PERM = { + (0, 1): np.array([0, 3, 2, 1], dtype=np.int64), + (1, 0): np.array([0, 1, 3, 2], dtype=np.int64), +} + +def _gram_schmidt_completion(sv): + sv = np.asarray(sv, dtype=complex).flatten() + sv = sv / np.linalg.norm(sv) + basis = [sv] + for i in range(4): + v = np.zeros(4, dtype=complex) + v[i] = 1.0 + for b in basis: + v -= np.vdot(b, v) * b + n = np.linalg.norm(v) + if n > 1e-12: + basis.append(v / n) + if len(basis) == 4: + break + return np.column_stack(basis) + + +def generate_candidates(sv, n, seed): + base = _gram_schmidt_completion(sv) + candidates = [base] + rng = np.random.default_rng(seed) + for _ in range(n - 1): + A = rng.standard_normal((3, 3)) + 1j * rng.standard_normal((3, 3)) + Q, R = np.linalg.qr(A) + Q = Q @ np.diag(R.diagonal() / np.abs(R.diagonal())) + D = np.eye(4, dtype=complex) + D[1:, 1:] = Q + candidates.append(base @ D) + return candidates + +def normalize_angle(a): + return float((a + np.pi) % (2 * np.pi) - np.pi) + + +def extract_ops(target_matrix): + qc = QuantumCircuit(2) + qc.append(UnitaryGate(target_matrix), [0, 1]) + template = transpile( + qc, basis_gates=["u3", "cx"], + optimization_level=2, seed_transpiler=0, + ) + ops = [] + for inst in template.data: + name = inst.operation.name + qubits = [template.find_bit(q).index for q in inst.qubits] + + if name == "cx": + ops.append(("cx", qubits[0], qubits[1])) + + elif name in ("u3", "u"): + theta, phi, lam = [float(p) for p in inst.operation.params] + q = qubits[0] + for axis, angle in [("rz", lam), ("ry", theta), ("rz", phi)]: + a = normalize_angle(angle) + if abs(a) > ANGLE_TOL: + ops.append((axis, q, a)) + + elif name in ("rz", "ry", "rx"): + a = normalize_angle(float(inst.operation.params[0])) + if abs(a) > ANGLE_TOL: + ops.append((name, qubits[0], a)) + + elif name == "p": + a = normalize_angle(float(inst.operation.params[0])) + if abs(a) > ANGLE_TOL: + ops.append(("rz", qubits[0], a)) + + elif name in ("id", "barrier"): + pass + + else: + raise ValueError(f"Unexpected gate: {name}") + + return ops + +_cache = {} # key -> {"gate": Gate, "t_count": int, "mat": np.ndarray} + + +def synthesize(axis, angle, eps): + """Synthesize one rotation into Clifford+T. Returns (gate, t_count).""" + key = (axis, float(angle), float(eps)) + if key in _cache and _cache[key].get("gate") is not None: + e = _cache[key] + return e["gate"], e["t_count"] + sub = {"rz": Rz, "ry": Ry, "rx": Rx}[axis](float(angle), float(eps)) + gate = sub.to_gate() + tc = count_t_gates_manual(dumps3(sub)) + _cache[key] = {"gate": gate, "t_count": tc, "mat": None} + return gate, tc + + +def gate_matrix(axis, angle, eps): + key = (axis, float(angle), float(eps)) + if key not in _cache or _cache[key].get("gate") is None: + synthesize(axis, angle, eps) + e = _cache[key] + if e["mat"] is None: + e["mat"] = Operator(e["gate"]).data + return e["mat"] + + +def apply_1q_gate_batch(state_b4, U2, qubit): + """ + state_b4: (B,4) + U2: (2,2) or (B,2,2) + """ + B = state_b4.shape[0] + st = state_b4.reshape(B, 2, 2) + if qubit == 0: + if U2.ndim == 2: + out = np.einsum("bij,kj->bik", st, U2) + else: + out = np.einsum("bij,bkj->bik", st, U2) + elif qubit == 1: + if U2.ndim == 2: + out = np.einsum("ij,bjk->bik", U2, st) + else: + out = np.einsum("bij,bjk->bik", U2, st) + else: + raise ValueError("qubit must be 0 or 1") + return out.reshape(B, 4) + + +def apply_cx_batch(state_b4, control, target): + perm = _CX_PERM[(control, target)] + return state_b4[:, perm] + + +def simulate_batch(ops, eps_matrix): + """ + eps_matrix: (B, n_rot) float + returns: (B,4) complex statevectors + """ + B = eps_matrix.shape[0] + state = np.zeros((B, 4), dtype=np.complex128) + state[:, 0] = 1.0 + + rot_idx = 0 + for op in ops: + if op[0] == "cx": + state = apply_cx_batch(state, op[1], op[2]) + else: + axis, q, angle = op[0], op[1], op[2] + eps_vals = eps_matrix[:, rot_idx] + if np.all(eps_vals == eps_vals[0]): + U = gate_matrix(axis, angle, float(eps_vals[0])) + else: + U = np.stack([gate_matrix(axis, angle, float(eps)) for eps in eps_vals], axis=0) + state = apply_1q_gate_batch(state, U, q) + rot_idx += 1 + + return state + + +def fidelities_from_states(states_b4): + overlaps = np.sum(_target_sv_conj[None, :] * states_b4, axis=1) # + return np.abs(overlaps) ** 2 + + +def fidelity_exact_qiskit(qc): + out = _SV0.evolve(qc).data + overlap = np.vdot(_target_sv, out) + return float(np.abs(overlap) ** 2) + +def build_circuit(ops, eps_list): + """Assemble the full 2-qubit Clifford+T circuit.""" + qc = QuantumCircuit(2) + rot_idx = 0 + for op in ops: + if op[0] == "cx": + qc.cx(op[1], op[2]) + else: + gate, _ = synthesize(op[0], op[2], eps_list[rot_idx]) + qc.append(gate, [op[1]]) + rot_idx += 1 + return qc + + +def total_t_count(ops, rotation_indices, eps_list): + """Sum T-counts over all synthesized rotations.""" + return sum( + synthesize(ops[idx][0], ops[idx][2], eps_list[j])[1] + for j, idx in enumerate(rotation_indices) + ) + +def optimize_candidate_ops(ops, cid): + rotation_indices = [i for i, op in enumerate(ops) if op[0] in ("rx", "ry", "rz")] + n_rot = len(rotation_indices) + + eps_vals = np.array([float(e) for e in EPS_COARSE], dtype=np.float64) + eps_matrix = np.tile(eps_vals[:, None], (1, n_rot)) + states = simulate_batch(ops, eps_matrix) + fids = fidelities_from_states(states) + + hit_eps = None + for eps, fid in zip(eps_vals.tolist(), fids.tolist()): + if fid >= TARGET_FIDELITY + FIDELITY_MARGIN: + hit_eps = eps + break + if fid >= TARGET_FIDELITY - FIDELITY_MARGIN: + qc_tmp = build_circuit(ops, [eps] * n_rot) + if fidelity_exact_qiskit(qc_tmp) >= TARGET_FIDELITY: + hit_eps = eps + break + + if hit_eps is None: + return (cid, None) + + current_eps = [float(hit_eps)] * n_rot + current_t = total_t_count(ops, rotation_indices, current_eps) + + max_iterations = 50 + for _ in range(max_iterations): + improved = False + for j in range(n_rot): + idx = rotation_indices[j] + axis = ops[idx][0] + angle = ops[idx][2] + orig_eps = float(current_eps[j]) + _, orig_tc = synthesize(axis, angle, orig_eps) + + trial_eps_list = [] + trial_tc_list = [] + for factor in RELAXATION_FACTORS: + trial_eps = orig_eps * float(factor) + if trial_eps > 0.5: + continue + _, trial_tc = synthesize(axis, angle, trial_eps) + if trial_tc >= orig_tc: + continue + trial_eps_list.append(float(trial_eps)) + trial_tc_list.append(int(trial_tc)) + + if not trial_eps_list: + continue + + B = len(trial_eps_list) + eps_matrix = np.tile(np.array(current_eps, dtype=np.float64), (B, 1)) + eps_matrix[:, j] = np.array(trial_eps_list, dtype=np.float64) + + states = simulate_batch(ops, eps_matrix) + trial_fids = fidelities_from_states(states) + + chosen = None + for k in range(B): + fid = float(trial_fids[k]) + if fid >= TARGET_FIDELITY + FIDELITY_MARGIN: + chosen = k + break + if fid >= TARGET_FIDELITY - FIDELITY_MARGIN: + trial_eps_vec = current_eps.copy() + trial_eps_vec[j] = trial_eps_list[k] + qc_tmp = build_circuit(ops, trial_eps_vec) + if fidelity_exact_qiskit(qc_tmp) >= TARGET_FIDELITY: + chosen = k + break + + if chosen is not None: + new_eps = trial_eps_list[chosen] + new_tc = trial_tc_list[chosen] + current_eps[j] = new_eps + current_t += new_tc - orig_tc + improved = True + + if not improved: + break + + qc_final = build_circuit(ops, current_eps) + fid_final = fidelity_exact_qiskit(qc_final) + + return (cid, (current_t, fid_final, ops, rotation_indices, current_eps)) + +def worker_task(args): + cid, cand_matrix = args + ops = extract_ops(cand_matrix) + return optimize_candidate_ops(ops, cid) + +def _default_mp_start(): + methods = mp.get_all_start_methods() + return "fork" if "fork" in methods else "spawn" + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--workers", type=int, default=_os.cpu_count() or 1, + help="Number of processes. Default: os.cpu_count().") + parser.add_argument("--mp-start", type=str, default=_default_mp_start(), + choices=mp.get_all_start_methods(), + help="Multiprocessing start method.") + parser.add_argument("--quiet", action="store_true", help="Less printing.") + args = parser.parse_args() + + candidates = generate_candidates(_target_sv, N_CANDIDATES, CANDIDATE_SEED) + + ctx = mp.get_context(args.mp_start) + tasks = [(i, candidates[i]) for i in range(N_CANDIDATES)] + + print(f"CPU workers: {args.workers} (mp-start={args.mp_start})") + print(f"Statevector: {np.round(_target_sv, 6)}") + print(f"Candidates: {N_CANDIDATES} | fidelity threshold: {TARGET_FIDELITY}") + print("=" * 60) + + results = {} + + t0 = time.perf_counter() + with ctx.Pool(processes=args.workers) as pool: + for cid, res in pool.imap_unordered(worker_task, tasks, chunksize=1): + results[cid] = res + + if args.quiet: + continue + + if res is None: + print(f" [{cid:2d}] SKIP – fidelity threshold not reached") + else: + tc, fid, ops, rot_idx, eps_list = res + n_rot = len(rot_idx) + n_cx = sum(1 for op in ops if op[0] == "cx") + print(f" [{cid:2d}] T={tc:4d} fidelity={fid:.10f} ({n_rot} rot, {n_cx} cx)") + t1 = time.perf_counter() + + for cid in range(N_CANDIDATES): + res = results.get(cid) + if res is None: + continue + tc, fid, ops, rot_idx, eps_list = res + if best is None: + best = (tc, fid, cid, ops, rot_idx, eps_list) + continue + if tc < best[0] or (tc == best[0] and (fid > best[1] or (fid == best[1] and cid < best[2]))): + best = (tc, fid, cid, ops, rot_idx, eps_list) + + if best is None: + print("ERROR: no candidate met the fidelity target.") + return + + tc, fid, cid, ops, rot_idx, eps_list = best + qc = build_circuit(ops, eps_list) + + qasm3_str = dumps3(qc) + verified_t = count_t_gates_manual(qasm3_str) + + print(f"\n{'=' * 52}") + print(f" FINAL RESULT (candidate {cid})") + print(f"{'=' * 52}") + print(f" T-count (sum): {tc}") + print(f" T-count (QASM): {verified_t}") + print(f" Fidelity |⟨ψ|U|00⟩|²: {fid:.10f}") + print(f" Runtime: {t1 - t0:.3f}s") + print(f" Per-rotation breakdown:") + for j, idx in enumerate(rot_idx): + axis = ops[idx][0] + angle = ops[idx][2] + _, tc_j = synthesize(axis, angle, eps_list[j]) + print(f" rot[{j}] {axis}({angle:+.6f}) q{ops[idx][1]}: eps={eps_list[j]:.1e} T={tc_j}") + + _os.makedirs("qasm", exist_ok=True) + with open("qasm/unitary7.qasm", "w") as f: + f.write(qasm3_str) + print("\n Saved to qasm/unitary7.qasm") + + +if __name__ == "__main__": + main() diff --git a/unitary/unitary8.py b/unitary/unitary8.py new file mode 100644 index 0000000..a57ca81 --- /dev/null +++ b/unitary/unitary8.py @@ -0,0 +1,22 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 + +qc = QuantumCircuit(2) + +qc.h(1) + +qc.t(0) +qc.t(1) +qc.cx(0,1) +qc.tdg(1) +qc.cx(0,1) + +qc.h(0) + +qc.cx(0,1) +qc.cx(1,0) +qc.cx(0,1) + +qasm3_str = dumps3(qc) +with open("qasm/unitary8.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/unitary9.py b/unitary/unitary9.py new file mode 100644 index 0000000..454de64 --- /dev/null +++ b/unitary/unitary9.py @@ -0,0 +1,26 @@ +from qiskit import QuantumCircuit +from qiskit.qasm3 import dumps as dumps3 + +qc = QuantumCircuit(2) + +qc.h(0) + +qc.t(0) +qc.t(1) +qc.cx(1, 0) +qc.tdg(0) +qc.cx(1, 0) + +qc.h(0) + +qc.s(0) +qc.s(1) +qc.t(1) + +qc.cx(0, 1) +qc.cx(1, 0) +qc.cx(0, 1) + +qasm3_str = dumps3(qc) +with open("qasm/unitary9.qasm", 'w') as file: + file.write(qasm3_str) \ No newline at end of file diff --git a/unitary/utils.py b/unitary/utils.py new file mode 100644 index 0000000..d25a027 --- /dev/null +++ b/unitary/utils.py @@ -0,0 +1,83 @@ +from __future__ import annotations +from typing import List + +from qiskit import QuantumCircuit + +import mpmath +from pygridsynth.gridsynth import gridsynth_gates + +def _tokenize(gates: str) -> List[str]: + s = gates.strip().replace(" ", "") + s = "".join(c for c in s.upper() if c in "HTSX") + + while "TTTTTTT" in s: + s = s.replace("TTTTTTT", "t") + + return list(s) + +def _apply_gate(qc: QuantumCircuit, g: str, dagger: bool) -> None: + g_up = g.upper() + if g_up == "H": + qc.h(0) + return + + if g == "t": + qc.tdg(0) if not dagger else qc.t(0) + return + + if g_up == "T": + qc.tdg(0) if dagger else qc.t(0) + return + + if g_up == "S": + qc.sdg(0) if dagger else qc.s(0) + return + + if g_up == "X": + qc.h(0) + qc.s(0); qc.s(0) + qc.h(0) + return + + +def gates_to_qiskit_circuit(gates: str, reverse: bool) -> QuantumCircuit: + toks = _tokenize(gates) + + ordered = toks if reverse else list(reversed(toks)) + dagger = reverse + + qc = QuantumCircuit(1) + for g in ordered: + _apply_gate(qc, g, dagger) + return qc + +def Rz(theta: float, epsilon: float) -> QuantumCircuit: + reverse = theta < 0 + + mpmath.mp.dps = 128 + theta = mpmath.mpf(str(abs(theta))) + epsilon = mpmath.mpf(str(epsilon)) + + gates = gridsynth_gates(theta=theta, epsilon=epsilon) + + return gates_to_qiskit_circuit(gates, reverse) + +def Ry(theta: float, epsilon: float) -> QuantumCircuit: + qc = QuantumCircuit(1) + + qc.sdg(0) + qc.h(0) + qc.append(Rz(theta, epsilon).to_gate(), [0]) + qc.h(0) + qc.s(0) + + return qc + +def Rx(theta: float, epsilon: float) -> QuantumCircuit: + qc = QuantumCircuit(1) + + qc.h(0) + qc.append(Rz(theta, epsilon).to_gate(), [0]) + qc.h(0) + + return qc \ No newline at end of file diff --git a/writeup/main.bib b/writeup/main.bib new file mode 100644 index 0000000..c17c13f --- /dev/null +++ b/writeup/main.bib @@ -0,0 +1,96 @@ +@article{10.5555/3179330.3179331, +author = {Ross, Neil J. and Selinger, Peter}, +title = {Optimal ancilla-free Clifford+T approximation of z-rotations}, +year = {2016}, +issue_date = {September 2016}, +publisher = {Rinton Press, Incorporated}, +address = {Paramus, NJ}, +volume = {16}, +number = {11–12}, +issn = {1533-7146}, +abstract = {We consider the problem of approximating arbitrary single-qubit z-rotations by ancilla-free Clifford+T circuits, up to given epsilon. We present a fast new probabilistic algorithm for solving this problem optimally, i.e., for finding the shortest possible circuit whatsoever for the given problem instance. The algorithm requires a factoring oracle (such as a quantum computer). Even in the absence of a factoring oracle, the algorithm is still near-optimal under a mild number-theoretic hypothesis. In this case, the algorithm finds a solution of T-count m + O(log(log(1/ε))), where m is the T-count of the second-to-optimal solution. In the typical case, this yields circuit approximations of T- count 3 log2(1/ε)+O(log(log(1/ε))). Our algorithm is efficient in practice, and provably efficient under the above-mentioned number-theoretic hypothesis, in the sense that its expected runtime is O(polylog(1/ε)).}, +journal = {Quantum Info. Comput.}, +month = sep, +pages = {901–953}, +numpages = {53}, +keywords = {circuit synthesis, clifford+T, optimal approximation of unitary operators} +} + +@article{PhysRevA.70.052328, + title = {Improved simulation of stabilizer circuits}, + author = {Aaronson, Scott and Gottesman, Daniel}, + journal = {Phys. Rev. A}, + volume = {70}, + issue = {5}, + pages = {052328}, + numpages = {14}, + year = {2004}, + month = {Nov}, + publisher = {American Physical Society}, + doi = {10.1103/PhysRevA.70.052328}, + url = {https://link.aps.org/doi/10.1103/PhysRevA.70.052328} +} + +@article{PhysRevA.57.127, + title = {Theory of fault-tolerant quantum computation}, + author = {Gottesman, Daniel}, + journal = {Phys. Rev. A}, + volume = {57}, + issue = {1}, + pages = {127--137}, + numpages = {0}, + year = {1998}, + month = {Jan}, + publisher = {American Physical Society}, + doi = {10.1103/PhysRevA.57.127}, + url = {https://link.aps.org/doi/10.1103/PhysRevA.57.127} +} + +@article{PhysRevA.105.052602, + title = {Universality verification for a set of quantum gates}, + author = {Sawicki, Adam and Mattioli, Lorenzo and Zimbor\'as, Zolt\'an}, + journal = {Phys. Rev. A}, + volume = {105}, + issue = {5}, + pages = {052602}, + numpages = {6}, + year = {2022}, + month = {May}, + publisher = {American Physical Society}, + doi = {10.1103/PhysRevA.105.052602}, + url = {https://link.aps.org/doi/10.1103/PhysRevA.105.052602} +} + +@article{RossSelinger2014OptimalAncillaFree, + author = {Ross, Neil J. and Selinger, Peter}, + title = {Optimal ancilla-free Clifford+T approximation of {$Z$}-rotations}, + year = {2014}, + eprint = {1403.2975}, + archivePrefix = {arXiv}, + primaryClass = {quant-ph}, + doi = {10.48550/arXiv.1403.2975}, + url = {https://arxiv.org/abs/1403.2975} +} + +@software{superquantum_rmsynth_2026, + author = {{Superquantum}}, + title = {rmsynth: High-performance Clifford+T circuit optimizer using phase-polynomial methods and punctured Reed--Muller decoding}, + year = {2026}, + url = {https://github.com/super-quantum/rmsynth%7D}, + license = {Apache-2.0}, + note = {GitHub repository} +} + +@article{Zhang2021QuantumGS, + author = {Zhang, Kaining and Hsieh, Min-Hsiu and Liu, Liu and Tao, Dacheng}, + title = {Quantum Gram-Schmidt Processes and Their Application to Efficient State Read-out for Quantum Algorithms}, + journal = {Physical Review Research}, + volume = {3}, + pages = {043095}, + year = {2021}, + doi = {10.1103/PhysRevResearch.3.043095}, + eprint = {https://arxiv.org/abs/2004.06421}, + archivePrefix = {arXiv}, + primaryClass = {quant-ph} +} + diff --git a/writeup/main.log b/writeup/main.log new file mode 100644 index 0000000..e69de29 diff --git a/writeup/main.pdf b/writeup/main.pdf new file mode 100644 index 0000000..2d3d404 Binary files /dev/null and b/writeup/main.pdf differ diff --git a/writeup/main.tex b/writeup/main.tex new file mode 100644 index 0000000..6fd1196 --- /dev/null +++ b/writeup/main.tex @@ -0,0 +1,323 @@ +\documentclass[twocolumn, letterpaper]{article} +\usepackage{authblk} +\usepackage{amsmath} +\usepackage{cite} +\usepackage{graphicx} +\graphicspath{ {../plots/} } +\usepackage{tikz} +\usetikzlibrary{quantikz2} +\newtheorem{theorem}{Theorem} + +\title{iQuHack 2026 (Superquantum Challenge): \\ Leveraging Modularity for Twelve Unitary Circuit Decompositions} +\author[1]{Adam Godel} +\author[1]{Yebin Song} +\author[1]{Nico Jackson} +\author[1]{Travis Meyer} +\author[1]{Timothy Wright} +\affil[1]{Boston University, Boston, Massachusetts 02215, USA} + +\begin{document} + +\maketitle +\setcounter{page}{1} +\begin{abstract} + We consider the Clifford + $T$ gate decomposition of twelve unitary gate operators, implementing modular gate implementations based on known near-optimal decompositions of the $R_z(\theta)$ gate with some precision $\epsilon$. We also examine the phase polynomial's ability to lead to reductions in the $T$ gate count based on coefficient parity or raw value depending on the gate restrictions. + \end{abstract} + +\section{Introduction} +The development and optimization of fault-tolerant quantum circuits has been at the forefront of quantum research in recent years. This weekend at iQuHack, Superquantum tasked us with implementing efficient approximate quantum circuit implementations of unitary gate operators using the Clifford + $T$ gate set, where the latter is by far the most computationally difficult gate to execute and functions as a description of the ``quantumness'' of a circuit.\footnotemark + +\footnotetext{Our code is available on GitHub at the following link: \texttt{https://github.com/adam-godel/2026-Superquantum}.} + +Our approach to implement these unitaries varied widely depending on the operator. Some have symmetries that can be exploited, while others are completely random and require brute-force optimization. Furthermore, there is a subjective tradeoff between minimizing the number of $T$ gates and minimizing the distance between the approximate and the exact unitaries. In this writeup, we present our approaches to implement all twelve operators tasked in our challenge, considering how our implementations can be varied in both of these optimization regimes. + +We will begin by establishing some background on quantum computing and circuit theory, then continue by discussing each of our implementations in detail, including our experimental results, and conclude with our reflection and possible future work on these problems. + +\section{Background} +A \emph{two-qubit quantum state} is represented as +\begin{equation} + |\psi\rangle = \alpha|00\rangle + \beta|01\rangle + \gamma |10\rangle + \delta|11\rangle, +\end{equation} +where $|\alpha|^2+|\beta|^2+|\gamma|^2+|\delta|^2=1$. A quantum state can be acted upon with \emph{quantum gates}, which are represented as unitary matrices $A \in U(2^n)$ for $n$ qubits such that $|\psi\rangle \mapsto A|\psi\rangle$, which is a valid $n$-qubit quantum state. + +The following quantum gates are known as the \emph{Clifford gates}~\cite{PhysRevA.57.127}: +\begin{align} + H = \frac{1}{\sqrt{2}}\begin{bmatrix} + 1 & 1 \\ + 1 & -1 + \end{bmatrix} \: + S = \begin{bmatrix} + 1 & 0 \\ + 0 & i + \end{bmatrix} \: + CX &= \begin{bmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & 1 \\ + 0 & 0 & 1 & 0 + \end{bmatrix} + \end{align} +When combined with the $T$ gate, defined as +\begin{equation} + T = \begin{bmatrix} + 1 & 0 \\ + 0 & e^{i\frac{\pi}{4}} + \end{bmatrix}, +\end{equation} +they form a \emph{universal gate set}~\cite{PhysRevA.105.052602}, meaning that any unitary operation can be approximated to arbitrary precision using circuits built with just these four gates. + +Moreover, the \emph{Gottesman-Knill theorem}~\cite{PhysRevA.70.052328} shows that the Clifford gates can be simulated in polynomial time on a classical computer. This reduces the ``hardness'' of a quantum circuit to be described in the number of $T$ gates it contains. + +\section{Our Implementations} +We now go through each of the twelve unitaries we implemented during the weekend, and the optimizations we made to leverage both low $T$ gate counts and higher accuracy. We describe the implementations in order, although the difficulty in constructing each implementation varied widely. Note that none of our circuit decompositions use any ancilla qubits. + +\subsection{Controlled-$Y$ Gate} +The \emph{controlled-$Y$ gate} is defined as +\begin{equation} + CY = \begin{bmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & 0 & -i \\ + 0 & 0 & i & 0 + \end{bmatrix}. +\end{equation} +To implement this gate, we consider that $(I \otimes S) CX (I \otimes S^\dagger)=CY$, where the $\dagger$ operator denotes the conjugate transpose. Since we can implement this gate using only Clifford gates, there is no tradeoff---we get high accuracy and no $T$ gate cost. + +\subsection{Controlled-$R_y(\pi/7)$ Gate} +The \emph{controlled-$R_y$ gate} is defined as +\begin{equation} + CR_y(\theta) = \begin{bmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & \cos(\theta/2) & -\sin(\theta/2) \\ + 0 & 0 & \sin(\theta/2) & \cos(\theta/2) + \end{bmatrix}. +\end{equation} +We want to consider the case where $\theta=\pi/7$, which does not map cleanly onto a Clifford + $T$ gate set. Therefore, we have to consider approximations. This is when we developed our central strategy for creating these implementations: \emph{\textbf{modularity}} of gates. + +Suppose we had a $R_y$ gate in our toolbox. If this were the case, we could represent $CR_y(\theta)$ with the following circuit: +\begin{equation} + \begin{quantikz} + \lstick{$q_0$} &&\ctrl{1}&&\ctrl{1}& \\ + \lstick{$q_1$} &\gate{R_y(\theta/2)}&\targ{}&\gate{R_y(-\theta/2)}&\targ{}& + \end{quantikz} +\end{equation} +We know that this is true by considering the state of $q_1$ based on the state of $q_0$. We know that $CR_y(\theta)$ should apply $R_y(\theta)$ if $q_0=|1\rangle$ and do nothing if $q_0=|0\rangle$. In Eq. 7, we can see that if $q_0=|0\rangle$, nothing is done to $q_1$, while if $q_0=|1\rangle$, we can see that a $R_y(\theta)$ gate is applied to $q_1$. + +The problem now reduces to an implementation of $R_y(\theta)$. We can observe that since $SXS^\dagger=Y$ and $HZH=X$, we have $R_y(\theta)=SHR_z(\theta)HS^\dagger$, i.e. we can represent $R_y(\theta)$ in terms of just $R_z(\theta)$ and Clifford gates. It is easy to see that the same is true for $R_x(\theta)$. + +We implement a Clifford + $T$ gate approximation of $R_z(\theta)$ using the \texttt{gridsynth} package~\cite{10.5555/3179330.3179331}, which takes in an angle $\theta$ and a precision $\epsilon$ and computes a decomposition for $R_z(\theta)$ with a $T$-gate count within $O(\log(\log(1/\epsilon)))$ of optimal. + +This allows us to modularly use the $R_x$, $R_y$, and $R_z$ gates, noting that they are the most expensive operation, so we should aim to minimize their usage. + +\subsection{Exponential of a Pauli String} +We next tackle the implementation of $\exp(i\frac{\pi}{7} ZZ)$. We can observe that +\begin{equation} +\exp(i\theta ZZ) = CX (I \otimes \exp(i\theta Z)) CX. +\end{equation} +Consider the $R_z$ gate, which is defined as +\begin{equation} + R_z(\theta) = \begin{bmatrix} + e^{-i\frac{\theta}{2}} & 0 \\ + 0 & e^{i\frac{\theta}{2}} + \end{bmatrix}. +\end{equation} +It is not hard to see that $\exp(i\theta Z)=R_z(-2\theta)$. Therefore, we can implement this unitary similarly to the previous one but using only one $R_z$ gate. + +\subsection{Exponential of a Hamiltonian} +Consider the unitary operator $\exp(i\frac{\pi}{7}H_1)$, where $H_1=XX+YY$. We implement each summand separately in a construction is similar to above. We implement $\exp(i \frac{\pi}{7} XX)$ by taking the previous circuit and conjugating with $H$, and we implement $\exp(i \frac{\pi}{7} YY)$ by conjugating with $HS$ and $S^\dagger H$ on both qubits. This allows us to implement the exponential of this Hamiltonian using only two $R_z$ gates. + +\subsection{A Curiously Simple Hamiltonian} +Suppose we consider a similar Hamiltonian to the one above, but with a slightly different construction. We consider $\exp(i\frac{\pi}{4}H_2)$, where $H_2=XX+YY+ZZ$. Can we implement this operator more efficiently than the previous ones? + +It turns out that we can, using the SWAP gate, which is defined as +\begin{equation} + \text{SWAP} = \frac{1}{2}(II+XX+YY+ZZ). +\end{equation} +Using the SWAP gate, we can rewrite our exponential as +\begin{equation} +\begin{aligned} + \exp\left(i\frac{\pi}{4}H_2\right) &= \exp\left(i\frac{\pi}{4}(2\text{SWAP}-I)\right) \\ + &= e^{-i\frac{\pi}{4}}\exp\left(i\frac{\pi}{2}\text{SWAP}\right) \\ + &= e^{i\frac{\pi}{4}}\text{SWAP} +\end{aligned} +\end{equation} +where the coefficient is a global phase that we can discard. Therefore, the Hamiltonian exponential is equivalent to the SWAP gate, which we can easily write using three CNOTs by the XOR swap algorithm: +\begin{equation} + \begin{quantikz} + \lstick{$q_0$} &\ctrl{1}&\targ{}&\ctrl{1}& \\ + \lstick{$q_1$} &\targ{}&\ctrl{-1}&\targ{}& + \end{quantikz} +\end{equation} +This form makes the Hamiltonian trivial to simulate. + +\subsection{Two-Qubit Transverse Field Ising Model} +We construct this exponential operator, defined as $\exp(i\frac{\pi}{7}H_3)$, where $H_3=XX+ZI+IZ$. We construct the $XX$ term in the same way as described in Sec. 3.4. For the other two terms, we simply apply $R_z(-2\theta)$ to each qubit. + +\subsection{State Preparation} +We now discuss the implementation of an arbitrary state preparation +\begin{equation} +\begin{aligned} + |00\rangle \mapsto (0.1061479384-0.679641467i)&|00\rangle \\ + + (-0.3622775887-0.453613136i)&|01\rangle \\ + + (0.2614190429+0.0445330969i)&|10\rangle \\ + + (0.3276449279-0.1101628411i)&|11\rangle. +\end{aligned} +\end{equation} +This task differs from the previous ones since it is totally random. There is no structure we can exploit to systematically minimize the number of $T$ gates we're using. + +Consider how this unitary operator might look. For a unitary operator $U$ where +\begin{equation} + U|00\rangle = \alpha|00\rangle + \beta|01\rangle + \gamma|10\rangle + \delta|11\rangle, +\end{equation} +its structure in the computational basis would be reminiscent of the following: +\begin{equation} + U = \begin{bmatrix} +0.1061479384-0.679641467i & * & * & * \\ +-0.3622775887-0.453613136i & * & * & * \\ +0.2614190429+0.0445330969i & * & * & * \\ +0.3276449279-0.1101628411i & * & * & * +\end{bmatrix} +\end{equation} +where the $*$ symbols depict ``free variables'' that we don't care about the specific values of. The key observation is that for this matrix to be unitary, these columns must form an orthonormal basis, and the specific values of these free variables will greatly affect the number of $T$ gates. + +Therefore, our protocol is the following: we first generate a complete unitary using the Gram-Schmidt process, encoding randomness on many different diagonal matrices that are applied to each sample unitary~\cite{Zhang2021QuantumGS}. We then test each candidate unitary over many different values of $\epsilon$. To balance the tradeoff, we start with a fidelity threshold compared to the expected state, and once that is hit, we then test over $\epsilon$ to minimize the number of $T$ gates. + +More precisely, we transpile the circuit into rotation gates using \texttt{qiskit}, and then decompose each one with a different most optimized $\epsilon$ value by comparing individually to the fidelity of the state with that operator applied as well as its individual $T$ gate count. + +This approach allows us to get a highly optimized circuit without incorporating any sort of structural symmetry; our approach works on fully random state preparation instances. + +\subsection{A Structured Unitary} +We aim to apply the unitary +\begin{equation} + U_1 = \frac{1}{2}\begin{bmatrix} + 1 & 1 & 1 & 1 \\ + 1 & i & -1 & -i \\ + 1 & -1 & 1 & -1 \\ + 1 & -i & -1 & i + \end{bmatrix}. +\end{equation} +Notice that this unitary is the two-qubit quantum Fourier transform~\cite{RossSelinger2014OptimalAncillaFree}. Since it only requires $z$ rotations that are multiples of $\frac{\pi}{4}$, we do not need any rotation gates. Our implementation uses only three $T$ gates. + +\subsection{Another Structured Unitary} +We aim to apply the unitary +\begin{equation} + U_2 = \begin{bmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 0 & -\frac{1}{2}+\frac{i}{2} & \frac{1}{2}+\frac{i}{2} \\ + 0 & i & 0 & 0 \\ + 0 & 0 & -\frac{1}{2}+\frac{i}{2} & -\frac{1}{2}-\frac{i}{2} + \end{bmatrix}. +\end{equation} +We can observe that this unitary, without a SWAP gate applied to it, is reminiscent of a controlled operation. Specifically, we can identify it as the controlled-$R_x\left(\frac{\pi}{4}\right)$ gate with some local phase changes, specifically $S \otimes TS$ gates before the SWAP. Since $\theta=\frac{\pi}{4}$, we can apply this directly as a $T$ gate. Ultimately, our implementation uses four $T$ gates in total. + +\subsection{Random Unitary} +In the case of a random unitary operator, we can just use the exact same protocol as in Sec. 3.7 but without the generation of the unitary, since we are already restricted to what the unitary needs to be. Similarly to the state preparation problem, this approach gives us an efficient circuit without exploiting any structure relating to the unitary. + +\subsection{Four-Qubit Diagonal Unitary} +We want to implement the four-qubit unitary $U$ such that $U|x\rangle = e^{i\frac{\pi}{8}\varphi(x)}|x\rangle$, where $\varphi(x)$ is some four-bit boolean function mod 8 known as the \emph{phase polynomial}. + +The key observation is that the phase polynomial fully encodes the unitary, and the number of odd coefficients will correspond with the number of $T$ gates. We first came up with some implementation for $\varphi(x)$, regardless of its optimality, and implemented it as a circuit. + +We then used the \texttt{rmsynth} package~\cite{superquantum_rmsynth_2026} to optimize the phase polynomial, aiming to minimize both the number of $T$ gates and the $T$ gate depth. Specifically, we just used the documentation defaults: a decoder of \texttt{rpa}, an effort level of \texttt{3}, and a policy lambda of \texttt{5}. + +From there, we get a dictionary representing the optimized phase polynomial, which we just implement as a quantum circuit as we have for the others. + +This gives us a $T$ gate count of 4 with nearly perfect accuracy. + +\subsection{$n$-Qubit Pauli List} +We also implemented the bonus unitary, which is defined as +\begin{equation} + U = \prod_{j=1}^m \exp\left( -i\frac{\pi}{8} k_jP_j \right) +\end{equation} +for Pauli strings $P_j$ with coefficients $k_j$. Since all $P_j$ commute pairwise, we can perform exact diagonalization using Clifford gates to get each Pauli gate for each qubit in the right basis. + +We end up with the non-Clifford operator being in the form $e^{i\frac{\pi}{8}\varphi(x)}$, just like our construction in Sec. 3.11. From there, we take the same approach, but excluding $S$ gates since they are prohibited according to the rules of the challenge. + +Given that constraint, we want to optimize for the lowest absolute coefficients as opposed to the lowest number of odd coefficients. We were able to get a $T$ gate count of 287; due to time constraints, we weren't really able to optimize this unitary construction in the same way we did for the others. + +\section{Simulations} +Given the intrinsic tradeoff between $T$-gate count and approximation accuracy, our research investigated different optimization regimes for various target operators. For unitaries $2, 3, 4, 6, 7,$ and $10$, we utilized a modular strategy where the circuit's total $T$-count was primarily determined by the precision ($\epsilon$) of our $R_z(\theta)$ gate decompositions. +\subsection{Unitary 2} +\begin{figure}[htbp] + \centering + \includegraphics[width=0.48\textwidth]{unitary_2_distance_vs_tcount.png} + \caption{$T$-count vs. distance tradeoff for Unitary 2.} + \label{fig:unitary2} +\end{figure} +Figure 1 depicts varying $\epsilon$ values for Unitary 2. The plot for Unitary 2 exhibits a non-monotonic ``spike'' in error, where the distance reaches a maximum of $4.56 \times 10^{-1}$ at mid-range $T$-counts due to local optimization failures. As the gate budget increases to 200, the approximation stabilizes at a persistent plateau of $4.46 \times 10^{-1}$, indicating that further $T$-gates do not significantly improve fidelity for this specific rotation. + +\subsection{Unitary 3} +\begin{figure}[htbp] + \centering + \includegraphics[width=0.48\textwidth]{unitary_3_distance_vs_tcount.png} + \caption{$T$-count vs. distance tradeoff for Unitary 3.} + \label{fig:unitary3} +\end{figure} +Figure 2 depicts varying $\epsilon$ values for Unitary 3. Unitary 3 demonstrates a successful exponential decrease in error, with the distance dropping from $7.62 \times 10^{-2}$ down to a high-precision value of $1.38 \times 10^{-10}$. The profile features a distinct ``breakthrough'' near a $T$-count of 98, where the algorithm identifies an optimal Clifford + $T$ sequence that dramatically reduces the residual error. + +\subsection{Unitary 4} +\begin{figure}[htbp] + \centering + \includegraphics[width=0.48\textwidth]{unitary_4_distance_vs_tcount.png} + \caption{$T$-count vs. distance tradeoff for Unitary 4.} + \label{fig:unitary4} +\end{figure} +Figure 3 depicts varying $\epsilon$ values for Unitary 4. This operator follows a steady downward trend punctuated by a significant error plateau between $T$-counts of 100 and 180. Upon reaching a budget of 196 gates, the distance collapses from roughly $10^{-5}$ to $1.96 \times 10^{-10}$, proving that higher $T$-gate thresholds are sometimes necessary to unlock high-precision approximations. + +\subsection{Unitary 6} +\begin{figure}[htbp] + \centering + \includegraphics[width=0.48\textwidth]{unitary_6_distance_vs_tcount.png} + \caption{$T$-count vs. distance tradeoff for Unitary 6.} + \label{fig:unitary6} +\end{figure} +\begin{table}[h!] +\centering +\begin{tabular}{c c c} +\hline +\textbf{Variant} & \textbf{$T$-count} & \textbf{Distance} \\ +\hline +YYY & 294 & 0.5090 \\ +YYN & 196 & 0.8959 \\ +YNY & 196 & 0.8959 \\ +YNN & 98 & 1.132 \\ +NYY & 196 & 0.9714 \\ +NYN & 98 & 1.252 \\ +NNY & 98 & 1.252 \\ +NNN & 0 & 1.446 \\ +\hline +\end{tabular} +\caption{Comparison of $T$-count and normalized distance for different Clifford variants. A ``Y'' marker indicates that a rotation gate is used, while an ``N'' marker indicates that a Clifford approximation is used ($S^\dagger$ gates in this case).} +\label{tab:clifford_variants} +\end{table} +Figure 4 depicts varying $\epsilon$ values for Unitary 6. Unitary 6 shows a rapid initial error reduction that quickly hits a hard ceiling, with the distance settling at $6.97 \times 10^{-1}$ despite increasing the $T$-count to nearly 300. This behavior suggests a structural mismatch where the specific target unitary remains mathematically distant from the gate sequences reachable within the current search depth. + +As an example, we decided to also investigate using pure Clifford gate approximations for Unitary 6. Table 1 shows the results, where an ``N`` marker indicates that an $S^\dagger$ gate was used instead of an $R_z\left(-\frac{2\pi}{7}\right)$ gate. The results indicate that including all of the rotation gates gives the lowest distance at the expense of having the highest $T$-count, while as we use more Clifford approximations, the accuracy decreases as the $T$-count decreases, which is what we expect. + +\subsection{Unitary 7} +\begin{figure}[htbp] + \centering + \includegraphics[width=0.48\textwidth]{unitary7_plot.png} + \caption{$T$-count vs. distance tradeoff for Unitary 7.} + \label{fig:unitary7} +\end{figure} +Figure 5 depicts varying $\epsilon$ values for Unitary 7. For Unitary 7, the analysis shifted from distance to Fidelity, targeting an extremely narrow high-precision band between 0.9999990 and 1.0. The plot reveals a stochastic, oscillatory pattern between $T$-counts of 490 and 592, characteristic of the randomized search protocol used to satisfy the strict $\geq$ 0.999999 fidelity threshold. This high resource cost and non-linear behavior are typical for ``totally random'' state preparations that lack exploitable structural symmetries. +\subsection{Unitary 10} +\begin{figure}[htbp] + \centering + \includegraphics[width=0.48\textwidth]{unitary10_distance_vs_tcount.png} + \caption{$T$-count vs. distance tradeoff for Unitary 10.} + \label{fig:unitary10} +\end{figure} +Figure 6 depicts varying $epsilon$ values for Unitary 10. This unitary requires a much larger resource budget, scaling from 250 to over 700 gates to achieve a precision of $1.0 \times 10^{-3}$. The log-log linear trend, despite a minor local instability at 350 gates, confirms that this ``random'' operator demands high gate density to achieve even moderate fidelity compared to more structured gates. + +\section{Reflection \& Conclusions} +In this project, we showed that while some unitaries can be easily decomposed into all Clifford gates, the ones that can't have a tradeoff between $T$ gate counts and accuracy. There is no objectively best configuration---ultimately, it depends on your use case and the ability of your hardware to simulate $T$ gates. + +For the later unitaries, we also identified the power of the phase polynomial to map many different classes of unitaries into Clifford and $R_z$ gates, providing the modularity that really made our implementations possible and efficient. + +We really enjoyed this project as a whole, and we are interested to explore the power of Clifford + $T$ decomposition as well as the \texttt{rmsynth} package and this problem's connection to the Reed-Muller code further. We definitely think there is still room for improvement in our implementations, particularly Unitary 12, and are excited to continue exploring better and even more modular approaches past the hackathon deadline! +\bibliographystyle{unsrt} +\bibliography{main} +\end{document} \ No newline at end of file