├── .flake8 ├── .gitignore ├── .readthedocs.yml ├── LICENSE ├── MANIFEST.in ├── README.md ├── arline_benchmarks ├── __init__.py ├── config_parser │ ├── __init__.py │ └── pipeline_config_parser.py ├── engines │ ├── __init__.py │ └── pipeline_engine.py ├── metrics │ ├── __init__.py │ └── gate_chain_analyser.py ├── pipeline │ ├── __init__.py │ └── pipeline.py ├── reports │ ├── __init__.py │ ├── kak_scheme.png │ ├── latex_report.py │ ├── plot_benchmarks.py │ └── results_logger.py ├── strategies │ ├── __init__.py │ ├── arline_rebase.py │ ├── cirq_3q_decomposition.py │ ├── cirq_drop_empty_moments.py │ ├── cirq_drop_negligible.py │ ├── cirq_eject_phased_paulis.py │ ├── cirq_eject_z.py │ ├── cirq_mapping.py │ ├── cirq_mapping_compression.py │ ├── cirq_merge_1q.py │ ├── cirq_merge_interactions.py │ ├── cirq_optimize_for_xmon.py │ ├── post_processing.py │ ├── pre_processing.py │ ├── pytket_chem_pass.py │ ├── pytket_commute_multis.py │ ├── pytket_cx_directed.py │ ├── pytket_default_mapping.py │ ├── pytket_mapping.py │ ├── pytket_mapping_compression.py │ ├── pytket_pauli_simp.py │ ├── pytket_peephole.py │ ├── pytket_postrouting.py │ ├── pytket_rebase.py │ ├── pytket_remove_redundancies.py │ ├── pytket_synthesise_ibm.py │ ├── pyzx_clifford_simp.py │ ├── pyzx_full_optimize.py │ ├── pyzx_full_reduce.py │ ├── qiskit_commutative_cancellation.py │ ├── qiskit_kak_blocks.py │ ├── qiskit_rebase.py │ ├── qiskit_transpile.py │ ├── qiskit_unroll.py │ ├── strategy.py │ ├── target_analysis.py │ ├── voqc_1q_gates_cancel.py │ ├── voqc_2q_gates_cancel.py │ ├── voqc_hadamard_reduction.py │ ├── voqc_merge_rotations.py │ └── voqc_not_propagation.py └── targets │ ├── __init__.py │ └── target.py ├── circuits ├── C17_204.qasm ├── mini-alu_167.qasm ├── one-two-three-v0_97.qasm ├── rd53_135.qasm └── sym9_146.qasm ├── configs ├── compression │ ├── config.jsonnet │ ├── pipelines.jsonnet │ └── run_and_plot.sh └── reports │ ├── latex.jsonnet │ └── plotter.jsonnet ├── docs ├── Makefile ├── _static │ ├── arline_benchmarks_logo.png │ └── arline_favicon.ico ├── arline_benchmarks.rst ├── circuits.rst ├── conf.py ├── config_parser.rst ├── configs.rst ├── engine.rst ├── index.rst ├── make.bat ├── metrics.rst ├── pipeline.rst ├── reports.rst ├── requirements.txt ├── strategies.rst └── targets.rst ├── pyproject.toml ├── scripts ├── arline-benchmarks-latex-report-generator ├── arline-benchmarks-plotter └── arline-benchmarks-runner ├── setup.py ├── tests ├── __init__.py ├── qasm_files │ └── general │ │ ├── 2q.qasm │ │ ├── 5q.qasm │ │ └── small_angle.qasm └── targets │ ├── __init__.py │ └── test_target.py └── tox.ini /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | 3 | max-line-length = 120 4 | ignore = E203 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # Vim temporary files 7 | *.swp 8 | *.swo 9 | 10 | # MacBook Files 11 | *.DS_Store 12 | 13 | # Jupyter backups 14 | .ipynb_checkpoints 15 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | 4 | # Required 5 | version: 2 6 | 7 | # Build documentation in the docs/ directory with Sphinx 8 | sphinx: 9 | configuration: docs/conf.py 10 | 11 | # Build documentation with MkDocs 12 | #mkdocs: 13 | # configuration: mkdocs.yml 14 | 15 | # Optionally build your docs in additional formats such as PDF 16 | #formats: 17 | # - pdf 18 | 19 | # Optionally set the version of Python and requirements required to build your docs 20 | python: 21 | version: 3.7 22 | install: 23 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE.txt 2 | include arline_benchmarks/reports/*.png 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | 3 | **Arline Benchmarks** platform allows to benchmark various algorithms for quantum circuit mapping/compression against 4 | each other on a list of predefined hardware types and target circuit classes. 5 | 6 | Arline Benchmarks has been recently used by Oxford Quantum Circuits team for compiler performance testing (see [blog post](https://oxfordquantumcircuits.com/oqc-integrates-tket)). 7 | 8 | ## Demo (report generation preview) 9 | 10 | ### Benchmarking run 11 | ![Benchmarking run](https://media.giphy.com/media/UTYhq49IghgFZAupQD/source.gif) 12 | 13 | ### LaTeX report 14 | ![Report](https://media.giphy.com/media/ejJgh5eHfHXqi57DB4/source.gif) 15 | 16 | ## List of supported compilation frameworks 17 | 18 | * [Google Cirq](https://github.com/quantumlib/Cirq) 19 | * [IBM Qiskit](https://github.com/Qiskit) 20 | * [CQC Tket](https://github.com/CQCL/tket) 21 | * [PyZX](https://github.com/Quantomatic/pyzx) 22 | * [VOQC](https://github.com/inQWIRE/pyvoqc) 23 | 24 | ## Installation 25 | 26 | ```console 27 | $ pip3 install arline-benchmarks 28 | ``` 29 | 30 | Alternatively, Arline Benchmarks can be installed locally in the editable mode. 31 | Clone Arline Benchmarks repository, `cd` to the source directory: 32 | 33 | Clone repository, `cd` to the source directory: 34 | ```console 35 | $ git clone https://github.com/ArlineQ/arline_benchmarks.git 36 | $ cd arline_benchmarks 37 | ``` 38 | 39 | We recommend to install Arline Benchmarks in [virtual environment](https://virtualenv.pypa.io/en/latest/). 40 | 41 | ```console 42 | $ virtualenv venv 43 | $ source venv/bin/activate 44 | ``` 45 | 46 | If `virtualenv` is not installed on your machine, run 47 | 48 | ```console 49 | $ pip3 install virtualenv 50 | ``` 51 | 52 | Next in order to install the Arline Benchmarks platform execute: 53 | 54 | ```console 55 | $ pip3 install . 56 | ``` 57 | 58 | Alternatively, Arline Benchmarks can be installed in the editable mode: 59 | 60 | ```console 61 | $ pip3 install -e . 62 | ``` 63 | 64 | ### VOQC installation 65 | 66 | To install Python wrapper for VOQC package follow [these instructions](https://github.com/inQWIRE/pyvoqc). 67 | 68 | ### Setting Environment Variables 69 | 70 | Add to your `~/.profile`: 71 | ```bash 72 | export ARLINE_BENCHMARKS= 73 | ``` 74 | 75 | ### TeXLive installation 76 | 77 | Automated generation of LaTeX report is an essential part of Arline Benchmarks. 78 | In order to enable full functionality of Arline Benchmarks, you will need to install TeXLive distribution. 79 | 80 | #### Ubuntu or Debian Linux: 81 | 82 | To install TeXLive simply run in terminal: 83 | 84 | ```console 85 | $ sudo apt install texlive-latex-extra 86 | ``` 87 | 88 | #### Windows: 89 | 90 | On Windows, TeXLive can be installed by downloading source code from [official website](https://www.tug.org/texlive/) 91 | and following installation instructions. 92 | 93 | 94 | #### MacOS: 95 | 96 | On MacOS simply install MacTex distribution from the [official website](https://www.tug.org/mactex/). 97 | 98 | #### Alternative solution for Linux/Windows/MacOS: 99 | 100 | TeXLive can be also installed as a part of the MikTex package by downloading and installing source code from 101 | https://miktex.org. TeXworks frontend is not required and can be ignored. 102 | 103 | 104 | 105 | ## Getting started 106 | 107 | ### Benchmark example run 108 | 109 | In order to run your first benchmarking experiment execute following commands 110 | ```console 111 | $ cd arline_benchmarks/configs/compression/ 112 | $ bash run_and_plot.sh 113 | ``` 114 | 115 | Bash script `run_and_plot.sh` executes 116 | 117 | 1. `scripts/arline-benchmarks-runner` - runs benchmarking experiment and saves result to `results/output 118 | /gate_chain_report.csv` 119 | 2. `arline_benhmarks/reports/plot_benchmarks.py` - generates plots with metrics based on `results/output 120 | /gate_chain_report.csv` to `results/output/figure` 121 | 3. `scripts/arline-latex-report-generator` - generates `results/latex/benchmark_report.tex` and 122 | `results/latex/benchmark_report.pdf` report files with benchmarking results. 123 | 124 | Configuration file `configs/compression/config.jsonnet` contains full description of benchmarking experiments. 125 | 126 | 127 | ### Generate plots with benchmark metrics 128 | 129 | To re-draw plots execute (from `arline_benchmarks/configs/compression/`) 130 | ```console 131 | $ bash plot.sh 132 | ``` 133 | 134 | ### Generate LaTeX report 135 | 136 | To re-generate LaTeX report based on the last benchmarking run (from `arline_benchmarks/configs/compression/`) 137 | 138 | ``` console 139 | $ arline-latex-report-generator -i results -o results 140 | ``` 141 | 142 | ### How to create a custom compilation pipeline? 143 | 144 | 145 | The key element of Arline Benchmarks is the concept of **compilation pipeline**. 146 | A pipeline is a sequence of compilation `stages: [stage1, stage2, stage3, ..]`. 147 | 148 | A typical pipeline consists of the following stages: 149 | 150 | * Generation of a target circuit 151 | * Mapping of logical qubits to physical qubits 152 | * Qubit routing for a particular hardware coupling topology 153 | * Circuit compression by applying circuit identities 154 | * Rebase to the final hardware gate set 155 | 156 | You can easily create a custom compilation pipeline by stacking individual stages (that might correspond to different 157 | compiler providers). A pipeline can consist of an unlimited number of compilation stages combined in an arbitrary order. 158 | The only exceptions are the first stage `target_analysis` and the last `gateset rebase stage` (optional). 159 | 160 | 161 | ### Configuration file .jsonnet 162 | 163 | Pipelines should be specified in the main configuration file .jsonnet. 164 | An example of a configuration file is located in `configs/compression/config.jsonnet`. 165 | 166 | * Function `local pipelines_set(target, hardware, plot_group)` defines a list of compilation pipelines to be benchmarked, `[pipeline1, pipeline2, ...]`. 167 | 168 | Each `pipeline_i = {...}` is represented as a dictionary that contains a description of the pipeline and a list of 169 | compilation stages. 170 | 171 | * Target circuits generation is defined in .jsonnet functions `local random_chain_cliford_t_target(...)` and `local random_chain_cx_u3_target(...)`. 172 | 173 | * Benchmarking experiment specifications are defined at the end of the config file in the dictionary with keys `{pipelines: ..., plotter: ...}` 174 | 175 | ## API documentation 176 | 177 | API documentation is here [documentation](https://arline-benchmarks.readthedocs.io/en/latest/). 178 | To generate HTML API documentation, run below command: 179 | 180 | ```console 181 | $ cd docs/ 182 | $ make html 183 | ``` 184 | 185 | ## Running tests 186 | 187 | To run unit-tests and check installed dependencies: 188 | 189 | ```console 190 | $ tox 191 | ``` 192 | 193 | ## Folder structure 194 | 195 | ``` 196 | arline_benchmarks 197 | │ 198 | ├── arline_benchmarks # platform classes 199 | │ ├── config_parser # parser of pipeline configuration 200 | │ ├── engine # pipeline engine 201 | │ ├── metrics # metrics for pipeline comparison 202 | | ├── pipeline # pipeline 203 | │ ├── reports # LaTeX report generator 204 | │ ├── strategies # list of strategies for mapping/compression/rebase 205 | │ └── targets # target generator 206 | │ 207 | ├── circuits # qasm circuits dataset 208 | │ 209 | ├── configs # configuration files 210 | │ └── compression # config .jsonnet file and .sh scripts 211 | │ 212 | ├── docs # documentation 213 | │ 214 | ├── scripts # run files 215 | │ 216 | └── test # tests 217 | ├── qasm_files # .qasm files for test 218 | └── targets # test for targets module 219 | ``` 220 | 221 | ## Contributors 222 | 223 | **Arline team**: Yaroslav Kharkov, Eugeny Mikhantyev, Alina Ivanova, Alex Kotelnikov 224 | -------------------------------------------------------------------------------- /arline_benchmarks/__init__.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /arline_benchmarks/config_parser/__init__.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /arline_benchmarks/config_parser/pipeline_config_parser.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import json 19 | import _jsonnet 20 | 21 | 22 | class PipelineConfigParser(dict): 23 | """Loads experiment configuration from disk (.jsonnet config file) 24 | 25 | :param setup_config_path: path to config 26 | :type setup_config_path: str 27 | """ 28 | 29 | def __init__(self, setup_config_path): 30 | super().__init__() 31 | self._setup_config_path = setup_config_path 32 | self.update(json.loads(_jsonnet.evaluate_file(setup_config_path))) 33 | 34 | def to_json(self, filename): 35 | with open(filename, "w", encoding="utf-8") as f: 36 | json.dump(self, f, ensure_ascii=False, indent=2) 37 | -------------------------------------------------------------------------------- /arline_benchmarks/engines/__init__.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /arline_benchmarks/engines/pipeline_engine.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import sys 19 | import traceback 20 | from os import makedirs, path 21 | from pprint import pprint 22 | from shutil import rmtree 23 | 24 | import pandas as pd 25 | from tqdm import tqdm 26 | 27 | from arline_benchmarks.pipeline.pipeline import Pipeline 28 | from arline_benchmarks.reports.results_logger import open_csv_results_logger 29 | from arline_benchmarks.targets.target import Target 30 | from arline_quantum.gate_chain.gate_chain import GateChain 31 | 32 | 33 | class PipelineEngine: 34 | """Benchmark Engine Class 35 | """ 36 | 37 | def __init__(self, cfg, args): 38 | self.args = args 39 | self.cfg = cfg 40 | self.run_id = 0 41 | 42 | def run(self): 43 | exit_code = 0 44 | # Output path 45 | output_dir = path.join(self.args.output) 46 | output_qasm_dir = path.join(output_dir, "qasm") 47 | self.create_result_dir(output_dir) 48 | self.create_result_dir(output_qasm_dir) 49 | # Convert .jsonnet config file to .json 50 | self.cfg.to_json(path.join(self.args.output, "config.json")) 51 | 52 | # column names in .csv output file 53 | id_columns_names = [ 54 | "Run ID", 55 | "Pipeline ID", 56 | "Stage ID", 57 | "Strategy ID", 58 | "Test Target Generator Name", 59 | "Test Target ID", 60 | "Pipeline Output Hardware Name", 61 | "Pipeline Output Number of Qubits", 62 | "QASM Path", 63 | "Test Type", 64 | ] 65 | 66 | columns_first = [] 67 | # Path to .csv report file with benchmarking results 68 | report_file = path.join(output_dir, "gate_chain_report.csv") 69 | 70 | with open_csv_results_logger(report_file, id_columns_names, columns_order=columns_first) as csv_logger: 71 | # Create Pipeline 72 | for pipeline_cfg in tqdm(self.cfg["pipelines"], desc="Overall benchmark progress", unit="pipeline"): 73 | pipeline = Pipeline(pipeline_id=pipeline_cfg["id"], stages=pipeline_cfg["stages"], run_analyser=True) 74 | # Create Target Generator 75 | target_generator = Target.from_config(config=pipeline_cfg["target"]) 76 | 77 | targets = [] 78 | while True: 79 | try: 80 | t = next(target_generator) 81 | if t is None: 82 | print("\n\nTarget is None", file=sys.stderr) 83 | print("Target config:", file=sys.stderr) 84 | pprint(pipeline_cfg["target"], stream=sys.stderr) 85 | continue 86 | targets.append(t) 87 | except StopIteration: 88 | break 89 | except Exception as e: 90 | print("\n\nError occurred when generating target", target_generator, file=sys.stderr) 91 | traceback.print_exc(file=sys.stderr) 92 | print("Target config:", file=sys.stderr) 93 | pprint(pipeline_cfg["target"], stream=sys.stderr) 94 | exit_code = -2 95 | continue 96 | 97 | for target, target_id in tqdm( 98 | targets, desc="Benchmarking pipeline {}".format(pipeline_cfg["id"]), unit="target", 99 | ): 100 | try: 101 | tqdm.write("Target ID: {}, Target Name: {}".format(target_id, pipeline_cfg["target"]["name"])) 102 | r = pipeline.run(target) 103 | except Exception as e: 104 | print( 105 | f"\n\nError occurred when running pipeline {pipeline.id} on target_id {target_id}:", 106 | file=sys.stderr, 107 | ) 108 | traceback.print_exc(file=sys.stderr) 109 | print("Pipeline config:", file=sys.stderr) 110 | pprint(pipeline_cfg, stream=sys.stderr) 111 | exit_code = -1 112 | continue 113 | 114 | for stg_cfg, stage_result, stg_report in zip( 115 | pipeline.stages, pipeline.stage_results, pipeline.analyser_report_history 116 | ): 117 | # Save Gate Chain 118 | file_path = path.join( 119 | output_qasm_dir, 120 | "{}_output_{}_{}_{}_{}".format( 121 | self.run_id, 122 | pipeline_cfg["id"], 123 | pipeline_cfg["target"]["name"], 124 | target_id, 125 | stg_cfg["id"] 126 | ), 127 | ) 128 | qasm_path = file_path+".qasm" 129 | chain_path = file_path+".pkl" 130 | if isinstance(stage_result, GateChain): 131 | stage_result.save_to_qasm(qasm_path, "q") 132 | 133 | # stage_result.save_chain(chain_path) #TODO fix problem with make_discrete 134 | # Add result to the .csv report 135 | 136 | hardw = pipeline.strategy_list[-1].quantum_hardware # Take hardware the last stage 137 | csv_logger.add_results( 138 | line_id=( 139 | self.run_id, # "Run ID", 140 | pipeline_cfg["id"], # "Pipeline ID", 141 | stg_cfg["id"], # "Stage ID", 142 | stg_cfg["strategy"], # "Strategy ID" 143 | pipeline_cfg["target"]["name"], # "Test Target Generator Name", 144 | target_id, # "Test Target ID", 145 | "{}".format(hardw.name), # "Pipeline Output Hardware Name", 146 | hardw.num_qubits, # "Pipeline Output Number of Qubits", 147 | qasm_path, # "QASM path" 148 | pipeline_cfg["test_type"], # "Test Type" 149 | ), 150 | data=stg_report, 151 | ) 152 | self.run_id += 1 153 | 154 | data = pd.read_csv(report_file) 155 | return exit_code 156 | 157 | def create_result_dir(self, d): 158 | rmtree(d, ignore_errors=True) 159 | makedirs(d) 160 | -------------------------------------------------------------------------------- /arline_benchmarks/metrics/__init__.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /arline_benchmarks/metrics/gate_chain_analyser.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | import os 18 | import tempfile 19 | 20 | from arline_quantum.gates import __gates_by_names__ 21 | from arline_quantum.utils.fidelity import meas_fidelity, matrix_to_psi 22 | from arline_quantum.estimators import Estimator 23 | 24 | from jkq import qcec 25 | 26 | DEBUG = 0 27 | 28 | 29 | class Analyser: 30 | """General analyser class 31 | """ 32 | 33 | def __init__(self, anls_list=None): 34 | self.report = {} 35 | self.anls_list = None 36 | 37 | def run_all(self, target, gate_chain): 38 | for f_name in self.available_anls(): 39 | getattr(self, f_name)(target, gate_chain) 40 | return self.report 41 | 42 | def available_anls(self): 43 | self.report = {} 44 | return [a for a in dir(self) if callable(getattr(self, a)) and hasattr(getattr(self, a), "is_analyse_function")] 45 | 46 | def run_selected(self, target, gate_chain): 47 | for f_name in self.anls_list: 48 | getattr(self, f_name)(target, gate_chain) 49 | return self.report 50 | 51 | 52 | def analyse(anls_func): 53 | """Call anls function and save result to file 54 | """ 55 | 56 | def anls_and_save(self, target, gate_chain): 57 | anls_name = anls_func.__name__ 58 | if DEBUG: 59 | print(anls_name, anls_func(self)) 60 | self.report.update(anls_func(self, target, gate_chain)) 61 | 62 | anls_and_save.is_analyse_function = True 63 | return anls_and_save 64 | 65 | 66 | class BasicAnalyser(Analyser): 67 | r"""Basic Gate Chain Analyser Class 68 | 69 | **Description:** 70 | Returns following relevant metrics: 71 | 72 | * Gate count by gate type 73 | * Circuit depth 74 | * Number of populated qubits (qubits involved in calculation) 75 | 76 | """ 77 | 78 | def __init__(self, verbose=False, cost_cfg={"class": "IbmCostFunction", "args": {}}): 79 | super().__init__() 80 | self.verbose = verbose 81 | self.cost_model = Estimator.from_config(cost_cfg) 82 | 83 | @analyse 84 | def depth(self, target, gate_chain): 85 | return {"Depth": gate_chain.get_depth()} 86 | 87 | @analyse 88 | def total_gate_count(self, target, gate_chain): 89 | return {"Total Gate Count": gate_chain.get_num_gates()} 90 | 91 | @analyse 92 | def gate_count_by_num_qubits(self, target, gate_chain): 93 | """Gate count by the number of qubits the gate acts on 94 | """ 95 | n_qubits = set() 96 | for g in gate_chain.quantum_hardware.gate_set.gate_list: 97 | n_qubits.add(g.num_qubits) 98 | # Add Single Qubit and Two Qubit Gates by default 99 | n_qubits.update({1, 2}) 100 | 101 | r = {n: 0 for n in range(1, max(n_qubits) + 1)} 102 | for gc in gate_chain.chain: 103 | r[gc._gate.num_qubits] += 1 104 | gcm = {} 105 | for n, v in r.items(): 106 | if n == 1: 107 | gcm["Single-Qubit Gate Count"] = v 108 | elif n == 2: 109 | gcm["Two-Qubit Gate Count"] = v 110 | else: 111 | gcm["{n}-Qubit Gate Count"] = v 112 | return gcm 113 | 114 | @analyse 115 | def gate_depth_by_num_qubits(self, target, gate_chain): 116 | """Gate depth by the number of qubits the gate acts on 117 | """ 118 | n_qubits = set() 119 | for g in gate_chain.quantum_hardware.gate_set.gate_list: 120 | n_qubits.add(g.num_qubits) 121 | # Add Single Qubit and Two Qubit Gates by default 122 | n_qubits.update({1, 2}) 123 | 124 | r = {n: 0 for n in range(1, max(n_qubits) + 1)} 125 | 126 | for n in range(1, max(n_qubits) + 1): 127 | gate_names = [g._gate.name for g in gate_chain.chain if g._gate.num_qubits == n] 128 | r[n] = gate_chain.get_depth_by_gate_type(gate_names) 129 | gcm = {} 130 | for n, v in r.items(): 131 | if n == 1: 132 | gcm["Single-Qubit Gate Depth"] = v 133 | elif n == 2: 134 | gcm["Two-Qubit Gate Depth"] = v 135 | else: 136 | gcm["{n}-Qubit Gate Depth"] = v 137 | return gcm 138 | 139 | @analyse 140 | def gate_count_by_type(self, target, gate_chain): 141 | gates_from_chain = gate_chain.get_gate_count() 142 | return { 143 | "Count of {} Gates".format(gate_name): gates_from_chain[gate_name] if gate_name in gates_from_chain else 0 144 | for gate_name in __gates_by_names__.keys() 145 | } 146 | 147 | @analyse 148 | def gate_depth_by_type(self, target, gate_chain): 149 | gates_from_chain = gate_chain.get_gate_count() 150 | return { 151 | "Depth of {} Gates".format(gate_name): gate_chain.get_depth_by_gate_type([gate_name]) 152 | if gate_name in gates_from_chain 153 | else 0 154 | for gate_name in __gates_by_names__.keys() 155 | } 156 | 157 | @analyse 158 | def gate_chain_cost_function(self, target, gate_chain): 159 | return {"Circuit Cost Function": self.cost_model.calculate_cost(gate_chain)} 160 | 161 | @analyse 162 | def num_populated_qubit(self, target, gate_chain): 163 | populated_qubits = 0 164 | for i in range(gate_chain.quantum_hardware.num_qubits): 165 | if gate_chain.get_num_gates_by_qubits(i) != 0: 166 | populated_qubits += 1 167 | return {"Number of Populated Qubits": populated_qubits} 168 | 169 | @analyse 170 | def connectivity_check(self, target, gate_chain): 171 | """Check Connectivity Violations 172 | """ 173 | violations = gate_chain.check_connectivity() 174 | return {"Connectivity Satisfied": (violations if self.verbose else (len(violations) == 0))} 175 | 176 | @analyse 177 | def gate_set_check(self, target, gate_chain): 178 | """Check Gate Set Violations 179 | """ 180 | violations = gate_chain.check_gate_set() 181 | return {"Gate Set Satisfied": (violations if self.verbose else (len(violations) == 0))} 182 | 183 | @analyse 184 | def qubit_number_check(self, target, gate_chain): 185 | """Check Qubit Number Violations 186 | """ 187 | violations = gate_chain.check_qubit_number() 188 | return {"Qubit Number Satisfied": (violations if self.verbose else (len(violations) == 0))} 189 | 190 | 191 | class GateChainTransformAnalyser(BasicAnalyser): 192 | r"""Gate Chain Transformation Analyser Class 193 | 194 | **Description:** 195 | Returns additional metrics: 196 | 197 | * Gate chain hardware (hardware class name corresponding to the current compilation pipeline stage) 198 | * Gate set for the current pipeline stage 199 | * Total number of qubits in the gate chain 200 | 201 | """ 202 | 203 | def __init__( 204 | self, 205 | verbose=False, 206 | cost_cfg={"class": "IbmCostFunction", "args": {}}, 207 | calculate_fidelity=False, 208 | fidelity_tol=0.999, 209 | check_equiv=False 210 | ): 211 | super().__init__(verbose, cost_cfg) 212 | self.calculate_fidelity = calculate_fidelity 213 | self.fidelity_tol = fidelity_tol 214 | self.check_equiv = check_equiv 215 | 216 | @analyse 217 | def fidelity(self, target, gate_chain): 218 | if not self.calculate_fidelity: 219 | return {} 220 | 221 | if target.quantum_hardware.num_qubits != gate_chain.quantum_hardware.num_qubits: 222 | # workaround when chains have different number of qubits 223 | num_qubits = max(target.quantum_hardware.num_qubits, gate_chain.quantum_hardware.num_qubits) 224 | 225 | if target.quantum_hardware.num_qubits != num_qubits: 226 | target = target.copy() 227 | target.quantum_hardware.num_qubits = num_qubits 228 | 229 | if gate_chain.quantum_hardware.num_qubits != num_qubits: 230 | gate_chain = gate_chain.copy() 231 | gate_chain.quantum_hardware.num_qubits = num_qubits 232 | 233 | target_psi = matrix_to_psi(target.matrix) 234 | current_psi = matrix_to_psi(gate_chain.matrix) 235 | fidelity = meas_fidelity(target_psi, current_psi) 236 | return {"Measurement Infidelity": abs(1-fidelity)} 237 | 238 | @analyse 239 | def gate_chain_hardware(self, target, gate_chain): 240 | hardw = gate_chain.quantum_hardware 241 | return {"Gate Chain Hardware": "{}".format(hardw.name)} 242 | 243 | @analyse 244 | def gate_chain_gate_set(self, target, gate_chain): 245 | gate_set_str = gate_chain.quantum_hardware.gate_set.get_gate_list_str() 246 | return {"Gate Set": gate_set_str} 247 | 248 | @analyse 249 | def gate_chain_hardware_number_of_qubits(self, target, gate_chain): 250 | return {"Gate Chain Number of Qubits": gate_chain.quantum_hardware.num_qubits} 251 | 252 | @analyse 253 | def check_equivalence(self, target, gate_chain): 254 | # Equivalence checker needs input/output .qasm files 255 | # Saving original and transformed gate chain to temporary files 256 | if not self.check_equiv: 257 | return {} 258 | with tempfile.TemporaryDirectory() as tmpdirname: 259 | fname_target = os.path.join(tmpdirname, "target.qasm") 260 | fname_chain = os.path.join(tmpdirname, "gate_chain.qasm") 261 | target.save_to_qasm(fname_target) 262 | gate_chain.save_to_qasm(fname_chain) 263 | 264 | # Checking circuit equivalence with qcec package 265 | equiv = qcec.verify( 266 | fname_chain, fname_target, fidelity=self.fidelity_tol, removeDiagonalGatesBeforeMeasure=True 267 | ) 268 | 269 | return {"Equivalence Checking": equiv["equivalence"]} 270 | 271 | 272 | class SynthesisAnalyser(BasicAnalyser): 273 | r"""QSP Gate Chain Analyser Class 274 | 275 | **Description:** 276 | 277 | QSP Gate Chain Analyser 278 | 279 | """ 280 | 281 | def __init__(self, fidelity_function, verbose=False, cost_cfg={"class": "IbmCostFunction", "args": {}}): 282 | super().__init__(verbose, cost_cfg) 283 | self._fidelity_function = fidelity_function 284 | 285 | @analyse 286 | def fidelity(self, target, gate_chain): 287 | fidelity = self._fidelity_function(target, gate_chain.matrix) 288 | return {"Fidelity": fidelity} 289 | 290 | @analyse 291 | def gate_chain_hardware(self, target, gate_chain): 292 | hardw = gate_chain.quantum_hardware 293 | return {"Gate Chain Hardware": "{}".format(hardw.name)} 294 | 295 | @analyse 296 | def gate_chain_gate_set(self, target, gate_chain): 297 | gate_set_str = gate_chain.quantum_hardware.gate_set.get_gate_list_str() 298 | return {"Gate Set": gate_set_str} 299 | 300 | @analyse 301 | def gate_chain_hardware_number_of_qubits(self, target, gate_chain): 302 | return {"Gate Chain Number of Qubits": gate_chain.quantum_hardware.num_qubits} 303 | -------------------------------------------------------------------------------- /arline_benchmarks/pipeline/__init__.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /arline_benchmarks/pipeline/pipeline.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from tqdm import tqdm 19 | 20 | from arline_benchmarks.strategies.strategy import Strategy 21 | 22 | 23 | class Pipeline: 24 | r"""Abstract Class for Pipeline 25 | """ 26 | 27 | def __init__(self, pipeline_id, stages, run_analyser): 28 | self.stages = stages 29 | self.run_analyser = run_analyser 30 | self.stage_results = [] 31 | self.analyser_report_history = [] 32 | self.id = pipeline_id 33 | self.strategy_list = [] 34 | for st_cfg in stages: 35 | self.strategy_list.append(Strategy.from_config(st_cfg)) 36 | 37 | def run(self, target): 38 | self.stage_results = [] 39 | self.analyser_report_history.clear() 40 | prev_stage_result = target 41 | # Sequentially execute strategies (stages) in compilation pipeline 42 | for strategy in self.strategy_list: 43 | tqdm.write("Pipeline ID: {}; Strategy: {}".format(self.id, str(strategy))) 44 | prev_stage_result = strategy.run(prev_stage_result, self.run_analyser) 45 | self.stage_results.append(prev_stage_result) 46 | # Return analyser results for the current compilation stage 47 | if self.run_analyser: 48 | strategy.analyser_report["Total Execution Time"] = self.get_accumulated_execution_time( 49 | strategy.analyser_report["Execution Time"] 50 | ) 51 | strategy.analyser_report["Full Check"] = ( 52 | strategy.analyser_report["Connectivity Satisfied"] 53 | and strategy.analyser_report["Gate Set Satisfied"] 54 | and strategy.analyser_report["Qubit Number Satisfied"] 55 | ) 56 | self.analyser_report_history.append(strategy.analyser_report) 57 | return prev_stage_result 58 | 59 | def get_accumulated_execution_time(self, last_stage_execution_time): 60 | if not self.analyser_report_history: 61 | return last_stage_execution_time 62 | else: 63 | return self.analyser_report_history[-1]["Total Execution Time"] + last_stage_execution_time 64 | 65 | def get_execution_time_by_stage(self, index): 66 | # Get runtime info for a particular compilation stage enumerated by index 67 | if index > len(self.stages): 68 | raise Exception( 69 | f"Index is larger then the number of stages: index = {index}, number of stages = {len(self.stages)}" 70 | ) 71 | return self.analyser_report_history[index]["execution_time"] 72 | 73 | def get_gate_chain_by_stage(self, index): 74 | if index > len(self.stages): 75 | raise Exception( 76 | f"Index is larger then the number of stages: index = {index}, number of stages = {len(self.stages)}" 77 | ) 78 | return self.stage_results[index] 79 | -------------------------------------------------------------------------------- /arline_benchmarks/reports/__init__.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /arline_benchmarks/reports/kak_scheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArlineQ/arline_benchmarks/d93ab31415fa400c5bf01a7fa0b0bf65db867336/arline_benchmarks/reports/kak_scheme.png -------------------------------------------------------------------------------- /arline_benchmarks/reports/results_logger.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from contextlib import contextmanager 19 | 20 | import pandas as pd 21 | 22 | 23 | class CsvResultsLogger: 24 | """ 25 | Columns order in csv: 26 | 27 | * all `id_columns_names` columns 28 | * columns with names from `columns_order` in specified order 29 | * all other columns 30 | """ 31 | 32 | def __init__(self, filename, id_columns_names, columns_order=[]): 33 | self._filename = filename 34 | self._id_columns_names = id_columns_names 35 | self._data = [] 36 | self._columns_order = columns_order 37 | 38 | def add_results(self, line_id, data): 39 | if len(line_id) != len(self._id_columns_names): 40 | Exception("line_id must be tuple with values of:", self._id_columns_names) 41 | d = data.copy() 42 | d.update({k: v for k, v in zip(self._id_columns_names, line_id)}) 43 | self._data.append(d) 44 | 45 | def close(self): 46 | columns_names = list(self._id_columns_names) 47 | columns_names += self._columns_order 48 | columns_name_set = set(columns_names) 49 | for d in self._data: 50 | for k in d.keys(): 51 | if k not in columns_name_set: 52 | columns_names.append(k) 53 | columns_name_set.add(k) 54 | 55 | results_df = pd.DataFrame(self._data, columns=columns_names) 56 | results_df.to_csv(self._filename, index=None, header=True) 57 | 58 | 59 | @contextmanager 60 | def open_csv_results_logger(*args, **kwargs): 61 | logger = CsvResultsLogger(*args, **kwargs) 62 | try: 63 | yield logger 64 | finally: 65 | logger.close() 66 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/__init__.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/arline_rebase.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import RebaseStrategy 6 | from arline_quantum.gate_sets.google import GoogleGateSet 7 | from arline_quantum.gate_sets.ibm import IbmGateSet 8 | from arline_quantum.gate_sets.ionq import IonqGateSet 9 | from arline_quantum.gate_sets.rigetti import RigettiGateSet 10 | from arline_quantum.gate_sets.pyzx import PyzxGateSet 11 | from arline_quantum.gate_sets.cx_rz_rx import CnotRzRxGateSet 12 | from arline_quantum.gate_sets.arline import ArlineGateSet 13 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 14 | 15 | _strategy_class_name = "ArlineRebase" 16 | 17 | 18 | class ArlineRebase(RebaseStrategy): 19 | r"""Class Wrapper for Arline Gate Rebase Strategy 20 | """ 21 | 22 | def run(self, target, run_analyser=True): 23 | 24 | start_time = timer() 25 | 26 | if isinstance(self.quantum_hardware.gate_set, GoogleGateSet): 27 | gate_chain = ArlineTranslator().rebase_to_google(target) 28 | elif isinstance(self.quantum_hardware.gate_set, IbmGateSet): 29 | gate_chain = ArlineTranslator().rebase_to_ibm(target) 30 | elif isinstance(self.quantum_hardware.gate_set, RigettiGateSet): 31 | gate_chain = ArlineTranslator().rebase_to_rigetti(target) 32 | elif isinstance(self.quantum_hardware.gate_set, IonqGateSet): 33 | gate_chain = ArlineTranslator().rebase_to_ionq(target) 34 | elif isinstance(self.quantum_hardware.gate_set, PyzxGateSet): 35 | gate_chain = ArlineTranslator().rebase_to_pyzx(target) 36 | elif isinstance(self.quantum_hardware.gate_set, CnotRzRxGateSet): 37 | gate_chain = ArlineTranslator().rebase_to_cx_rz_rx(target) 38 | elif isinstance(self.quantum_hardware.gate_set, ArlineGateSet): 39 | gate_chain = ArlineTranslator().rebase_to_arline(target) 40 | else: 41 | raise NotImplementedError() 42 | 43 | self.execution_time = timer() - start_time 44 | 45 | gate_chain.quantum_hardware = self.quantum_hardware 46 | 47 | if run_analyser: 48 | self.analyse(target, gate_chain) 49 | self.analyser_report["Execution Time"] = self.execution_time 50 | return gate_chain 51 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_3q_decomposition.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | 23 | from cirq.optimizers import three_qubit_decomposition 24 | 25 | 26 | _strategy_class_name = "Cirq3qDecomposition" 27 | 28 | 29 | class Cirq3qDecomposition(CompressionStrategy): 30 | r"""Perform Quantum Shannon Decomposition for 3q circuits 31 | """ 32 | 33 | def run(self, target, run_analyser=True): 34 | assert target.quantum_hardware.num_qubits == 3, 'Supports only 3q circuits' 35 | matrix_u = target.matrix 36 | 37 | circuit_object = target.convert_to("cirq") 38 | 39 | start_time = timer() 40 | a, b, c = cirq.LineQubit.range(3) 41 | operations = three_qubit_matrix_to_operations(a, b, c, matrix_u) 42 | circuit_object = cirq.Circuit(operations) 43 | 44 | self.execution_time = timer() - start_time 45 | 46 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 47 | gate_chain.quantum_hardware = self.quantum_hardware 48 | 49 | if run_analyser: 50 | self.analyse(target, gate_chain) 51 | self.analyser_report["Execution Time"] = self.execution_time 52 | return gate_chain 53 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_drop_empty_moments.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | 23 | from cirq.optimizers import DropEmptyMoments 24 | 25 | 26 | _strategy_class_name = "CirqDropEmptyMoments" 27 | 28 | 29 | class CirqDropEmptyMoments(CompressionStrategy): 30 | r"""Strategy for Cirq Drop Empty Moments 31 | """ 32 | 33 | def run(self, target, run_analyser=True): 34 | circuit_object = target.convert_to("cirq") 35 | 36 | start_time = timer() 37 | 38 | # drop empty moments 39 | DropEmptyMoments().optimize_circuit(circuit_object) 40 | 41 | self.execution_time = timer() - start_time 42 | 43 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 44 | gate_chain.quantum_hardware = self.quantum_hardware 45 | 46 | if run_analyser: 47 | self.analyse(target, gate_chain) 48 | self.analyser_report["Execution Time"] = self.execution_time 49 | return gate_chain 50 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_drop_negligible.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | 23 | from cirq.optimizers import DropNegligible 24 | 25 | 26 | _strategy_class_name = "CirqDropNegligible" 27 | 28 | 29 | class CirqDropNegligible(CompressionStrategy): 30 | r"""Strategy for Cirq Drop Negligible Gates 31 | """ 32 | 33 | def run(self, target, run_analyser=True): 34 | circuit_object = target.convert_to("cirq") 35 | 36 | start_time = timer() 37 | 38 | # drop negligible gates 39 | DropNegligible().optimize_circuit(circuit_object) 40 | 41 | self.execution_time = timer() - start_time 42 | 43 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 44 | gate_chain.quantum_hardware = self.quantum_hardware 45 | 46 | if run_analyser: 47 | self.analyse(target, gate_chain) 48 | self.analyser_report["Execution Time"] = self.execution_time 49 | return gate_chain 50 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_eject_phased_paulis.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 23 | from arline_quantum.gate_sets.cx_rz_rx import CnotRzRxGateSet 24 | from cirq.optimizers import EjectPhasedPaulis 25 | 26 | _strategy_class_name = "CirqEjectPhasedPaulis" 27 | 28 | 29 | class CirqEjectPhasedPaulis(CompressionStrategy): 30 | r"""Strategy for Cirq Push X, Y, and PhasedXPow Gates Toward the End of the Circuit 31 | """ 32 | 33 | def run(self, target, run_analyser=True): 34 | # Check if gates in target gate chain are from ['Cx', 'Rz', 'Rx'] set 35 | # If gates are not from ['Cx', 'Rz', 'Rx'] set, than perform rebase 36 | unique_gates = set([g.gate.name for g in target.chain]) 37 | if not all(g in CnotRzRxGateSet().get_gate_list_str() for g in unique_gates): 38 | gate_chain = ArlineTranslator().rebase_to_cx_rz_rx(target) 39 | else: 40 | gate_chain = target 41 | circuit_object = gate_chain.convert_to("cirq") 42 | 43 | start_time = timer() 44 | 45 | # Push X, Y, and PhasedXPow gates toward the end of the circuit 46 | eject_paulis = EjectPhasedPaulis() 47 | eject_paulis.optimize_circuit(circuit_object) 48 | 49 | self.execution_time = timer() - start_time 50 | 51 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 52 | gate_chain.quantum_hardware = self.quantum_hardware 53 | 54 | if run_analyser: 55 | self.analyse(target, gate_chain) 56 | self.analyser_report["Execution Time"] = self.execution_time 57 | return gate_chain 58 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_eject_z.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 23 | from arline_quantum.gate_sets.cx_rz_rx import CnotRzRxGateSet 24 | 25 | from cirq.optimizers import EjectZ 26 | 27 | _strategy_class_name = "CirqEjectZ" 28 | 29 | 30 | class CirqEjectZ(CompressionStrategy): 31 | r"""Strategy for Cirq Push Z Gates Toward the End of the Circuit 32 | """ 33 | 34 | def run(self, target, run_analyser=True): 35 | unique_gates = set([g.gate.name for g in target.chain]) 36 | if not all(g in CnotRzRxGateSet().get_gate_list_str() for g in unique_gates): 37 | gate_chain = ArlineTranslator().rebase_to_cx_rz_rx(target) 38 | else: 39 | gate_chain = target 40 | circuit_object = gate_chain.convert_to("cirq") 41 | 42 | start_time = timer() 43 | 44 | eject_z = EjectZ() 45 | eject_z.optimize_circuit(circuit_object) 46 | 47 | self.execution_time = timer() - start_time 48 | 49 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 50 | gate_chain.quantum_hardware = self.quantum_hardware 51 | 52 | if run_analyser: 53 | self.analyse(target, gate_chain) 54 | self.analyser_report["Execution Time"] = self.execution_time 55 | return gate_chain 56 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_mapping.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | from typing import List 20 | 21 | import cirq.contrib.routing as ccr 22 | from arline_benchmarks.strategies.strategy import MappingStrategy 23 | from arline_quantum.gate_chain.gate_chain import GateChain 24 | from arline_quantum.qubit_connectivities.qubit_connectivity import All2All 25 | from cirq import CNotPowGate, ExpandComposite, LineQubit, NamedQubit 26 | 27 | _strategy_class_name = "CirqMapping" 28 | 29 | 30 | class CirqMapping(MappingStrategy): 31 | r"""Cirq Mapping Strategy 32 | """ 33 | 34 | def __init__( 35 | self, 36 | hardware, 37 | routing_attempts=1, 38 | router=None, 39 | algo_name="greedy", 40 | random_state=1, 41 | max_search_radius=1, 42 | analyser_options={}, 43 | ): 44 | super().__init__(hardware, analyser_options) 45 | self.cirq_hardware = self.quantum_hardware.convert_to_cirq_hardware() 46 | self.routing_attempts = routing_attempts 47 | self.router = router 48 | self.algo_name = algo_name 49 | self.random_state = random_state 50 | self.max_search_radius = max_search_radius 51 | 52 | def run(self, target, run_analyser=True): 53 | circuit_object = target.convert_to("cirq") 54 | 55 | start_time = timer() 56 | 57 | # Skip routing+mapping if hardware has All2All connectivity 58 | if isinstance(self.quantum_hardware.qubit_connectivity, All2All): 59 | print("All2All connectivity, skipping routing") 60 | else: 61 | # only 'greedy' routing is implemented in Cirq 62 | swap_networks: List[ccr.SwapNetwork] = [] 63 | 64 | routing_attempts = self.routing_attempts 65 | for _ in range(routing_attempts): 66 | swap_network = ccr.route_circuit( 67 | circuit_object, 68 | self.cirq_hardware, 69 | router=self.router, 70 | algo_name=self.algo_name, 71 | random_state=self.random_state, 72 | max_search_radius=self.max_search_radius 73 | ) 74 | swap_networks.append(swap_network) 75 | assert len(swap_networks) > 0, "Unable to get routing for circuit" 76 | # Sort by the least number of qubits first (as routing sometimes adds extra ancilla qubits), 77 | # and then the length of the circuit second. 78 | swap_networks.sort(key=lambda swap_network: (len(swap_network.circuit.all_qubits()), len(swap_network.circuit))) 79 | 80 | circuit_object = swap_networks[0].circuit 81 | 82 | qubit_order = {LineQubit(n): NamedQubit(f"q_{n}") for n in range(self.quantum_hardware.num_qubits)} 83 | 84 | # decompose composite gates 85 | no_decomp = lambda op: isinstance(op.gate, CNotPowGate) 86 | ExpandComposite(no_decomp=no_decomp).optimize_circuit(circuit_object) 87 | 88 | self.execution_time = timer() - start_time 89 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 90 | gate_chain.quantum_hardware = self.quantum_hardware 91 | 92 | if run_analyser: 93 | self.analyse(target, gate_chain) 94 | self.analyser_report["Execution Time"] = self.execution_time 95 | return gate_chain 96 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_mapping_compression.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | from typing import List 20 | 21 | from arline_benchmarks.strategies.strategy import CompressionStrategy 22 | from arline_quantum.gate_chain.gate_chain import GateChain 23 | from arline_quantum.qubit_connectivities.qubit_connectivity import All2All 24 | from arline_quantum.gate_sets.cx_rz_rx import CnotRzRxGateSet 25 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 26 | 27 | import cirq.contrib.routing as ccr 28 | from cirq import CNotPowGate, ExpandComposite, LineQubit, NamedQubit 29 | 30 | from cirq.optimizers import EjectZ, EjectPhasedPaulis, DropNegligible, DropEmptyMoments 31 | from cirq.optimizers import MergeInteractions 32 | from cirq import merge_single_qubit_gates_into_phased_x_z 33 | from cirq.google.optimizers import optimized_for_xmon 34 | 35 | _strategy_class_name = "CirqMappingCompression" 36 | 37 | 38 | class CirqMappingCompression(CompressionStrategy): 39 | r"""Cirq Mapping+Compression Strategy 40 | """ 41 | 42 | def __init__( 43 | self, 44 | hardware, 45 | routing_attempts=1, 46 | router=None, 47 | algo_name="greedy", 48 | random_state=1, 49 | max_search_radius=1, 50 | analyser_options={}, 51 | ): 52 | super().__init__(hardware, analyser_options) 53 | self.cirq_hardware = self.quantum_hardware.convert_to_cirq_hardware() 54 | self.routing_attempts = routing_attempts 55 | self.router = router 56 | self.algo_name = algo_name 57 | self.random_state = random_state 58 | self.max_search_radius = max_search_radius 59 | 60 | def run(self, target, run_analyser=True): 61 | # Check if gates in target gate chain are from ['Cz', 'Rz', 'Rx'] set 62 | # If gates are not from ['Cz', 'Rz', 'Rx'] set, than perform rebase 63 | unique_gates = set([g.gate.name for g in target.chain]) 64 | if not all(g in CnotRzRxGateSet().get_gate_list_str() for g in unique_gates): 65 | gate_chain = ArlineTranslator().rebase_to_cx_rz_rx(target) 66 | else: 67 | gate_chain = target 68 | 69 | circuit_object = gate_chain.convert_to("cirq") 70 | 71 | start_time = timer() 72 | 73 | # Skip routing+mapping if hardware has All2All connectivity 74 | if isinstance(self.quantum_hardware.qubit_connectivity, All2All): 75 | print("\nAll2All connectivity, skipping routing") 76 | else: 77 | # First perform circuit routing 78 | # only 'greedy' routing is implemented in Cirq 79 | swap_networks: List[ccr.SwapNetwork] = [] 80 | routing_attempts = self.routing_attempts 81 | for _ in range(routing_attempts): 82 | swap_network = ccr.route_circuit( 83 | circuit_object, 84 | self.cirq_hardware, 85 | router=self.router, 86 | algo_name=self.algo_name, 87 | random_state=self.random_state, 88 | max_search_radius=self.max_search_radius 89 | ) 90 | swap_networks.append(swap_network) 91 | assert len(swap_networks) > 0, "Unable to get routing for circuit" 92 | # Sort by the least number of qubits first (as routing sometimes adds extra ancilla qubits), 93 | # and then the length of the circuit second. 94 | swap_networks.sort(key=lambda swap_network: (len(swap_network.circuit.all_qubits()), len(swap_network.circuit))) 95 | circuit_object = swap_networks[0].circuit 96 | 97 | # decompose composite gates 98 | no_decomp = lambda op: isinstance(op.gate, CNotPowGate) 99 | ExpandComposite(no_decomp=no_decomp).optimize_circuit(circuit_object) 100 | 101 | # Now run Cirq circuit optimization passes: 102 | # Convert to Xmon gates (native gates for Google transmon devices) 103 | # (Essential to get optimal performance) 104 | circuit_object = optimized_for_xmon(circuit_object) 105 | # Push Z gates toward the end of the circuit 106 | EjectZ().optimize_circuit(circuit_object) 107 | # Push X, Y, and PhasedXPow gates toward the end of the circuit 108 | EjectPhasedPaulis().optimize_circuit(circuit_object) 109 | # Merge Interactions pass 110 | MergeInteractions().optimize_circuit(circuit_object) 111 | # Merge single-qubit gates into PhasedX and PhasedZ gates 112 | merge_single_qubit_gates_into_phased_x_z(circuit_object) 113 | # Drop negligible gates 114 | DropNegligible().optimize_circuit(circuit_object) 115 | # Drop empty moments 116 | DropEmptyMoments().optimize_circuit(circuit_object) 117 | 118 | self.execution_time = timer() - start_time 119 | 120 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 121 | gate_chain.quantum_hardware = self.quantum_hardware 122 | 123 | if run_analyser: 124 | self.analyse(target, gate_chain) 125 | self.analyser_report["Execution Time"] = self.execution_time 126 | return gate_chain 127 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_merge_1q.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | 23 | from cirq import merge_single_qubit_gates_into_phased_x_z 24 | 25 | 26 | _strategy_class_name = "CirqMerge1Q" 27 | 28 | 29 | class CirqMerge1Q(CompressionStrategy): 30 | r"""Strategy for Cirq Merge Single-Qubit Gates into PhasedX and PhasedZ Gates 31 | """ 32 | 33 | def run(self, target, run_analyser=True): 34 | circuit_object = target.convert_to("cirq") 35 | 36 | start_time = timer() 37 | 38 | # Merge single qubit gates into PhasedX and PhasedZ gates 39 | merge_single_qubit_gates_into_phased_x_z(circuit_object) 40 | 41 | self.execution_time = timer() - start_time 42 | 43 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 44 | gate_chain.quantum_hardware = self.quantum_hardware 45 | 46 | if run_analyser: 47 | self.analyse(target, gate_chain) 48 | self.analyser_report["Execution Time"] = self.execution_time 49 | return gate_chain 50 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_merge_interactions.py: -------------------------------------------------------------------------------- 1 | 2 | # Arline Benchmarks 3 | # Copyright (C) 2019-2022 Turation Ltd 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as 7 | # published by the Free Software Foundation, either version 3 of the 8 | # License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | 18 | 19 | from timeit import default_timer as timer 20 | 21 | from arline_benchmarks.strategies.strategy import CompressionStrategy 22 | from arline_quantum.gate_chain.gate_chain import GateChain 23 | 24 | from cirq.optimizers import MergeInteractions 25 | 26 | 27 | _strategy_class_name = "CirqMergeInteractions" 28 | 29 | 30 | class CirqMergeInteractions(CompressionStrategy): 31 | r"""Strategy for Cirq Merge Interactions 1q+2q 32 | """ 33 | 34 | def run(self, target, run_analyser=True): 35 | circuit_object = target.convert_to("cirq") 36 | 37 | start_time = timer() 38 | 39 | MergeInteractions().optimize_circuit(circuit_object) 40 | 41 | self.execution_time = timer() - start_time 42 | 43 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 44 | gate_chain.quantum_hardware = self.quantum_hardware 45 | 46 | if run_analyser: 47 | self.analyse(target, gate_chain) 48 | self.analyser_report["Execution Time"] = self.execution_time 49 | return gate_chain 50 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/cirq_optimize_for_xmon.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 23 | from arline_quantum.gate_sets.cx_rz_rx import CnotRzRxGateSet 24 | 25 | from cirq.google.optimizers import optimized_for_xmon 26 | 27 | _strategy_class_name = "CirqOptimizeForXmon" 28 | 29 | 30 | class CirqOptimizeForXmon(CompressionStrategy): 31 | r"""Convert To Xmon Gates (Native Gates For Google Transmon Devices) 32 | """ 33 | 34 | def run(self, target, run_analyser=True): 35 | unique_gates = set([g.gate.name for g in target.chain]) 36 | if not all(g in CnotRzRxGateSet().get_gate_list_str() for g in unique_gates): 37 | gate_chain = ArlineTranslator().rebase_to_cx_rz_rx(target) 38 | else: 39 | gate_chain = target 40 | circuit_object = gate_chain.convert_to("cirq") 41 | 42 | start_time = timer() 43 | 44 | circuit_object = optimized_for_xmon(circuit_object) 45 | 46 | self.execution_time = timer() - start_time 47 | 48 | gate_chain = GateChain.convert_from(circuit_object, format_id="cirq") 49 | gate_chain.quantum_hardware = self.quantum_hardware 50 | 51 | if run_analyser: 52 | self.analyse(target, gate_chain) 53 | self.analyser_report["Execution Time"] = self.execution_time 54 | return gate_chain 55 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/post_processing.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | from timeit import default_timer as timer 18 | 19 | from arline_benchmarks.strategies.strategy import CircuitProcessingStrategy 20 | from arline_quantum.gate_chain.gate_chain import GateChain 21 | from arline_quantum.gates.measure import Measure 22 | 23 | _strategy_class_name = "PostProcessing" 24 | 25 | 26 | class PostProcessing(CircuitProcessingStrategy): 27 | r"""Post-Processing Gates Strategy 28 | """ 29 | 30 | def __init__( 31 | self, 32 | hardware, 33 | remove_measure=False, 34 | analyser_options={} 35 | ): 36 | super().__init__(hardware, analyser_options) 37 | self.remove_measure = remove_measure 38 | 39 | def run(self, target, run_analyser=True): 40 | start_time = timer() 41 | 42 | if self.remove_measure: 43 | gate_chain = GateChain(target.quantum_hardware) 44 | # Add all gates except Measure to empty gate chain 45 | for el in target: 46 | if not isinstance(el.gate, Measure): 47 | gate_chain.add_gate(el.gate, el.connections) 48 | 49 | self.execution_time = timer() - start_time 50 | gate_chain.quantum_hardware = self.quantum_hardware 51 | if run_analyser: 52 | self.analyse(target, gate_chain) 53 | self.analyser_report["Execution Time"] = self.execution_time 54 | return gate_chain 55 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pre_processing.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | from timeit import default_timer as timer 18 | 19 | from arline_benchmarks.strategies.strategy import CircuitProcessingStrategy 20 | from arline_quantum.gates.measure import Measure 21 | from arline_quantum.gates.barrier import Barrier 22 | 23 | _strategy_class_name = "PreProcessing" 24 | 25 | 26 | class PreProcessing(CircuitProcessingStrategy): 27 | r"""Pre-Processing Strategy 28 | """ 29 | 30 | def __init__( 31 | self, 32 | hardware, 33 | add_measure=False, 34 | combine_regs=True, 35 | analyser_options={} 36 | ): 37 | super().__init__(hardware, analyser_options) 38 | self.add_measure = add_measure 39 | self.combine_regs = combine_regs 40 | 41 | def run(self, target, run_analyser=False): 42 | gate_chain = target.copy() 43 | start_time = timer() 44 | 45 | if self.combine_regs and len(gate_chain.qreg_mapping) > 1: 46 | gate_chain.qreg_mapping = {} 47 | gate_chain.qreg_mapping["q"] = {v: v for v in range(self.quantum_hardware.num_qubits)} 48 | 49 | if self.combine_regs and len(gate_chain.creg_mapping) > 1: 50 | creg_num = sum([len(r) for r in self.creg_mapping.values()]) 51 | gate_chain.creg_mapping = {} 52 | gate_chain.creg_mapping["c"] = {v: v for v in range(creg_num)} 53 | 54 | if self.add_measure: 55 | # Add barrier separator 56 | qubits = list(range(gate_chain.quantum_hardware.num_qubits)) 57 | gate_chain.add_gate(Barrier(), connections=qubits) 58 | # Add Measure gates (default creg assignment) 59 | for q in qubits: 60 | gate_chain.add_gate(Measure(), connections=[q], cregs=[q]) 61 | 62 | self.execution_time = timer() - start_time 63 | if run_analyser: 64 | self.analyse(target, gate_chain) 65 | self.analyser_report["Execution Time"] = self.execution_time 66 | return gate_chain -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_chem_pass.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 8 | from arline_quantum.gate_sets.cx_rz_rx import CnotRzRxGateSet 9 | 10 | from pytket.passes import PauliSimp, SequencePass, FullPeepholeOptimise, OptimisePhaseGadgets 11 | 12 | _strategy_class_name = "PytketChemPass" 13 | 14 | 15 | class PytketChemPass(CompressionStrategy): 16 | r"""PytketChemPass Optimise Strategy 17 | """ 18 | 19 | def run(self, target, run_analyser=True): 20 | unique_gates = set([g.gate.name for g in target.chain]) 21 | if not all(g in CnotRzRxGateSet().get_gate_list_str() for g in unique_gates): 22 | gate_chain = ArlineTranslator().rebase_to_cx_rz_rx(target) 23 | else: 24 | gate_chain = target 25 | circuit_object = PytketGateChainConverter().from_gate_chain(gate_chain) 26 | 27 | start_time = timer() 28 | 29 | chem_pass = SequencePass([PauliSimp(), FullPeepholeOptimise()]) 30 | chem_pass.apply(circuit_object) 31 | 32 | self.execution_time = timer() - start_time 33 | 34 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 35 | gate_chain.quantum_hardware = self.quantum_hardware 36 | 37 | if run_analyser: 38 | self.analyse(target, gate_chain) 39 | self.analyser_report["Execution Time"] = self.execution_time 40 | return gate_chain 41 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_commute_multis.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.transform import CommuteThroughMultis 9 | 10 | _strategy_class_name = "PytketCommuteThroughMultis" 11 | 12 | 13 | class PytketCommuteThroughMultis(CompressionStrategy): 14 | r"""Pytket CommuteThroughMultis Strategy 15 | (Applies a collection of commutation rules to move single qubit operations 16 | past multiqubit operations they commute with, towards the front of the circuit.) 17 | """ 18 | 19 | def run(self, target, run_analyser=True): 20 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 21 | 22 | start_time = timer() 23 | CommuteThroughMultis().apply(circuit_object) 24 | self.execution_time = timer() - start_time 25 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 26 | gate_chain.quantum_hardware = self.quantum_hardware 27 | 28 | if run_analyser: 29 | self.analyse(target, gate_chain) 30 | self.analyser_report["Execution Time"] = self.execution_time 31 | return gate_chain 32 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_cx_directed.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.transform import Transform 9 | from pytket.routing import Architecture 10 | 11 | _strategy_class_name = "PytketCxDirected" 12 | 13 | 14 | class PytketCxDirected(CompressionStrategy): 15 | r"""Pytket CxDirected Strategy 16 | 17 | (changes direction of CX gates to match topology) 18 | """ 19 | 20 | def __init__( 21 | self, 22 | hardware, 23 | analyser_options={}, 24 | ): 25 | super().__init__(hardware, analyser_options) 26 | self.pytket_hardware = self.convert_to_pytket_hardware() 27 | 28 | def run(self, target, run_analyser=True): 29 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 30 | 31 | start_time = timer() 32 | 33 | # Change direction of CXs if needed (for directed coupling graph) 34 | Transform.DecomposeCXDirected(self.pytket_hardware).apply(circuit_object) 35 | self.execution_time = timer() - start_time 36 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 37 | gate_chain.quantum_hardware = self.quantum_hardware 38 | 39 | if run_analyser: 40 | self.analyse(target, gate_chain) 41 | self.analyser_report["Execution Time"] = self.execution_time 42 | return gate_chain 43 | 44 | def convert_to_pytket_hardware(self): 45 | coupling_map = self.quantum_hardware.qubit_connectivity.get_coupling_map() 46 | topology = [tuple(edge) for edge in coupling_map] 47 | hardware = Architecture(topology) 48 | return hardware 49 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_default_mapping.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import MappingStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.transform import Transform 9 | 10 | from pytket.passes import DefaultMappingPass 11 | from pytket.device import Device 12 | from pytket.routing import Architecture 13 | 14 | _strategy_class_name = "PytketDefaultMapping" 15 | 16 | 17 | class PytketDefaultMapping(MappingStrategy): 18 | r"""Pytket Default Mapping Strategy. 19 | Constructs a pass to relabel Circuit Qubits to Device Nodes, 20 | and then routes to the connectivity graph of a :py:class: ‘Device’. 21 | Edge direction is ignored. Placement used is GraphPlacement. 22 | """ 23 | 24 | def __init__( 25 | self, 26 | hardware, 27 | analyser_options={}, 28 | ): 29 | super().__init__(hardware, analyser_options) 30 | self.pytket_hardware = self.convert_to_pytket_hardware() 31 | 32 | def run(self, target, run_analyser=True): 33 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 34 | 35 | start_time = timer() 36 | DefaultMappingPass(Device(self.pytket_hardware)).apply(circuit_object) 37 | Transform.DecomposeBRIDGE().apply(circuit_object) 38 | Transform.DecomposeSWAPtoCX(self.pytket_hardware).apply(circuit_object) 39 | self.execution_time = timer() - start_time 40 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 41 | gate_chain.quantum_hardware = self.quantum_hardware 42 | 43 | if run_analyser: 44 | self.analyse(target, gate_chain) 45 | self.analyser_report["Execution Time"] = self.execution_time 46 | return gate_chain 47 | 48 | def convert_to_pytket_hardware(self): 49 | coupling_map = self.quantum_hardware.qubit_connectivity.get_coupling_map() 50 | topology = [tuple(edge) for edge in coupling_map] 51 | hardware = Architecture(topology) 52 | return hardware 53 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_mapping.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import MappingStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.transform import Transform 9 | 10 | from pytket.passes import DefaultMappingPass 11 | from pytket.device import Device 12 | from pytket.routing import Architecture 13 | 14 | _strategy_class_name = "PytketMapping" 15 | 16 | 17 | class PytketMapping(MappingStrategy): 18 | r"""Pytket Mapping Strategy 19 | """ 20 | 21 | def __init__( 22 | self, 23 | hardware, 24 | analyser_options={}, 25 | ): 26 | super().__init__(hardware, analyser_options) 27 | self.pytket_hardware = self.convert_to_pytket_hardware() 28 | 29 | def run(self, target, run_analyser=True): 30 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 31 | 32 | start_time = timer() 33 | 34 | # Default mapping pass 35 | DefaultMappingPass(Device(self.pytket_hardware)).apply(circuit_object) 36 | Transform.DecomposeBRIDGE().apply(circuit_object) 37 | Transform.DecomposeSWAPtoCX(self.pytket_hardware).apply(circuit_object) 38 | 39 | self.execution_time = timer() - start_time 40 | 41 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 42 | gate_chain.quantum_hardware = self.quantum_hardware 43 | 44 | if run_analyser: 45 | self.analyse(target, gate_chain) 46 | self.analyser_report["Execution Time"] = self.execution_time 47 | return gate_chain 48 | 49 | def convert_to_pytket_hardware(self): 50 | coupling_map = self.quantum_hardware.qubit_connectivity.get_coupling_map() 51 | topology = [tuple(edge) for edge in coupling_map] 52 | hardware = Architecture(topology) 53 | return hardware 54 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_mapping_compression.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.transform import Transform 9 | from pytket.passes import PauliSimp, SequencePass, FullPeepholeOptimise 10 | 11 | from pytket.routing import Architecture 12 | from pytket.passes import DefaultMappingPass 13 | from pytket.device import Device 14 | from pytket.passes import SynthesiseIBM 15 | 16 | _strategy_class_name = "PytketMappingCompression" 17 | 18 | 19 | class PytketMappingCompression(CompressionStrategy): 20 | r"""Pytket Mapping+Compression Strategy 21 | """ 22 | 23 | def __init__( 24 | self, 25 | hardware, 26 | analyser_options={}, 27 | chem_pass=False, 28 | ): 29 | super().__init__(hardware, analyser_options) 30 | self.pytket_hardware = self.convert_to_pytket_hardware() 31 | self.chem_pass = chem_pass 32 | 33 | def run(self, target, run_analyser=True): 34 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 35 | 36 | start_time = timer() 37 | 38 | # This works only for pytket==0.6.0 39 | # qubit_placement = LinePlacement(Device(self.pytket_hardware)) 40 | # qubit_placement.place(circuit_object) # In case of LinePlacement or GraphPlacement 41 | # qmap = qubit_placement.get_placement_map(circuit_object) 42 | 43 | # Uncomment to impose trivial qubit map 44 | # qmap = {Qubit(i): Node(i) for i in range(self.quantum_hardware.num_qubits)} 45 | # place_with_map(circuit_object, qmap) 46 | 47 | # Default qubit mapping 48 | qmap = None 49 | if self.chem_pass: 50 | # Chemistry-tailored optimisation pass 51 | SequencePass([PauliSimp(), FullPeepholeOptimise()]).apply(circuit_object) 52 | SynthesiseIBM().apply(circuit_object) 53 | else: 54 | # The main optimisation pass (heavy) 55 | FullPeepholeOptimise().apply(circuit_object) 56 | # Default mapping pass 57 | DefaultMappingPass(Device(self.pytket_hardware)).apply(circuit_object) 58 | # Decomposes all Pytket BRIDGE gates into CX gates 59 | Transform.DecomposeBRIDGE().apply(circuit_object) 60 | # Decomposes all SWAP gates into triples of CX gates. 61 | # If the SWAP is adjacent to a CX, it will prefer to insert in the direction that allows for gate cancellation. 62 | # When an Architecture is provided, this will prefer to insert the CXs such that fewer need redirecting. 63 | Transform.DecomposeSWAPtoCX(self.pytket_hardware).apply(circuit_object) 64 | # Rebase to CX, U1, U3 and optimize 65 | SynthesiseIBM().apply(circuit_object) 66 | self.execution_time = timer() - start_time 67 | 68 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object, qmap=qmap) 69 | gate_chain.quantum_hardware = self.quantum_hardware 70 | 71 | if run_analyser: 72 | self.analyse(target, gate_chain) 73 | self.analyser_report["Execution Time"] = self.execution_time 74 | return gate_chain 75 | 76 | def convert_to_pytket_hardware(self): 77 | coupling_map = self.quantum_hardware.qubit_connectivity.get_coupling_map() 78 | topology = [tuple(edge) for edge in coupling_map] 79 | hardware = Architecture(topology) 80 | return hardware 81 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_pauli_simp.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 8 | from arline_quantum.gate_sets.cx_rz_rx import CnotRzRxGateSet 9 | 10 | from pytket.passes import PauliSimp 11 | 12 | _strategy_class_name = "PytketPauliSimp" 13 | 14 | 15 | class PytketPauliSimp(CompressionStrategy): 16 | r"""PytketPauliSimp Optimise Strategy 17 | """ 18 | 19 | def run(self, target, run_analyser=True): 20 | unique_gates = set([g.gate.name for g in target.chain]) 21 | if not all(g in CnotRzRxGateSet().get_gate_list_str() for g in unique_gates): 22 | gate_chain = ArlineTranslator().rebase_to_cx_rz_rx(target) 23 | else: 24 | gate_chain = target 25 | circuit_object = PytketGateChainConverter().from_gate_chain(gate_chain) 26 | 27 | start_time = timer() 28 | 29 | PauliSimp().apply(circuit_object) 30 | 31 | self.execution_time = timer() - start_time 32 | 33 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 34 | gate_chain.quantum_hardware = self.quantum_hardware 35 | 36 | if run_analyser: 37 | self.analyse(target, gate_chain) 38 | self.analyser_report["Execution Time"] = self.execution_time 39 | return gate_chain 40 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_peephole.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.passes import FullPeepholeOptimise 9 | 10 | _strategy_class_name = "PytketPeephole" 11 | 12 | 13 | class PytketPeephole(CompressionStrategy): 14 | r"""Pytket Full Peephole Optimise Strategy 15 | """ 16 | 17 | def run(self, target, run_analyser=True): 18 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 19 | 20 | start_time = timer() 21 | 22 | # The main optimisation pass (heavy) 23 | FullPeepholeOptimise().apply(circuit_object) 24 | 25 | self.execution_time = timer() - start_time 26 | 27 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 28 | gate_chain.quantum_hardware = self.quantum_hardware 29 | 30 | if run_analyser: 31 | self.analyse(target, gate_chain) 32 | self.analyser_report["Execution Time"] = self.execution_time 33 | return gate_chain 34 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_postrouting.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.transform import Transform 9 | 10 | _strategy_class_name = "PytketPostrouting" 11 | 12 | 13 | class PytketPostrouting(CompressionStrategy): 14 | r"""Pytket Optimise Post Routing Strategy 15 | """ 16 | 17 | def run(self, target, run_analyser=True): 18 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 19 | 20 | start_time = timer() 21 | 22 | # Fast optimisation pass, performing basic simplifications 23 | # Works on any circuit, giving the result in U1, U2, U3, CX gates. 24 | # If all multi-qubit gates are CXs, then this preserves their placement and orientation, 25 | # so it is safe to perform after routing. 26 | 27 | Transform.OptimisePostRouting().apply(circuit_object) 28 | self.execution_time = timer() - start_time 29 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 30 | gate_chain.quantum_hardware = self.quantum_hardware 31 | 32 | if run_analyser: 33 | self.analyse(target, gate_chain) 34 | self.analyser_report["Execution Time"] = self.execution_time 35 | return gate_chain 36 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_rebase.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import RebaseStrategy 6 | from arline_quantum.gate_chain.gate_chain import GateChain 7 | from arline_quantum.gate_sets.google import GoogleGateSet 8 | from arline_quantum.gate_sets.ibm import IbmGateSet 9 | from arline_quantum.gate_sets.ionq import IonqGateSet 10 | from arline_quantum.gate_sets.pyzx import PyzxGateSet 11 | from arline_quantum.gate_sets.rigetti import RigettiGateSet 12 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 13 | 14 | from pytket.cirq import tk_to_cirq 15 | from pytket.passes import RebaseCirq, RebaseIBM, RebasePyZX, RebaseQuil, RebaseUMD 16 | 17 | 18 | _strategy_class_name = "PytketRebase" 19 | 20 | 21 | class PytketRebase(RebaseStrategy): 22 | r"""Pytket Gate Rebase Strategy 23 | """ 24 | 25 | def run(self, target, run_analyser=True): 26 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 27 | 28 | start_time = timer() 29 | 30 | if isinstance(self.quantum_hardware.gate_set, GoogleGateSet): 31 | RebaseCirq().apply(circuit_object) 32 | elif isinstance(self.quantum_hardware.gate_set, IbmGateSet): 33 | RebaseIBM().apply(circuit_object) 34 | elif isinstance(self.quantum_hardware.gate_set, PyzxGateSet): 35 | RebasePyZX().apply(circuit_object) 36 | elif isinstance(self.quantum_hardware.gate_set, RigettiGateSet): 37 | RebaseQuil().apply(circuit_object) 38 | elif isinstance(self.quantum_hardware.gate_set, IonqGateSet): # TODO PhasedX to Rxy 39 | # RebaseUMD().apply(optimised_circuit) 40 | raise Exception("PhasedX gate is not implemented yet") 41 | else: 42 | raise NotImplementedError() 43 | 44 | self.execution_time = timer() - start_time 45 | 46 | gate_chain = self.save_gate_chain(circuit_object) 47 | gate_chain.quantum_hardware = self.quantum_hardware 48 | 49 | if run_analyser: 50 | self.analyse(target, gate_chain) 51 | self.analyser_report["Execution Time"] = self.execution_time 52 | return gate_chain 53 | 54 | def save_gate_chain(self, circuit_object): 55 | # Check if this code is still needed 56 | if isinstance(self.quantum_hardware.gate_set, GoogleGateSet): 57 | cirq_circuit = tk_to_cirq(circuit_object) 58 | qasm_data = cirq_circuit.to_qasm() 59 | lines = qasm_data.split("\n") 60 | gate_chain = GateChain.from_qasm(lines, self.quantum_hardware) # TODO set quantum_hardware 61 | return gate_chain 62 | else: 63 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 64 | return gate_chain 65 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_remove_redundancies.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.transform import RemoveRedundancies 9 | 10 | _strategy_class_name = "PytketRemoveRedundancies" 11 | 12 | 13 | class PytketRemoveRedundancies(CompressionStrategy): 14 | r"""Pytket RemoveRedundancies Strategy 15 | (Applies a collection of simple optimisations, such as removing gate-inverse pairs, merging similar rotation gates, 16 | and removing identity gates. Preserves the gate set and any placement/orientation of multi-qubit gates.) 17 | """ 18 | 19 | def run(self, target, run_analyser=True): 20 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 21 | 22 | start_time = timer() 23 | RemoveRedundancies().apply(circuit_object) 24 | self.execution_time = timer() - start_time 25 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 26 | gate_chain.quantum_hardware = self.quantum_hardware 27 | 28 | if run_analyser: 29 | self.analyse(target, gate_chain) 30 | self.analyser_report["Execution Time"] = self.execution_time 31 | return gate_chain 32 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pytket_synthesise_ibm.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 7 | 8 | from pytket.passes import SynthesiseIBM 9 | 10 | _strategy_class_name = "PytketSynthesiseIbm" 11 | 12 | 13 | class PytketSynthesiseIbm(CompressionStrategy): 14 | r"""Pytket SynthesiseIBM Strategy 15 | (Optimises circuit preserving connectivity and converts all gates to CX, U1, U2 and U3 gates.) 16 | """ 17 | 18 | def run(self, target, run_analyser=True): 19 | circuit_object = PytketGateChainConverter().from_gate_chain(target) 20 | 21 | start_time = timer() 22 | 23 | SynthesiseIBM().apply(circuit_object) 24 | 25 | self.execution_time = timer() - start_time 26 | 27 | gate_chain = PytketGateChainConverter().to_gate_chain(circuit_object) 28 | gate_chain.quantum_hardware = self.quantum_hardware 29 | 30 | if run_analyser: 31 | self.analyse(target, gate_chain) 32 | self.analyser_report["Execution Time"] = self.execution_time 33 | return gate_chain 34 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pyzx_clifford_simp.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.gate_chain import GateChain 7 | 8 | import pyzx as zx 9 | 10 | _strategy_class_name = "PyzxCliffordSimp" 11 | 12 | 13 | class PyzxCliffordSimp(CompressionStrategy): 14 | r"""PyZX Clifford Simplify Strategy 15 | """ 16 | 17 | def run(self, target, run_analyser=True): 18 | qasm_data = target.to_qasm(qreg_name="q", creg_name="c") 19 | 20 | start_time = timer() 21 | 22 | # Convert qasm into circuit 23 | graph = zx.sqasm(qasm_data) 24 | 25 | # Perform Clifford optimization of PyZX graph 26 | zx.simplify.clifford_simp(graph) 27 | # Convert optimized graph back to circuit 28 | optimised_circuit = zx.extract_circuit(graph) 29 | 30 | self.execution_time = timer() - start_time 31 | 32 | qasm_data = optimised_circuit.to_qasm() 33 | lines = qasm_data.split("\n") 34 | gate_chain = GateChain.from_qasm_list_of_lines(lines, quantum_hardware=None) # TODO set quantum_hardware 35 | gate_chain.quantum_hardware = self.quantum_hardware 36 | 37 | if run_analyser: 38 | self.analyse(target, gate_chain) 39 | self.analyser_report["Execution Time"] = self.execution_time 40 | return gate_chain 41 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pyzx_full_optimize.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.gate_chain import GateChain 7 | 8 | import pyzx as zx 9 | 10 | _strategy_class_name = "PyzxFullOptimize" 11 | 12 | 13 | class PyzxFullOptimize(CompressionStrategy): 14 | r"""PyZX Full Optimize Strategy 15 | Does not involve ZX calculus (requires CliffordT input gate set) 16 | """ 17 | 18 | def run(self, target, run_analyser=True): 19 | qasm_data = target.to_qasm(qreg_name="q", creg_name="c") 20 | 21 | start_time = timer() 22 | 23 | # Convert qasm into circuit 24 | circuit_object = zx.Circuit(None).from_qasm(qasm_data) 25 | zx.optimize.full_optimize(circuit_object) 26 | 27 | self.execution_time = timer() - start_time 28 | 29 | qasm_data = circuit_object.to_qasm() 30 | lines = qasm_data.split("\n") 31 | gate_chain = GateChain.from_qasm_list_of_lines(lines, quantum_hardware=None) # TODO set quantum_hardware 32 | gate_chain.quantum_hardware = self.quantum_hardware 33 | 34 | if run_analyser: 35 | self.analyse(target, gate_chain) 36 | self.analyser_report["Execution Time"] = self.execution_time 37 | return gate_chain 38 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/pyzx_full_reduce.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_benchmarks.strategies.strategy import CompressionStrategy 6 | from arline_quantum.gate_chain.gate_chain import GateChain 7 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 8 | from arline_quantum.gate_sets.pyzx import PyzxGateSet 9 | import pyzx as zx 10 | 11 | _strategy_class_name = "PyzxFullReduce" 12 | 13 | 14 | class PyzxFullReduce(CompressionStrategy): 15 | r"""PyZX Full Reduce Strategy 16 | """ 17 | 18 | def run(self, target, run_analyser=True): 19 | # Check if all gates in target gate chain are from PyZX gate set 20 | # If not, than perform rebase to PyZX gate set 21 | unique_gates = set([g.gate.name for g in target.chain]) 22 | if not all(g in PyzxGateSet().get_gate_list_str() for g in unique_gates): 23 | gate_chain = ArlineTranslator().rebase_to_pyzx(target) 24 | else: 25 | gate_chain = target 26 | qasm_data = gate_chain.to_qasm(qreg_name="q", creg_name="c") 27 | 28 | start_time = timer() 29 | 30 | # Convert qasm to PyZX circuit object 31 | graph = zx.sqasm(qasm_data) 32 | # Fully fledged optimization of PyZX graph (can change graph structure) 33 | zx.simplify.full_reduce(graph) 34 | # Convert optimized graph back to circuit 35 | optimised_circuit = zx.extract_circuit(graph) 36 | 37 | self.execution_time = timer() - start_time 38 | 39 | qasm_data = optimised_circuit.to_qasm() 40 | lines = qasm_data.split("\n") 41 | gate_chain = GateChain.from_qasm_list_of_lines(lines, quantum_hardware=None) # TODO set quantum_hardware 42 | gate_chain.quantum_hardware = self.quantum_hardware 43 | 44 | if run_analyser: 45 | self.analyse(target, gate_chain) 46 | self.analyser_report["Execution Time"] = self.execution_time 47 | return gate_chain 48 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/qiskit_commutative_cancellation.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | 23 | from qiskit.transpiler.passmanager import PassManager 24 | from qiskit.transpiler.passes import CommutativeCancellation 25 | from qiskit.compiler import transpile 26 | 27 | _strategy_class_name = "QiskitCommutativeCancellation" 28 | 29 | 30 | class QiskitCommutativeCancellation(CompressionStrategy): 31 | r"""Qiskit Commutative Cancellation Strategy 32 | """ 33 | 34 | def __init__( 35 | self, 36 | hardware, 37 | analyser_options={}, 38 | ): 39 | super().__init__(hardware, analyser_options) 40 | 41 | def run(self, target, run_analyser=True): 42 | circuit_object = target.convert_to("qiskit") 43 | start_time = timer() 44 | 45 | pm = PassManager().append(CommutativeCancellation()) 46 | circuit_object = transpile(circuit_object, pass_manager=pm) 47 | 48 | self.execution_time = timer() - start_time 49 | 50 | gate_chain = GateChain.convert_from(circuit_object, format_id="qiskit") 51 | gate_chain.quantum_hardware = self.quantum_hardware 52 | 53 | if run_analyser: 54 | self.analyse(target, gate_chain) 55 | self.analyser_report["Execution Time"] = self.execution_time 56 | return gate_chain 57 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/qiskit_kak_blocks.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from qiskit.transpiler.passmanager import PassManager 21 | from qiskit.transpiler.passes import Collect2qBlocks 22 | from qiskit.transpiler.passes import ConsolidateBlocks 23 | from qiskit.transpiler.passes import UnitarySynthesis 24 | from qiskit.transpiler.passes import Optimize1qGates 25 | 26 | from arline_benchmarks.strategies.strategy import CompressionStrategy 27 | from arline_quantum.gate_chain.gate_chain import GateChain 28 | 29 | from qiskit.compiler import transpile 30 | 31 | _strategy_class_name = "QiskitKakBlocks" 32 | 33 | 34 | class QiskitKakBlocks(CompressionStrategy): 35 | r"""Qiskit kAk 2q blocks Compression Strategy 36 | """ 37 | 38 | def __init__( 39 | self, 40 | hardware, 41 | analyser_options={}, 42 | ): 43 | super().__init__(hardware, analyser_options) 44 | 45 | def run(self, target, run_analyser=True): 46 | circuit_object = target.convert_to("qiskit") 47 | start_time = timer() 48 | basis_gates = ['u1', 'u2', 'u3', 'cx'] 49 | passes = [ 50 | Collect2qBlocks(), 51 | ConsolidateBlocks(basis_gates=basis_gates), 52 | UnitarySynthesis(basis_gates), 53 | Optimize1qGates(basis_gates), 54 | ] 55 | pm = PassManager().append(passes) 56 | circuit_object = transpile(circuit_object, pass_manager=pm) 57 | 58 | self.execution_time = timer() - start_time 59 | 60 | gate_chain = GateChain.convert_from(circuit_object, format_id="qiskit") 61 | gate_chain.quantum_hardware = self.quantum_hardware 62 | 63 | if run_analyser: 64 | self.analyse(target, gate_chain) 65 | self.analyser_report["Execution Time"] = self.execution_time 66 | return gate_chain 67 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/qiskit_rebase.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | from timeit import default_timer as timer 18 | 19 | from arline_benchmarks.strategies.strategy import RebaseStrategy 20 | from arline_quantum.gate_chain.gate_chain import GateChain 21 | 22 | from qiskit.transpiler.passes import BasisTranslator 23 | from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel 24 | from qiskit.converters import circuit_to_dag, dag_to_circuit 25 | 26 | _strategy_class_name = "QiskitRebase" 27 | 28 | 29 | class QiskitRebase(RebaseStrategy): 30 | r"""Qiskit Gate Rebase Strategy 31 | """ 32 | 33 | def run(self, target, run_analyser=True): 34 | original_circuit = target.convert_to("qiskit") 35 | 36 | start_time = timer() 37 | 38 | # Get gate set of quantum hardware object (target gate set) 39 | gate_set = self.quantum_hardware.gate_set 40 | basis_gates = list(gate_set.gates_by_qasm_name.keys()) 41 | # Core part of rebase transformation 42 | dag = circuit_to_dag(original_circuit) 43 | rebased_dag = BasisTranslator(sel, basis_gates).run(dag) 44 | optimised_circuit = dag_to_circuit(rebased_dag) 45 | 46 | self.execution_time = timer() - start_time 47 | 48 | gate_chain = GateChain.convert_from(optimised_circuit, format_id="qiskit") 49 | gate_chain.quantum_hardware = self.quantum_hardware 50 | 51 | if run_analyser: 52 | self.analyse(target, gate_chain) 53 | self.analyser_report["Execution Time"] = self.execution_time 54 | return gate_chain 55 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/qiskit_transpile.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import CompressionStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | 23 | from qiskit.compiler import transpile 24 | 25 | _strategy_class_name = "QiskitTranspile" 26 | 27 | 28 | class QiskitTranspile(CompressionStrategy): 29 | r"""Qiskit Transpile Strategy 30 | """ 31 | 32 | def __init__( 33 | self, 34 | hardware, 35 | seed_transpiler=1, 36 | optimization_level=3, 37 | routing_method='sabre', 38 | layout_method='sabre', 39 | analyser_options={}, 40 | ): 41 | super().__init__(hardware, analyser_options) 42 | self.qiskit_hardware = self.quantum_hardware.convert_to_qiskit_hardware() 43 | self.seed_transpiler = seed_transpiler 44 | self.optimization_level = optimization_level 45 | self.routing_method = routing_method 46 | self.layout_method = layout_method 47 | 48 | def run(self, target, run_analyser=True): 49 | circuit_object = target.convert_to("qiskit") 50 | start_time = timer() 51 | circuit_object = transpile( 52 | circuit_object, 53 | backend=self.qiskit_hardware, 54 | seed_transpiler=self.seed_transpiler, 55 | optimization_level=self.optimization_level, 56 | routing_method=self.routing_method, 57 | layout_method=self.layout_method 58 | ) 59 | 60 | self.execution_time = timer() - start_time 61 | 62 | gate_chain = GateChain.convert_from(circuit_object, format_id="qiskit") 63 | gate_chain.quantum_hardware = self.quantum_hardware 64 | 65 | if run_analyser: 66 | self.analyse(target, gate_chain) 67 | self.analyser_report["Execution Time"] = self.execution_time 68 | return gate_chain 69 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/qiskit_unroll.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from timeit import default_timer as timer 19 | 20 | from arline_benchmarks.strategies.strategy import RebaseStrategy 21 | from arline_quantum.gate_chain.gate_chain import GateChain 22 | 23 | from qiskit.transpiler.passes import Unroll3qOrMore 24 | from qiskit.converters import circuit_to_dag, dag_to_circuit 25 | 26 | _strategy_class_name = "QiskitUnroll" 27 | 28 | 29 | class QiskitUnroll(RebaseStrategy): 30 | r"""Qiskit Unroll Strategy 31 | """ 32 | 33 | def __init__( 34 | self, 35 | hardware, 36 | analyser_options={}, 37 | ): 38 | super().__init__(hardware, analyser_options) 39 | self.qiskit_hardware = self.quantum_hardware.convert_to_qiskit_hardware() 40 | 41 | def run(self, target, run_analyser=True): 42 | circuit_object = target.convert_to("qiskit") 43 | 44 | start_time = timer() 45 | 46 | if target.quantum_hardware.num_qubits < 3: 47 | pass 48 | else: 49 | unrolled_dag = Unroll3qOrMore().run(circuit_to_dag(circuit_object)) 50 | circuit_object = dag_to_circuit(unrolled_dag) 51 | self.execution_time = timer() - start_time 52 | 53 | gate_chain = GateChain.convert_from(circuit_object, 'qiskit') 54 | gate_chain.quantum_hardware = self.quantum_hardware 55 | 56 | if run_analyser: 57 | self.analyse(target, gate_chain) 58 | self.analyser_report["Execution Time"] = self.execution_time 59 | return gate_chain 60 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/strategy.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import importlib 19 | from contextlib import suppress 20 | 21 | from arline_benchmarks.metrics.gate_chain_analyser import GateChainTransformAnalyser, SynthesisAnalyser 22 | from arline_quantum.hardware import hardware_by_name 23 | from arline_quantum.utils.fidelity import statevector_fidelity 24 | 25 | 26 | class Strategy: 27 | r"""Abstract Class for Strategy 28 | """ 29 | 30 | def __init__( 31 | self, 32 | analyser_options={} 33 | ): 34 | self.execution_time = 0 35 | self.analyser = None 36 | self.analyser_report = None 37 | self.analyser_options = analyser_options 38 | 39 | def run(self, target, run_analyser=True): 40 | raise NotImplementedError() 41 | 42 | def analyse(self, target, result): 43 | raise NotImplementedError() 44 | 45 | @staticmethod 46 | def from_config(cfg): 47 | strategy_name = cfg["strategy"] 48 | m = importlib.import_module("arline_benchmarks.strategies." + strategy_name) 49 | strategy_class = getattr(m, m._strategy_class_name) 50 | strategy_cfg = cfg["args"] 51 | return strategy_class(**strategy_cfg) 52 | 53 | def __str__(self): 54 | s = self.__class__.__name__ 55 | with suppress(AttributeError): 56 | s += f" ({self.quantum_hardware.name})" 57 | return s 58 | 59 | 60 | class CircuitProcessingStrategy(Strategy): 61 | r"""Abstract Class for Connectivity Mapping Strategy 62 | """ 63 | 64 | def __init__( 65 | self, 66 | hardware, 67 | analyser_options={} 68 | ): 69 | super().__init__(analyser_options) 70 | self.quantum_hardware = hardware_by_name(hardware) 71 | 72 | def analyse(self, target, result): 73 | if self.analyser is None: 74 | self.analyser = GateChainTransformAnalyser(**self.analyser_options) 75 | self.analyser_report = self.analyser.run_all(target, result) 76 | 77 | 78 | class MappingStrategy(Strategy): 79 | r"""Abstract Class for Connectivity Mapping Strategy 80 | """ 81 | 82 | def __init__( 83 | self, 84 | hardware, 85 | analyser_options={} 86 | ): 87 | super().__init__(analyser_options) 88 | self.quantum_hardware = hardware_by_name(hardware) 89 | 90 | def analyse(self, target, result): 91 | if self.analyser is None: 92 | self.analyser = GateChainTransformAnalyser(**self.analyser_options) 93 | self.analyser_report = self.analyser.run_all(target, result) 94 | 95 | 96 | class RebaseStrategy(Strategy): 97 | r"""Abstract Class for Gate Set Rebase Strategy 98 | """ 99 | 100 | def __init__( 101 | self, 102 | hardware, 103 | analyser_options={} 104 | ): 105 | super().__init__(analyser_options) 106 | self.quantum_hardware = hardware_by_name(hardware) 107 | 108 | def analyse(self, target, result): 109 | if self.analyser is None: 110 | self.analyser = GateChainTransformAnalyser(**self.analyser_options) 111 | self.analyser_report = self.analyser.run_all(target, result) 112 | 113 | 114 | class CompressionStrategy(Strategy): 115 | r"""Abstract Class for Compression Strategy 116 | """ 117 | 118 | def __init__( 119 | self, 120 | hardware, 121 | analyser_options={} 122 | ): 123 | super().__init__(analyser_options) 124 | self.quantum_hardware = hardware_by_name(hardware) 125 | 126 | def analyse(self, target, result): 127 | if self.analyser is None: 128 | self.analyser = GateChainTransformAnalyser(**self.analyser_options) 129 | self.analyser_report = self.analyser.run_all(target, result) 130 | 131 | 132 | class QSPStrategy(Strategy): 133 | r"""Abstract Class for QSP Strategy 134 | """ 135 | 136 | def __init__( 137 | self, 138 | hardware, 139 | analyser_options={} 140 | ): 141 | super().__init__(analyser_options) 142 | self.quantum_hardware = hardware_by_name(hardware) 143 | 144 | def analyse(self, target, result): 145 | if self.analyser is None: 146 | 147 | def fidelity_function(t, u): 148 | return statevector_fidelity(t, u) 149 | 150 | self.analyser = SynthesisAnalyser(fidelity_function) 151 | self.analyser_report = self.analyser.run_all(target, result) 152 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/target_analysis.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | from arline_benchmarks.strategies.strategy import Strategy 19 | from arline_benchmarks.metrics.gate_chain_analyser import GateChainTransformAnalyser, SynthesisAnalyser 20 | from arline_quantum.gate_chain.gate_chain import GateChain 21 | 22 | 23 | _strategy_class_name = "TargetAnalysis" 24 | 25 | 26 | class TargetAnalysis(Strategy): 27 | r"""Dummy strategy to run analyser 28 | """ 29 | 30 | def __init__( 31 | self, 32 | analyser_options={} 33 | ): 34 | super().__init__(analyser_options) 35 | 36 | def run(self, target, run_analyser=True): 37 | if run_analyser: 38 | self.analyse(target, target) 39 | self.analyser_report["Execution Time"] = 0 40 | return target 41 | 42 | def analyse(self, target, result): 43 | if self.analyser is None: 44 | if isinstance(target, GateChain): 45 | self.analyser = GateChainTransformAnalyser() 46 | else: 47 | self.analyser = SynthesisAnalyser() 48 | self.analyser_report = self.analyser.run_all(target, result) 49 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/voqc_1q_gates_cancel.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_quantum.gate_chain.gate_chain import GateChain 6 | from arline_benchmarks.strategies.strategy import CompressionStrategy 7 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 8 | 9 | from qiskit import QuantumCircuit 10 | 11 | from pyvoqc.voqc import VOQC 12 | from pyvoqc.qiskit.voqc_optimization import QisVOQC 13 | from qiskit.transpiler import PassManager 14 | 15 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 16 | from arline_quantum.gate_sets.voqc import VoqcGateSet 17 | 18 | 19 | _strategy_class_name = "VoqcSingleQubitCancel" 20 | 21 | 22 | class VoqcSingleQubitCancel(CompressionStrategy): 23 | r"""VOQC Single-Qubit Gates Cancellation Strategy 24 | """ 25 | 26 | def run(self, target, run_analyser=True): 27 | # Perform preliminrary rebase to comply with supported VOQC gates 28 | unique_gates = set([g.gate.name for g in target.chain]) 29 | if not all(g in VoqcGateSet().get_gate_list_str() for g in unique_gates): 30 | gate_chain = ArlineTranslator().rebase_to_voqc(target) 31 | else: 32 | gate_chain = target 33 | circuit_object = gate_chain.convert_to("qiskit") 34 | 35 | start_time = timer() 36 | 37 | # Append VOQC pass without argument to the Pass Manager 38 | pm = PassManager() 39 | pm.append(QisVOQC(["cancel_single_qubit_gates"])) 40 | new_circuit = pm.run(circuit_object) 41 | 42 | self.execution_time = timer() - start_time 43 | 44 | gate_chain = GateChain.convert_from(new_circuit, "qiskit") 45 | gate_chain.quantum_hardware = self.quantum_hardware 46 | 47 | if run_analyser: 48 | self.analyse(target, gate_chain) 49 | self.analyser_report["Execution Time"] = self.execution_time 50 | return gate_chain 51 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/voqc_2q_gates_cancel.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_quantum.gate_chain.gate_chain import GateChain 6 | from arline_benchmarks.strategies.strategy import CompressionStrategy 7 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 8 | 9 | from qiskit import QuantumCircuit 10 | 11 | from pyvoqc.voqc import VOQC 12 | from pyvoqc.qiskit.voqc_optimization import QisVOQC 13 | from qiskit.transpiler import PassManager 14 | 15 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 16 | from arline_quantum.gate_sets.voqc import VoqcGateSet 17 | 18 | _strategy_class_name = "VoqcTwoQubitCancel" 19 | 20 | 21 | class VoqcTwoQubitCancel(CompressionStrategy): 22 | r"""VOQC Two-Qubit Gates Cancellation Strategy 23 | """ 24 | 25 | def run(self, target, run_analyser=True): 26 | # Perform preliminrary rebase to comply with supported VOQC gates 27 | unique_gates = set([g.gate.name for g in target.chain]) 28 | if not all(g in VoqcGateSet().get_gate_list_str() for g in unique_gates): 29 | gate_chain = ArlineTranslator().rebase_to_voqc(target) 30 | else: 31 | gate_chain = target 32 | circuit_object = gate_chain.convert_to("qiskit") 33 | 34 | start_time = timer() 35 | 36 | # Append VOQC pass without argument to the Pass Manager 37 | pm = PassManager() 38 | pm.append(QisVOQC(["cancel_two_qubit_gates"])) 39 | new_circuit = pm.run(circuit_object) 40 | 41 | self.execution_time = timer() - start_time 42 | 43 | gate_chain = GateChain.convert_from(new_circuit, "qiskit") 44 | gate_chain.quantum_hardware = self.quantum_hardware 45 | 46 | if run_analyser: 47 | self.analyse(target, gate_chain) 48 | self.analyser_report["Execution Time"] = self.execution_time 49 | return gate_chain 50 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/voqc_hadamard_reduction.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_quantum.gate_chain.gate_chain import GateChain 6 | from arline_benchmarks.strategies.strategy import CompressionStrategy 7 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 8 | 9 | from qiskit import QuantumCircuit 10 | 11 | from pyvoqc.voqc import VOQC 12 | from pyvoqc.qiskit.voqc_optimization import QisVOQC 13 | from qiskit.transpiler import PassManager 14 | 15 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 16 | from arline_quantum.gate_sets.voqc import VoqcGateSet 17 | 18 | _strategy_class_name = "VoqcHadamardReduction" 19 | 20 | 21 | class VoqcHadamardReduction(CompressionStrategy): 22 | r"""VOQC Hadamard Reduction Strategy 23 | """ 24 | 25 | def run(self, target, run_analyser=True): 26 | # Perform preliminrary rebase to comply with supported VOQC gates 27 | unique_gates = set([g.gate.name for g in target.chain]) 28 | if not all(g in VoqcGateSet().get_gate_list_str() for g in unique_gates): 29 | gate_chain = ArlineTranslator().rebase_to_voqc(target) 30 | else: 31 | gate_chain = target 32 | circuit_object = gate_chain.convert_to("qiskit") 33 | 34 | start_time = timer() 35 | 36 | # Append VOQC pass without argument to the Pass Manager 37 | pm = PassManager() 38 | pm.append(QisVOQC(["hadamard_reduction"])) 39 | new_circuit = pm.run(circuit_object) 40 | 41 | self.execution_time = timer() - start_time 42 | 43 | gate_chain = GateChain.convert_from(new_circuit, "qiskit") 44 | gate_chain.quantum_hardware = self.quantum_hardware 45 | 46 | if run_analyser: 47 | self.analyse(target, gate_chain) 48 | self.analyser_report["Execution Time"] = self.execution_time 49 | return gate_chain 50 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/voqc_merge_rotations.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_quantum.gate_chain.gate_chain import GateChain 6 | from arline_benchmarks.strategies.strategy import CompressionStrategy 7 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 8 | 9 | from qiskit import QuantumCircuit 10 | 11 | from pyvoqc.voqc import VOQC 12 | from pyvoqc.qiskit.voqc_optimization import QisVOQC 13 | from qiskit.transpiler import PassManager 14 | 15 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 16 | from arline_quantum.gate_sets.voqc import VoqcGateSet 17 | 18 | _strategy_class_name = "VoqcMergeRotations" 19 | 20 | 21 | class VoqcMergeRotations(CompressionStrategy): 22 | r"""VOQC Merge Single-Qubit Rotations Strategy 23 | """ 24 | 25 | def run(self, target, run_analyser=True): 26 | # Perform preliminrary rebase to comply with supported VOQC gates 27 | unique_gates = set([g.gate.name for g in target.chain]) 28 | if not all(g in VoqcGateSet().get_gate_list_str() for g in unique_gates): 29 | gate_chain = ArlineTranslator().rebase_to_voqc(target) 30 | else: 31 | gate_chain = target 32 | circuit_object = gate_chain.convert_to("qiskit") 33 | 34 | start_time = timer() 35 | 36 | # Append VOQC pass without argument to the Pass Manager 37 | pm = PassManager() 38 | pm.append(QisVOQC(["merge_rotations"])) 39 | new_circuit = pm.run(circuit_object) 40 | 41 | self.execution_time = timer() - start_time 42 | 43 | gate_chain = GateChain.convert_from(new_circuit, "qiskit") 44 | gate_chain.quantum_hardware = self.quantum_hardware 45 | 46 | if run_analyser: 47 | self.analyse(target, gate_chain) 48 | self.analyser_report["Execution Time"] = self.execution_time 49 | return gate_chain 50 | -------------------------------------------------------------------------------- /arline_benchmarks/strategies/voqc_not_propagation.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019-2022 Turation Ltd 2 | 3 | from timeit import default_timer as timer 4 | 5 | from arline_quantum.gate_chain.gate_chain import GateChain 6 | from arline_benchmarks.strategies.strategy import CompressionStrategy 7 | from arline_quantum.gate_chain.converters import PytketGateChainConverter 8 | 9 | from qiskit import QuantumCircuit 10 | 11 | from pyvoqc.voqc import VOQC 12 | from pyvoqc.qiskit.voqc_optimization import QisVOQC 13 | from qiskit.transpiler import PassManager 14 | 15 | from arline_quantum.gate_chain.basis_translator import ArlineTranslator 16 | from arline_quantum.gate_sets.voqc import VoqcGateSet 17 | 18 | _strategy_class_name = "Voqc" 19 | 20 | 21 | class VoqcNotPropagation(CompressionStrategy): 22 | r"""VOQC Not Propagation Optimisation Strategy 23 | """ 24 | 25 | def run(self, target, run_analyser=True): 26 | # Perform preliminrary rebase to comply with supported VOQC gates 27 | unique_gates = set([g.gate.name for g in target.chain]) 28 | if not all(g in VoqcGateSet().get_gate_list_str() for g in unique_gates): 29 | gate_chain = ArlineTranslator().rebase_to_voqc(target) 30 | else: 31 | gate_chain = target 32 | circuit_object = gate_chain.convert_to("qiskit") 33 | 34 | start_time = timer() 35 | 36 | # Append VOQC pass without argument to the Pass Manager 37 | pm = PassManager() 38 | pm.append(QisVOQC(["not_propagation"])) 39 | new_circuit = pm.run(circuit_object) 40 | 41 | self.execution_time = timer() - start_time 42 | 43 | gate_chain = GateChain.convert_from(new_circuit, "qiskit") 44 | gate_chain.quantum_hardware = self.quantum_hardware 45 | 46 | if run_analyser: 47 | self.analyse(target, gate_chain) 48 | self.analyser_report["Execution Time"] = self.execution_time 49 | return gate_chain 50 | -------------------------------------------------------------------------------- /arline_benchmarks/targets/__init__.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /arline_benchmarks/targets/target.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | import itertools 19 | from glob import glob 20 | from os.path import basename, join, splitext, expandvars 21 | 22 | import numpy as np 23 | 24 | from arline_quantum.gate_chain.gate_chain import GateChain 25 | from arline_quantum.gates.u3 import U3 26 | 27 | from arline_quantum.hardware import hardware_by_name 28 | 29 | 30 | def limit_targets_number(f): 31 | r"""Limits total number of generated circuits (`<=number`), `f` is the target generator 32 | """ 33 | 34 | def g(self): 35 | if "number" not in self._cfg or not self._cfg["number"] is None and self._cfg["number"] < 0: 36 | return f(self) 37 | 38 | try: 39 | self.cnt 40 | except AttributeError: 41 | self.cnt = 0 42 | 43 | if self._cfg["number"] is None: 44 | if self.cnt >= self.number: 45 | raise StopIteration() 46 | elif self.cnt >= self._cfg["number"]: 47 | raise StopIteration() 48 | self.cnt += 1 49 | 50 | return f(self) 51 | 52 | return g 53 | 54 | 55 | class Target: 56 | r"""Abstract class for benchmarking target circuits 57 | """ 58 | 59 | def __init__(self, config={}): 60 | self._cfg = config 61 | if "seed" in self._cfg: 62 | self.seed(self._cfg["seed"]) # TODO test 63 | 64 | def __iter__(self): 65 | return self 66 | 67 | def __next__(self): 68 | return self.next() 69 | 70 | def next(self): 71 | raise NotImplementedError() 72 | 73 | def seed(self, seed=None): 74 | raise NotImplementedError() 75 | 76 | @staticmethod 77 | def from_config(config): 78 | target_classes = [RandomChainTarget, QasmChainTarget] 79 | 80 | cl = {(c.task, c.algo,): c for c in target_classes}[(config["task"], config["algo"])] 81 | return cl(config) 82 | 83 | 84 | class GateChainTarget(Target): 85 | 86 | task = "circuit_transformation" 87 | 88 | 89 | class RandomChainTarget(GateChainTarget): 90 | r"""Random Chain Target Class 91 | 92 | **Description:** 93 | Generates random quantum circuits (gate chains) from a discrete gateset 94 | Supports two types of gate probability distribution in the target generator: 95 | 96 | * Uniform distribution (all gate placements have equal probabilities) 97 | * Custom probability distribution for each gate placement [e.g. action_probabilities = {"CX_01": 0.1, "CX_10": 0.2, "S_0": 0.5, "S_1": 0.2}] 98 | 99 | Additional optional arguments: 100 | * Depth limit - maximum depth of generated circuits 101 | * Two qubit gate count upper bound 102 | * Two qubit gate count lower bound 103 | * Total gate count (gate_chain_length) 104 | """ 105 | algo = "random_chain" 106 | 107 | def __init__(self, config): 108 | super().__init__(config=config) 109 | self._quantum_hardware = hardware_by_name(self._cfg["hardware"]) 110 | self._actions = [] 111 | self.two_qubit_actions = [] 112 | self.id = 0 113 | 114 | try: 115 | self.depth_limit = self._cfg["depth_limit"] 116 | except KeyError: 117 | self.depth_limit = None 118 | 119 | try: 120 | self.two_qubit_gate_num_upper_bound = self._cfg["two_qubit_gate_num_upper_bound"] 121 | except KeyError: 122 | self.two_qubit_gate_num_upper_bound = None 123 | 124 | try: 125 | self.two_qubit_gate_num_lower_bound = self._cfg["two_qubit_gate_num_lower_bound"] 126 | assert self.two_qubit_gate_num_upper_bound is not None 127 | assert self.two_qubit_gate_num_upper_bound - self.two_qubit_gate_num_lower_bound >= 0 128 | except KeyError: 129 | self.two_qubit_gate_num_lower_bound = 0 130 | 131 | if self.two_qubit_gate_num_upper_bound is not None and self.depth_limit is not None: 132 | raise Exception("'two_qubit_gate_num_upper_bound' and 'depth_limit' can not be specified simultaneously.") 133 | 134 | for gate_name, gate in self._quantum_hardware.gate_set.gates_by_name.items(): 135 | for appy_to_qubits in itertools.permutations(range(self._quantum_hardware.num_qubits), gate.num_qubits): 136 | if len(appy_to_qubits) > 1: 137 | if not self._quantum_hardware.qubit_connectivity.check_connection(appy_to_qubits): 138 | continue 139 | 140 | action_name = gate_name + ("_{}" * len(appy_to_qubits)).format(*appy_to_qubits) 141 | 142 | if gate.num_qubits == 2 and self.two_qubit_gate_num_upper_bound is not None: 143 | self.two_qubit_actions.append((action_name, gate, appy_to_qubits)) 144 | continue 145 | 146 | self._actions.append((action_name, gate, appy_to_qubits)) 147 | 148 | self._actions_probabilities = None 149 | try: 150 | if self._cfg["gate_distribution"] == "uniform": 151 | pass 152 | else: 153 | self._actions_probabilities = [None for a in self._actions] 154 | 155 | actions_per_gate = {} 156 | for action_name, gate, appy_to_qubits in self._actions: 157 | try: 158 | actions_per_gate[gate.__name__] += 1 159 | except KeyError: 160 | actions_per_gate[gate.__name__] = 1 161 | 162 | total_p = 0 163 | for i, a in enumerate(self._actions): 164 | action_name, gate, appy_to_qubits = a 165 | 166 | try: 167 | p = self._cfg["gate_distribution"][gate.__name__] / actions_per_gate[gate.__name__] 168 | self._actions_probabilities[i] = p 169 | total_p += p 170 | except KeyError: 171 | pass 172 | 173 | empty_p_cnt = sum([1 if p is None else 0 for p in self._actions_probabilities]) 174 | 175 | if total_p > 1: 176 | raise Exception("The sum of gates probabilities must be <= 1") 177 | if total_p != 1: 178 | if empty_p_cnt == 0: 179 | raise Exception("The sum of gates probabilities must be == 1") 180 | else: 181 | self._actions_probabilities = [ 182 | p if p is not None else (1 - total_p) / empty_p_cnt for p in self._actions_probabilities 183 | ] 184 | 185 | #print("Actions probabilities:\n", {a[0]: p for a, p in zip(self._actions, self._actions_probabilities)}) 186 | 187 | if self.two_qubit_gate_num_upper_bound is not None and self._actions_probabilities is not None: 188 | raise Exception( 189 | "'two_qubit_gate_num_upper_bound' and 'gate_distribution' can not be specified simultaneously." 190 | ) 191 | 192 | except KeyError: 193 | pass 194 | 195 | @limit_targets_number 196 | def next(self): 197 | self.id += 1 198 | chain = GateChain(self._quantum_hardware) 199 | 200 | if "chain_length" in self._cfg: 201 | chain_length = self._cfg["chain_length"] 202 | elif "chain_length_max" in self._cfg: 203 | max_length = self._cfg["chain_length_max"] 204 | min_length = 0 205 | if "chain_length_max" in self._cfg: 206 | min_length = self._cfg["chain_length_min"] 207 | chain_length = self.np_random.randint(min_length, max_length + 1) 208 | else: 209 | raise Exception("No chain_length specified") 210 | 211 | two_qubit_pos = [] 212 | if self.two_qubit_gate_num_upper_bound is not None: 213 | two_qubit_number = self.np_random.randint( 214 | self.two_qubit_gate_num_lower_bound, self.two_qubit_gate_num_upper_bound + 1 215 | ) 216 | two_qubit_pos = self.np_random.choice(range(chain_length), two_qubit_number, replace=False) 217 | 218 | for i in range(chain_length): 219 | if self.depth_limit is not None and chain.get_depth() >= self.depth_limit: 220 | break 221 | 222 | if i in two_qubit_pos: 223 | action = self.np_random.choice(range(len(self.two_qubit_actions))) 224 | action_name, gate_class, appy_to_qubits = self.two_qubit_actions[action] 225 | else: 226 | action = self.np_random.choice(range(len(self._actions)), p=self._actions_probabilities) 227 | action_name, gate_class, appy_to_qubits = self._actions[action] 228 | 229 | if gate_class == U3: 230 | # Haar random unitary rotation matrix 231 | theta = np.arccos(self.np_random.uniform(low=-1, high=1)) 232 | phi, lmbda = self.np_random.uniform(low=0, high=2 * np.pi, size=2) 233 | gate = gate_class(theta, phi, lmbda) 234 | elif gate_class.num_angles > 0: 235 | # Uniform rotation [0, 2*pi] 236 | angles = self.np_random.uniform(low=0, high=2 * np.pi, size=gate_class.num_angles) 237 | gate = gate_class(*angles) 238 | else: 239 | gate = gate_class() 240 | chain.add_gate(gate, appy_to_qubits) 241 | 242 | return chain, self.id 243 | 244 | def seed(self, seed=None): 245 | self.np_random = np.random.RandomState(seed) 246 | 247 | 248 | class QasmChainTarget(GateChainTarget): 249 | r"""Qasm Chain Target Class 250 | 251 | **Description:** 252 | Generates target gate chains from a .qasm dataset. 253 | """ 254 | algo = "qasm" # TODO algo -> type 255 | 256 | def __init__(self, config): 257 | super().__init__(config=config) 258 | if isinstance(self._cfg["qasm_path"], str): 259 | self.qasm_list = glob(join(expandvars(self._cfg["qasm_path"]), "*.qasm")) 260 | if isinstance(self._cfg["qasm_path"], list): 261 | self.qasm_list = [expandvars(f) for f in self._cfg["qasm_path"]] 262 | self.number = len(self.qasm_list) 263 | self.qasm_number = 0 264 | 265 | @limit_targets_number 266 | def next(self): 267 | qasm_f = self.qasm_list[self.qasm_number] 268 | chain = GateChain.from_qasm(qasm_f, None) 269 | self.qasm_number += 1 270 | return chain, splitext(basename(qasm_f))[0] 271 | 272 | def __str__(self): 273 | return "From QASM {}".format(self.qasm_list[self.qasm_number]) 274 | -------------------------------------------------------------------------------- /circuits/C17_204.qasm: -------------------------------------------------------------------------------- 1 | OPENQASM 2.0; 2 | include "qelib1.inc"; 3 | qreg q[16]; 4 | creg c[16]; 5 | cx q[5],q[1]; 6 | cx q[5],q[0]; 7 | h q[1]; 8 | t q[3]; 9 | t q[6]; 10 | t q[1]; 11 | cx q[6],q[3]; 12 | cx q[1],q[6]; 13 | cx q[3],q[1]; 14 | tdg q[6]; 15 | cx q[3],q[6]; 16 | tdg q[3]; 17 | tdg q[6]; 18 | t q[1]; 19 | cx q[1],q[6]; 20 | cx q[3],q[1]; 21 | cx q[6],q[3]; 22 | h q[1]; 23 | h q[6]; 24 | t q[5]; 25 | t q[4]; 26 | t q[6]; 27 | cx q[4],q[5]; 28 | cx q[6],q[4]; 29 | cx q[5],q[6]; 30 | tdg q[4]; 31 | cx q[5],q[4]; 32 | tdg q[5]; 33 | tdg q[4]; 34 | t q[6]; 35 | cx q[6],q[4]; 36 | cx q[5],q[6]; 37 | cx q[4],q[5]; 38 | h q[6]; 39 | h q[1]; 40 | t q[3]; 41 | t q[6]; 42 | t q[1]; 43 | cx q[6],q[3]; 44 | cx q[1],q[6]; 45 | cx q[3],q[1]; 46 | tdg q[6]; 47 | cx q[3],q[6]; 48 | tdg q[3]; 49 | tdg q[6]; 50 | t q[1]; 51 | cx q[1],q[6]; 52 | cx q[3],q[1]; 53 | cx q[6],q[3]; 54 | h q[1]; 55 | h q[6]; 56 | t q[5]; 57 | t q[4]; 58 | t q[6]; 59 | cx q[4],q[5]; 60 | cx q[6],q[4]; 61 | cx q[5],q[6]; 62 | tdg q[4]; 63 | cx q[5],q[4]; 64 | tdg q[5]; 65 | tdg q[4]; 66 | t q[6]; 67 | cx q[6],q[4]; 68 | cx q[5],q[6]; 69 | cx q[4],q[5]; 70 | h q[6]; 71 | h q[0]; 72 | t q[3]; 73 | t q[6]; 74 | t q[0]; 75 | cx q[6],q[3]; 76 | cx q[0],q[6]; 77 | cx q[3],q[0]; 78 | tdg q[6]; 79 | cx q[3],q[6]; 80 | tdg q[3]; 81 | tdg q[6]; 82 | t q[0]; 83 | cx q[0],q[6]; 84 | cx q[3],q[0]; 85 | cx q[6],q[3]; 86 | h q[0]; 87 | h q[6]; 88 | t q[5]; 89 | t q[4]; 90 | t q[6]; 91 | cx q[4],q[5]; 92 | cx q[6],q[4]; 93 | cx q[5],q[6]; 94 | tdg q[4]; 95 | cx q[5],q[4]; 96 | tdg q[5]; 97 | tdg q[4]; 98 | t q[6]; 99 | cx q[6],q[4]; 100 | cx q[5],q[6]; 101 | cx q[4],q[5]; 102 | h q[6]; 103 | h q[0]; 104 | t q[3]; 105 | t q[6]; 106 | t q[0]; 107 | cx q[6],q[3]; 108 | cx q[0],q[6]; 109 | cx q[3],q[0]; 110 | tdg q[6]; 111 | cx q[3],q[6]; 112 | tdg q[3]; 113 | tdg q[6]; 114 | t q[0]; 115 | cx q[0],q[6]; 116 | cx q[3],q[0]; 117 | cx q[6],q[3]; 118 | h q[0]; 119 | h q[6]; 120 | t q[5]; 121 | t q[4]; 122 | t q[6]; 123 | cx q[4],q[5]; 124 | cx q[6],q[4]; 125 | cx q[5],q[6]; 126 | tdg q[4]; 127 | cx q[5],q[4]; 128 | tdg q[5]; 129 | tdg q[4]; 130 | t q[6]; 131 | cx q[6],q[4]; 132 | cx q[5],q[6]; 133 | cx q[4],q[5]; 134 | h q[6]; 135 | h q[1]; 136 | t q[3]; 137 | t q[2]; 138 | t q[1]; 139 | cx q[2],q[3]; 140 | cx q[1],q[2]; 141 | cx q[3],q[1]; 142 | tdg q[2]; 143 | cx q[3],q[2]; 144 | tdg q[3]; 145 | tdg q[2]; 146 | t q[1]; 147 | cx q[1],q[2]; 148 | cx q[3],q[1]; 149 | cx q[2],q[3]; 150 | h q[1]; 151 | h q[2]; 152 | t q[4]; 153 | t q[0]; 154 | t q[2]; 155 | cx q[0],q[4]; 156 | cx q[2],q[0]; 157 | cx q[4],q[2]; 158 | tdg q[0]; 159 | cx q[4],q[0]; 160 | tdg q[4]; 161 | tdg q[0]; 162 | t q[2]; 163 | cx q[2],q[0]; 164 | cx q[4],q[2]; 165 | cx q[0],q[4]; 166 | h q[2]; 167 | h q[0]; 168 | t q[6]; 169 | t q[5]; 170 | t q[0]; 171 | cx q[5],q[6]; 172 | cx q[0],q[5]; 173 | cx q[6],q[0]; 174 | tdg q[5]; 175 | cx q[6],q[5]; 176 | tdg q[6]; 177 | tdg q[5]; 178 | t q[0]; 179 | cx q[0],q[5]; 180 | cx q[6],q[0]; 181 | cx q[5],q[6]; 182 | h q[0]; 183 | h q[2]; 184 | t q[4]; 185 | t q[0]; 186 | t q[2]; 187 | cx q[0],q[4]; 188 | cx q[2],q[0]; 189 | cx q[4],q[2]; 190 | tdg q[0]; 191 | cx q[4],q[0]; 192 | tdg q[4]; 193 | tdg q[0]; 194 | t q[2]; 195 | cx q[2],q[0]; 196 | cx q[4],q[2]; 197 | cx q[0],q[4]; 198 | h q[2]; 199 | h q[1]; 200 | t q[3]; 201 | t q[2]; 202 | t q[1]; 203 | cx q[2],q[3]; 204 | cx q[1],q[2]; 205 | cx q[3],q[1]; 206 | tdg q[2]; 207 | cx q[3],q[2]; 208 | tdg q[3]; 209 | tdg q[2]; 210 | t q[1]; 211 | cx q[1],q[2]; 212 | cx q[3],q[1]; 213 | cx q[2],q[3]; 214 | h q[1]; 215 | h q[2]; 216 | t q[4]; 217 | t q[0]; 218 | t q[2]; 219 | cx q[0],q[4]; 220 | cx q[2],q[0]; 221 | cx q[4],q[2]; 222 | tdg q[0]; 223 | cx q[4],q[0]; 224 | tdg q[4]; 225 | tdg q[0]; 226 | t q[2]; 227 | cx q[2],q[0]; 228 | cx q[4],q[2]; 229 | cx q[0],q[4]; 230 | h q[2]; 231 | h q[0]; 232 | t q[6]; 233 | t q[5]; 234 | t q[0]; 235 | cx q[5],q[6]; 236 | cx q[0],q[5]; 237 | cx q[6],q[0]; 238 | tdg q[5]; 239 | cx q[6],q[5]; 240 | tdg q[6]; 241 | tdg q[5]; 242 | t q[0]; 243 | cx q[0],q[5]; 244 | cx q[6],q[0]; 245 | cx q[5],q[6]; 246 | h q[0]; 247 | h q[2]; 248 | t q[4]; 249 | t q[0]; 250 | t q[2]; 251 | cx q[0],q[4]; 252 | cx q[2],q[0]; 253 | cx q[4],q[2]; 254 | tdg q[0]; 255 | cx q[4],q[0]; 256 | tdg q[4]; 257 | tdg q[0]; 258 | t q[2]; 259 | cx q[2],q[0]; 260 | cx q[4],q[2]; 261 | cx q[0],q[4]; 262 | h q[2]; 263 | x q[5]; 264 | h q[1]; 265 | t q[4]; 266 | t q[3]; 267 | t q[1]; 268 | cx q[3],q[4]; 269 | cx q[1],q[3]; 270 | cx q[4],q[1]; 271 | tdg q[3]; 272 | cx q[4],q[3]; 273 | tdg q[4]; 274 | tdg q[3]; 275 | t q[1]; 276 | cx q[1],q[3]; 277 | cx q[4],q[1]; 278 | cx q[3],q[4]; 279 | h q[1]; 280 | h q[3]; 281 | t q[6]; 282 | t q[5]; 283 | t q[3]; 284 | cx q[5],q[6]; 285 | cx q[3],q[5]; 286 | cx q[6],q[3]; 287 | tdg q[5]; 288 | cx q[6],q[5]; 289 | tdg q[6]; 290 | tdg q[5]; 291 | t q[3]; 292 | cx q[3],q[5]; 293 | cx q[6],q[3]; 294 | cx q[5],q[6]; 295 | h q[3]; 296 | h q[1]; 297 | t q[4]; 298 | t q[3]; 299 | t q[1]; 300 | cx q[3],q[4]; 301 | cx q[1],q[3]; 302 | cx q[4],q[1]; 303 | tdg q[3]; 304 | cx q[4],q[3]; 305 | tdg q[4]; 306 | tdg q[3]; 307 | t q[1]; 308 | cx q[1],q[3]; 309 | cx q[4],q[1]; 310 | cx q[3],q[4]; 311 | h q[1]; 312 | h q[3]; 313 | t q[6]; 314 | t q[5]; 315 | t q[3]; 316 | cx q[5],q[6]; 317 | cx q[3],q[5]; 318 | cx q[6],q[3]; 319 | tdg q[5]; 320 | cx q[6],q[5]; 321 | tdg q[6]; 322 | tdg q[5]; 323 | t q[3]; 324 | cx q[3],q[5]; 325 | cx q[6],q[3]; 326 | cx q[5],q[6]; 327 | h q[3]; 328 | h q[0]; 329 | t q[5]; 330 | t q[2]; 331 | t q[0]; 332 | cx q[2],q[5]; 333 | cx q[0],q[2]; 334 | cx q[5],q[0]; 335 | tdg q[2]; 336 | cx q[5],q[2]; 337 | tdg q[5]; 338 | tdg q[2]; 339 | t q[0]; 340 | cx q[0],q[2]; 341 | cx q[5],q[0]; 342 | cx q[2],q[5]; 343 | h q[0]; 344 | h q[0]; 345 | t q[2]; 346 | t q[6]; 347 | t q[0]; 348 | cx q[6],q[2]; 349 | cx q[0],q[6]; 350 | cx q[2],q[0]; 351 | tdg q[6]; 352 | cx q[2],q[6]; 353 | tdg q[2]; 354 | tdg q[6]; 355 | t q[0]; 356 | cx q[0],q[6]; 357 | cx q[2],q[0]; 358 | cx q[6],q[2]; 359 | h q[0]; 360 | h q[6]; 361 | t q[3]; 362 | t q[1]; 363 | t q[6]; 364 | cx q[1],q[3]; 365 | cx q[6],q[1]; 366 | cx q[3],q[6]; 367 | tdg q[1]; 368 | cx q[3],q[1]; 369 | tdg q[3]; 370 | tdg q[1]; 371 | t q[6]; 372 | cx q[6],q[1]; 373 | cx q[3],q[6]; 374 | cx q[1],q[3]; 375 | h q[6]; 376 | h q[1]; 377 | t q[5]; 378 | t q[4]; 379 | t q[1]; 380 | cx q[4],q[5]; 381 | cx q[1],q[4]; 382 | cx q[5],q[1]; 383 | tdg q[4]; 384 | cx q[5],q[4]; 385 | tdg q[5]; 386 | tdg q[4]; 387 | t q[1]; 388 | cx q[1],q[4]; 389 | cx q[5],q[1]; 390 | cx q[4],q[5]; 391 | h q[1]; 392 | h q[6]; 393 | t q[3]; 394 | t q[1]; 395 | t q[6]; 396 | cx q[1],q[3]; 397 | cx q[6],q[1]; 398 | cx q[3],q[6]; 399 | tdg q[1]; 400 | cx q[3],q[1]; 401 | tdg q[3]; 402 | tdg q[1]; 403 | t q[6]; 404 | cx q[6],q[1]; 405 | cx q[3],q[6]; 406 | cx q[1],q[3]; 407 | h q[6]; 408 | h q[0]; 409 | t q[2]; 410 | t q[6]; 411 | t q[0]; 412 | cx q[6],q[2]; 413 | cx q[0],q[6]; 414 | cx q[2],q[0]; 415 | tdg q[6]; 416 | cx q[2],q[6]; 417 | tdg q[2]; 418 | tdg q[6]; 419 | t q[0]; 420 | cx q[0],q[6]; 421 | cx q[2],q[0]; 422 | cx q[6],q[2]; 423 | h q[0]; 424 | h q[6]; 425 | t q[3]; 426 | t q[1]; 427 | t q[6]; 428 | cx q[1],q[3]; 429 | cx q[6],q[1]; 430 | cx q[3],q[6]; 431 | tdg q[1]; 432 | cx q[3],q[1]; 433 | tdg q[3]; 434 | tdg q[1]; 435 | t q[6]; 436 | cx q[6],q[1]; 437 | cx q[3],q[6]; 438 | cx q[1],q[3]; 439 | h q[6]; 440 | h q[1]; 441 | t q[5]; 442 | t q[4]; 443 | t q[1]; 444 | cx q[4],q[5]; 445 | cx q[1],q[4]; 446 | cx q[5],q[1]; 447 | tdg q[4]; 448 | cx q[5],q[4]; 449 | tdg q[5]; 450 | tdg q[4]; 451 | t q[1]; 452 | cx q[1],q[4]; 453 | cx q[5],q[1]; 454 | cx q[4],q[5]; 455 | h q[1]; 456 | h q[6]; 457 | t q[3]; 458 | t q[1]; 459 | t q[6]; 460 | cx q[1],q[3]; 461 | cx q[6],q[1]; 462 | cx q[3],q[6]; 463 | tdg q[1]; 464 | cx q[3],q[1]; 465 | tdg q[3]; 466 | tdg q[1]; 467 | t q[6]; 468 | cx q[6],q[1]; 469 | cx q[3],q[6]; 470 | cx q[1],q[3]; 471 | h q[6]; 472 | -------------------------------------------------------------------------------- /circuits/mini-alu_167.qasm: -------------------------------------------------------------------------------- 1 | OPENQASM 2.0; 2 | include "qelib1.inc"; 3 | qreg q[16]; 4 | creg c[16]; 5 | h q[1]; 6 | t q[0]; 7 | t q[3]; 8 | t q[1]; 9 | cx q[3],q[0]; 10 | cx q[1],q[3]; 11 | cx q[0],q[1]; 12 | tdg q[3]; 13 | cx q[0],q[3]; 14 | tdg q[0]; 15 | tdg q[3]; 16 | t q[1]; 17 | cx q[1],q[3]; 18 | cx q[0],q[1]; 19 | cx q[3],q[0]; 20 | h q[1]; 21 | h q[2]; 22 | t q[3]; 23 | t q[4]; 24 | t q[2]; 25 | cx q[4],q[3]; 26 | cx q[2],q[4]; 27 | cx q[3],q[2]; 28 | tdg q[4]; 29 | cx q[3],q[4]; 30 | tdg q[3]; 31 | tdg q[4]; 32 | t q[2]; 33 | cx q[2],q[4]; 34 | cx q[3],q[2]; 35 | cx q[4],q[3]; 36 | h q[2]; 37 | h q[4]; 38 | t q[0]; 39 | t q[1]; 40 | t q[4]; 41 | cx q[1],q[0]; 42 | cx q[4],q[1]; 43 | cx q[0],q[4]; 44 | tdg q[1]; 45 | cx q[0],q[1]; 46 | tdg q[0]; 47 | tdg q[1]; 48 | t q[4]; 49 | cx q[4],q[1]; 50 | cx q[0],q[4]; 51 | cx q[1],q[0]; 52 | h q[4]; 53 | h q[2]; 54 | t q[3]; 55 | t q[4]; 56 | t q[2]; 57 | cx q[4],q[3]; 58 | cx q[2],q[4]; 59 | cx q[3],q[2]; 60 | tdg q[4]; 61 | cx q[3],q[4]; 62 | tdg q[3]; 63 | tdg q[4]; 64 | t q[2]; 65 | cx q[2],q[4]; 66 | cx q[3],q[2]; 67 | cx q[4],q[3]; 68 | h q[2]; 69 | h q[4]; 70 | t q[0]; 71 | t q[1]; 72 | t q[4]; 73 | cx q[1],q[0]; 74 | cx q[4],q[1]; 75 | cx q[0],q[4]; 76 | tdg q[1]; 77 | cx q[0],q[1]; 78 | tdg q[0]; 79 | tdg q[1]; 80 | t q[4]; 81 | cx q[4],q[1]; 82 | cx q[0],q[4]; 83 | cx q[1],q[0]; 84 | h q[4]; 85 | h q[0]; 86 | t q[3]; 87 | t q[4]; 88 | t q[0]; 89 | cx q[4],q[3]; 90 | cx q[0],q[4]; 91 | cx q[3],q[0]; 92 | tdg q[4]; 93 | cx q[3],q[4]; 94 | tdg q[3]; 95 | tdg q[4]; 96 | t q[0]; 97 | cx q[0],q[4]; 98 | cx q[3],q[0]; 99 | cx q[4],q[3]; 100 | h q[0]; 101 | h q[4]; 102 | t q[1]; 103 | t q[2]; 104 | t q[4]; 105 | cx q[2],q[1]; 106 | cx q[4],q[2]; 107 | cx q[1],q[4]; 108 | tdg q[2]; 109 | cx q[1],q[2]; 110 | tdg q[1]; 111 | tdg q[2]; 112 | t q[4]; 113 | cx q[4],q[2]; 114 | cx q[1],q[4]; 115 | cx q[2],q[1]; 116 | h q[4]; 117 | h q[0]; 118 | t q[3]; 119 | t q[4]; 120 | t q[0]; 121 | cx q[4],q[3]; 122 | cx q[0],q[4]; 123 | cx q[3],q[0]; 124 | tdg q[4]; 125 | cx q[3],q[4]; 126 | tdg q[3]; 127 | tdg q[4]; 128 | t q[0]; 129 | cx q[0],q[4]; 130 | cx q[3],q[0]; 131 | cx q[4],q[3]; 132 | h q[0]; 133 | h q[4]; 134 | t q[1]; 135 | t q[2]; 136 | t q[4]; 137 | cx q[2],q[1]; 138 | cx q[4],q[2]; 139 | cx q[1],q[4]; 140 | tdg q[2]; 141 | cx q[1],q[2]; 142 | tdg q[1]; 143 | tdg q[2]; 144 | t q[4]; 145 | cx q[4],q[2]; 146 | cx q[1],q[4]; 147 | cx q[2],q[1]; 148 | h q[4]; 149 | h q[1]; 150 | t q[3]; 151 | t q[4]; 152 | t q[1]; 153 | cx q[4],q[3]; 154 | cx q[1],q[4]; 155 | cx q[3],q[1]; 156 | tdg q[4]; 157 | cx q[3],q[4]; 158 | tdg q[3]; 159 | tdg q[4]; 160 | t q[1]; 161 | cx q[1],q[4]; 162 | cx q[3],q[1]; 163 | cx q[4],q[3]; 164 | h q[1]; 165 | h q[4]; 166 | t q[0]; 167 | t q[2]; 168 | t q[4]; 169 | cx q[2],q[0]; 170 | cx q[4],q[2]; 171 | cx q[0],q[4]; 172 | tdg q[2]; 173 | cx q[0],q[2]; 174 | tdg q[0]; 175 | tdg q[2]; 176 | t q[4]; 177 | cx q[4],q[2]; 178 | cx q[0],q[4]; 179 | cx q[2],q[0]; 180 | h q[4]; 181 | h q[1]; 182 | t q[3]; 183 | t q[4]; 184 | t q[1]; 185 | cx q[4],q[3]; 186 | cx q[1],q[4]; 187 | cx q[3],q[1]; 188 | tdg q[4]; 189 | cx q[3],q[4]; 190 | tdg q[3]; 191 | tdg q[4]; 192 | t q[1]; 193 | cx q[1],q[4]; 194 | cx q[3],q[1]; 195 | cx q[4],q[3]; 196 | h q[1]; 197 | h q[4]; 198 | t q[0]; 199 | t q[2]; 200 | t q[4]; 201 | cx q[2],q[0]; 202 | cx q[4],q[2]; 203 | cx q[0],q[4]; 204 | tdg q[2]; 205 | cx q[0],q[2]; 206 | tdg q[0]; 207 | tdg q[2]; 208 | t q[4]; 209 | cx q[4],q[2]; 210 | cx q[0],q[4]; 211 | cx q[2],q[0]; 212 | h q[4]; 213 | h q[3]; 214 | t q[1]; 215 | t q[2]; 216 | t q[3]; 217 | cx q[2],q[1]; 218 | cx q[3],q[2]; 219 | cx q[1],q[3]; 220 | tdg q[2]; 221 | cx q[1],q[2]; 222 | tdg q[1]; 223 | tdg q[2]; 224 | t q[3]; 225 | cx q[3],q[2]; 226 | cx q[1],q[3]; 227 | cx q[2],q[1]; 228 | h q[3]; 229 | h q[2]; 230 | t q[3]; 231 | t q[4]; 232 | t q[2]; 233 | cx q[4],q[3]; 234 | cx q[2],q[4]; 235 | cx q[3],q[2]; 236 | tdg q[4]; 237 | cx q[3],q[4]; 238 | tdg q[3]; 239 | tdg q[4]; 240 | t q[2]; 241 | cx q[2],q[4]; 242 | cx q[3],q[2]; 243 | cx q[4],q[3]; 244 | h q[2]; 245 | h q[4]; 246 | t q[0]; 247 | t q[1]; 248 | t q[4]; 249 | cx q[1],q[0]; 250 | cx q[4],q[1]; 251 | cx q[0],q[4]; 252 | tdg q[1]; 253 | cx q[0],q[1]; 254 | tdg q[0]; 255 | tdg q[1]; 256 | t q[4]; 257 | cx q[4],q[1]; 258 | cx q[0],q[4]; 259 | cx q[1],q[0]; 260 | h q[4]; 261 | h q[2]; 262 | t q[3]; 263 | t q[4]; 264 | t q[2]; 265 | cx q[4],q[3]; 266 | cx q[2],q[4]; 267 | cx q[3],q[2]; 268 | tdg q[4]; 269 | cx q[3],q[4]; 270 | tdg q[3]; 271 | tdg q[4]; 272 | t q[2]; 273 | cx q[2],q[4]; 274 | cx q[3],q[2]; 275 | cx q[4],q[3]; 276 | h q[2]; 277 | h q[4]; 278 | t q[0]; 279 | t q[1]; 280 | t q[4]; 281 | cx q[1],q[0]; 282 | cx q[4],q[1]; 283 | cx q[0],q[4]; 284 | tdg q[1]; 285 | cx q[0],q[1]; 286 | tdg q[0]; 287 | tdg q[1]; 288 | t q[4]; 289 | cx q[4],q[1]; 290 | cx q[0],q[4]; 291 | cx q[1],q[0]; 292 | h q[4]; 293 | -------------------------------------------------------------------------------- /circuits/one-two-three-v0_97.qasm: -------------------------------------------------------------------------------- 1 | OPENQASM 2.0; 2 | include "qelib1.inc"; 3 | qreg q[16]; 4 | creg c[16]; 5 | cx q[3],q[2]; 6 | cx q[4],q[1]; 7 | h q[0]; 8 | t q[1]; 9 | t q[4]; 10 | t q[0]; 11 | cx q[4],q[1]; 12 | cx q[0],q[4]; 13 | cx q[1],q[0]; 14 | tdg q[4]; 15 | cx q[1],q[4]; 16 | tdg q[1]; 17 | tdg q[4]; 18 | t q[0]; 19 | cx q[0],q[4]; 20 | cx q[1],q[0]; 21 | cx q[4],q[1]; 22 | h q[0]; 23 | h q[3]; 24 | t q[4]; 25 | t q[2]; 26 | t q[3]; 27 | cx q[2],q[4]; 28 | cx q[3],q[2]; 29 | cx q[4],q[3]; 30 | tdg q[2]; 31 | cx q[4],q[2]; 32 | tdg q[4]; 33 | tdg q[2]; 34 | t q[3]; 35 | cx q[3],q[2]; 36 | cx q[4],q[3]; 37 | cx q[2],q[4]; 38 | h q[3]; 39 | h q[2]; 40 | t q[0]; 41 | t q[1]; 42 | t q[2]; 43 | cx q[1],q[0]; 44 | cx q[2],q[1]; 45 | cx q[0],q[2]; 46 | tdg q[1]; 47 | cx q[0],q[1]; 48 | tdg q[0]; 49 | tdg q[1]; 50 | t q[2]; 51 | cx q[2],q[1]; 52 | cx q[0],q[2]; 53 | cx q[1],q[0]; 54 | h q[2]; 55 | h q[3]; 56 | t q[4]; 57 | t q[2]; 58 | t q[3]; 59 | cx q[2],q[4]; 60 | cx q[3],q[2]; 61 | cx q[4],q[3]; 62 | tdg q[2]; 63 | cx q[4],q[2]; 64 | tdg q[4]; 65 | tdg q[2]; 66 | t q[3]; 67 | cx q[3],q[2]; 68 | cx q[4],q[3]; 69 | cx q[2],q[4]; 70 | h q[3]; 71 | h q[2]; 72 | t q[0]; 73 | t q[1]; 74 | t q[2]; 75 | cx q[1],q[0]; 76 | cx q[2],q[1]; 77 | cx q[0],q[2]; 78 | tdg q[1]; 79 | cx q[0],q[1]; 80 | tdg q[0]; 81 | tdg q[1]; 82 | t q[2]; 83 | cx q[2],q[1]; 84 | cx q[0],q[2]; 85 | cx q[1],q[0]; 86 | h q[2]; 87 | h q[3]; 88 | t q[1]; 89 | t q[2]; 90 | t q[3]; 91 | cx q[2],q[1]; 92 | cx q[3],q[2]; 93 | cx q[1],q[3]; 94 | tdg q[2]; 95 | cx q[1],q[2]; 96 | tdg q[1]; 97 | tdg q[2]; 98 | t q[3]; 99 | cx q[3],q[2]; 100 | cx q[1],q[3]; 101 | cx q[2],q[1]; 102 | h q[3]; 103 | h q[1]; 104 | t q[4]; 105 | t q[2]; 106 | t q[1]; 107 | cx q[2],q[4]; 108 | cx q[1],q[2]; 109 | cx q[4],q[1]; 110 | tdg q[2]; 111 | cx q[4],q[2]; 112 | tdg q[4]; 113 | tdg q[2]; 114 | t q[1]; 115 | cx q[1],q[2]; 116 | cx q[4],q[1]; 117 | cx q[2],q[4]; 118 | h q[1]; 119 | h q[2]; 120 | t q[0]; 121 | t q[3]; 122 | t q[2]; 123 | cx q[3],q[0]; 124 | cx q[2],q[3]; 125 | cx q[0],q[2]; 126 | tdg q[3]; 127 | cx q[0],q[3]; 128 | tdg q[0]; 129 | tdg q[3]; 130 | t q[2]; 131 | cx q[2],q[3]; 132 | cx q[0],q[2]; 133 | cx q[3],q[0]; 134 | h q[2]; 135 | h q[1]; 136 | t q[4]; 137 | t q[2]; 138 | t q[1]; 139 | cx q[2],q[4]; 140 | cx q[1],q[2]; 141 | cx q[4],q[1]; 142 | tdg q[2]; 143 | cx q[4],q[2]; 144 | tdg q[4]; 145 | tdg q[2]; 146 | t q[1]; 147 | cx q[1],q[2]; 148 | cx q[4],q[1]; 149 | cx q[2],q[4]; 150 | h q[1]; 151 | h q[2]; 152 | t q[0]; 153 | t q[3]; 154 | t q[2]; 155 | cx q[3],q[0]; 156 | cx q[2],q[3]; 157 | cx q[0],q[2]; 158 | tdg q[3]; 159 | cx q[0],q[3]; 160 | tdg q[0]; 161 | tdg q[3]; 162 | t q[2]; 163 | cx q[2],q[3]; 164 | cx q[0],q[2]; 165 | cx q[3],q[0]; 166 | h q[2]; 167 | h q[3]; 168 | t q[1]; 169 | t q[2]; 170 | t q[3]; 171 | cx q[2],q[1]; 172 | cx q[3],q[2]; 173 | cx q[1],q[3]; 174 | tdg q[2]; 175 | cx q[1],q[2]; 176 | tdg q[1]; 177 | tdg q[2]; 178 | t q[3]; 179 | cx q[3],q[2]; 180 | cx q[1],q[3]; 181 | cx q[2],q[1]; 182 | h q[3]; 183 | h q[2]; 184 | t q[4]; 185 | t q[1]; 186 | t q[2]; 187 | cx q[1],q[4]; 188 | cx q[2],q[1]; 189 | cx q[4],q[2]; 190 | tdg q[1]; 191 | cx q[4],q[1]; 192 | tdg q[4]; 193 | tdg q[1]; 194 | t q[2]; 195 | cx q[2],q[1]; 196 | cx q[4],q[2]; 197 | cx q[1],q[4]; 198 | h q[2]; 199 | h q[1]; 200 | t q[0]; 201 | t q[3]; 202 | t q[1]; 203 | cx q[3],q[0]; 204 | cx q[1],q[3]; 205 | cx q[0],q[1]; 206 | tdg q[3]; 207 | cx q[0],q[3]; 208 | tdg q[0]; 209 | tdg q[3]; 210 | t q[1]; 211 | cx q[1],q[3]; 212 | cx q[0],q[1]; 213 | cx q[3],q[0]; 214 | h q[1]; 215 | h q[2]; 216 | t q[4]; 217 | t q[1]; 218 | t q[2]; 219 | cx q[1],q[4]; 220 | cx q[2],q[1]; 221 | cx q[4],q[2]; 222 | tdg q[1]; 223 | cx q[4],q[1]; 224 | tdg q[4]; 225 | tdg q[1]; 226 | t q[2]; 227 | cx q[2],q[1]; 228 | cx q[4],q[2]; 229 | cx q[1],q[4]; 230 | h q[2]; 231 | h q[1]; 232 | t q[0]; 233 | t q[3]; 234 | t q[1]; 235 | cx q[3],q[0]; 236 | cx q[1],q[3]; 237 | cx q[0],q[1]; 238 | tdg q[3]; 239 | cx q[0],q[3]; 240 | tdg q[0]; 241 | tdg q[3]; 242 | t q[1]; 243 | cx q[1],q[3]; 244 | cx q[0],q[1]; 245 | cx q[3],q[0]; 246 | h q[1]; 247 | h q[1]; 248 | t q[2]; 249 | t q[3]; 250 | t q[1]; 251 | cx q[3],q[2]; 252 | cx q[1],q[3]; 253 | cx q[2],q[1]; 254 | tdg q[3]; 255 | cx q[2],q[3]; 256 | tdg q[2]; 257 | tdg q[3]; 258 | t q[1]; 259 | cx q[1],q[3]; 260 | cx q[2],q[1]; 261 | cx q[3],q[2]; 262 | h q[1]; 263 | h q[4]; 264 | t q[0]; 265 | t q[3]; 266 | t q[4]; 267 | cx q[3],q[0]; 268 | cx q[4],q[3]; 269 | cx q[0],q[4]; 270 | tdg q[3]; 271 | cx q[0],q[3]; 272 | tdg q[0]; 273 | tdg q[3]; 274 | t q[4]; 275 | cx q[4],q[3]; 276 | cx q[0],q[4]; 277 | cx q[3],q[0]; 278 | h q[4]; 279 | h q[3]; 280 | t q[1]; 281 | t q[2]; 282 | t q[3]; 283 | cx q[2],q[1]; 284 | cx q[3],q[2]; 285 | cx q[1],q[3]; 286 | tdg q[2]; 287 | cx q[1],q[2]; 288 | tdg q[1]; 289 | tdg q[2]; 290 | t q[3]; 291 | cx q[3],q[2]; 292 | cx q[1],q[3]; 293 | cx q[2],q[1]; 294 | h q[3]; 295 | -------------------------------------------------------------------------------- /circuits/rd53_135.qasm: -------------------------------------------------------------------------------- 1 | OPENQASM 2.0; 2 | include "qelib1.inc"; 3 | qreg q[16]; 4 | creg c[16]; 5 | cx q[1],q[5]; 6 | cx q[2],q[1]; 7 | cx q[1],q[0]; 8 | h q[5]; 9 | t q[0]; 10 | t q[1]; 11 | t q[5]; 12 | cx q[1],q[0]; 13 | cx q[5],q[1]; 14 | cx q[0],q[5]; 15 | tdg q[1]; 16 | cx q[0],q[1]; 17 | tdg q[0]; 18 | tdg q[1]; 19 | t q[5]; 20 | cx q[5],q[1]; 21 | cx q[0],q[5]; 22 | cx q[1],q[0]; 23 | h q[5]; 24 | cx q[0],q[5]; 25 | cx q[0],q[3]; 26 | cx q[0],q[4]; 27 | h q[5]; 28 | t q[3]; 29 | t q[4]; 30 | t q[5]; 31 | cx q[4],q[3]; 32 | cx q[5],q[4]; 33 | cx q[3],q[5]; 34 | tdg q[4]; 35 | cx q[3],q[4]; 36 | tdg q[3]; 37 | tdg q[4]; 38 | t q[5]; 39 | cx q[5],q[4]; 40 | cx q[3],q[5]; 41 | cx q[4],q[3]; 42 | h q[5]; 43 | h q[0]; 44 | t q[3]; 45 | t q[4]; 46 | t q[0]; 47 | cx q[4],q[3]; 48 | cx q[0],q[4]; 49 | cx q[3],q[0]; 50 | tdg q[4]; 51 | cx q[3],q[4]; 52 | tdg q[3]; 53 | tdg q[4]; 54 | t q[0]; 55 | cx q[0],q[4]; 56 | cx q[3],q[0]; 57 | cx q[4],q[3]; 58 | h q[0]; 59 | h q[6]; 60 | t q[2]; 61 | t q[5]; 62 | t q[6]; 63 | cx q[5],q[2]; 64 | cx q[6],q[5]; 65 | cx q[2],q[6]; 66 | tdg q[5]; 67 | cx q[2],q[5]; 68 | tdg q[2]; 69 | tdg q[5]; 70 | t q[6]; 71 | cx q[6],q[5]; 72 | cx q[2],q[6]; 73 | cx q[5],q[2]; 74 | h q[6]; 75 | h q[5]; 76 | t q[0]; 77 | t q[1]; 78 | t q[5]; 79 | cx q[1],q[0]; 80 | cx q[5],q[1]; 81 | cx q[0],q[5]; 82 | tdg q[1]; 83 | cx q[0],q[1]; 84 | tdg q[0]; 85 | tdg q[1]; 86 | t q[5]; 87 | cx q[5],q[1]; 88 | cx q[0],q[5]; 89 | cx q[1],q[0]; 90 | h q[5]; 91 | h q[6]; 92 | t q[2]; 93 | t q[5]; 94 | t q[6]; 95 | cx q[5],q[2]; 96 | cx q[6],q[5]; 97 | cx q[2],q[6]; 98 | tdg q[5]; 99 | cx q[2],q[5]; 100 | tdg q[2]; 101 | tdg q[5]; 102 | t q[6]; 103 | cx q[6],q[5]; 104 | cx q[2],q[6]; 105 | cx q[5],q[2]; 106 | h q[6]; 107 | h q[5]; 108 | t q[0]; 109 | t q[1]; 110 | t q[5]; 111 | cx q[1],q[0]; 112 | cx q[5],q[1]; 113 | cx q[0],q[5]; 114 | tdg q[1]; 115 | cx q[0],q[1]; 116 | tdg q[0]; 117 | tdg q[1]; 118 | t q[5]; 119 | cx q[5],q[1]; 120 | cx q[0],q[5]; 121 | cx q[1],q[0]; 122 | h q[5]; 123 | h q[5]; 124 | t q[1]; 125 | t q[2]; 126 | t q[5]; 127 | cx q[2],q[1]; 128 | cx q[5],q[2]; 129 | cx q[1],q[5]; 130 | tdg q[2]; 131 | cx q[1],q[2]; 132 | tdg q[1]; 133 | tdg q[2]; 134 | t q[5]; 135 | cx q[5],q[2]; 136 | cx q[1],q[5]; 137 | cx q[2],q[1]; 138 | h q[5]; 139 | h q[6]; 140 | t q[0]; 141 | t q[2]; 142 | t q[6]; 143 | cx q[2],q[0]; 144 | cx q[6],q[2]; 145 | cx q[0],q[6]; 146 | tdg q[2]; 147 | cx q[0],q[2]; 148 | tdg q[0]; 149 | tdg q[2]; 150 | t q[6]; 151 | cx q[6],q[2]; 152 | cx q[0],q[6]; 153 | cx q[2],q[0]; 154 | h q[6]; 155 | h q[0]; 156 | t q[3]; 157 | t q[4]; 158 | t q[0]; 159 | cx q[4],q[3]; 160 | cx q[0],q[4]; 161 | cx q[3],q[0]; 162 | tdg q[4]; 163 | cx q[3],q[4]; 164 | tdg q[3]; 165 | tdg q[4]; 166 | t q[0]; 167 | cx q[0],q[4]; 168 | cx q[3],q[0]; 169 | cx q[4],q[3]; 170 | h q[0]; 171 | cx q[3],q[0]; 172 | h q[6]; 173 | t q[4]; 174 | t q[5]; 175 | t q[6]; 176 | cx q[5],q[4]; 177 | cx q[6],q[5]; 178 | cx q[4],q[6]; 179 | tdg q[5]; 180 | cx q[4],q[5]; 181 | tdg q[4]; 182 | tdg q[5]; 183 | t q[6]; 184 | cx q[6],q[5]; 185 | cx q[4],q[6]; 186 | cx q[5],q[4]; 187 | h q[6]; 188 | h q[5]; 189 | t q[3]; 190 | t q[2]; 191 | t q[5]; 192 | cx q[2],q[3]; 193 | cx q[5],q[2]; 194 | cx q[3],q[5]; 195 | tdg q[2]; 196 | cx q[3],q[2]; 197 | tdg q[3]; 198 | tdg q[2]; 199 | t q[5]; 200 | cx q[5],q[2]; 201 | cx q[3],q[5]; 202 | cx q[2],q[3]; 203 | h q[5]; 204 | h q[2]; 205 | t q[0]; 206 | t q[1]; 207 | t q[2]; 208 | cx q[1],q[0]; 209 | cx q[2],q[1]; 210 | cx q[0],q[2]; 211 | tdg q[1]; 212 | cx q[0],q[1]; 213 | tdg q[0]; 214 | tdg q[1]; 215 | t q[2]; 216 | cx q[2],q[1]; 217 | cx q[0],q[2]; 218 | cx q[1],q[0]; 219 | h q[2]; 220 | h q[5]; 221 | t q[3]; 222 | t q[2]; 223 | t q[5]; 224 | cx q[2],q[3]; 225 | cx q[5],q[2]; 226 | cx q[3],q[5]; 227 | tdg q[2]; 228 | cx q[3],q[2]; 229 | tdg q[3]; 230 | tdg q[2]; 231 | t q[5]; 232 | cx q[5],q[2]; 233 | cx q[3],q[5]; 234 | cx q[2],q[3]; 235 | h q[5]; 236 | h q[6]; 237 | t q[4]; 238 | t q[5]; 239 | t q[6]; 240 | cx q[5],q[4]; 241 | cx q[6],q[5]; 242 | cx q[4],q[6]; 243 | tdg q[5]; 244 | cx q[4],q[5]; 245 | tdg q[4]; 246 | tdg q[5]; 247 | t q[6]; 248 | cx q[6],q[5]; 249 | cx q[4],q[6]; 250 | cx q[5],q[4]; 251 | h q[6]; 252 | h q[5]; 253 | t q[3]; 254 | t q[2]; 255 | t q[5]; 256 | cx q[2],q[3]; 257 | cx q[5],q[2]; 258 | cx q[3],q[5]; 259 | tdg q[2]; 260 | cx q[3],q[2]; 261 | tdg q[3]; 262 | tdg q[2]; 263 | t q[5]; 264 | cx q[5],q[2]; 265 | cx q[3],q[5]; 266 | cx q[2],q[3]; 267 | h q[5]; 268 | h q[2]; 269 | t q[0]; 270 | t q[1]; 271 | t q[2]; 272 | cx q[1],q[0]; 273 | cx q[2],q[1]; 274 | cx q[0],q[2]; 275 | tdg q[1]; 276 | cx q[0],q[1]; 277 | tdg q[0]; 278 | tdg q[1]; 279 | t q[2]; 280 | cx q[2],q[1]; 281 | cx q[0],q[2]; 282 | cx q[1],q[0]; 283 | h q[2]; 284 | h q[5]; 285 | t q[3]; 286 | t q[2]; 287 | t q[5]; 288 | cx q[2],q[3]; 289 | cx q[5],q[2]; 290 | cx q[3],q[5]; 291 | tdg q[2]; 292 | cx q[3],q[2]; 293 | tdg q[3]; 294 | tdg q[2]; 295 | t q[5]; 296 | cx q[5],q[2]; 297 | cx q[3],q[5]; 298 | cx q[2],q[3]; 299 | h q[5]; 300 | cx q[0],q[4]; 301 | -------------------------------------------------------------------------------- /circuits/sym9_146.qasm: -------------------------------------------------------------------------------- 1 | OPENQASM 2.0; 2 | include "qelib1.inc"; 3 | qreg q[16]; 4 | creg c[16]; 5 | h q[9]; 6 | t q[0]; 7 | t q[1]; 8 | t q[9]; 9 | cx q[1],q[0]; 10 | cx q[9],q[1]; 11 | cx q[0],q[9]; 12 | tdg q[1]; 13 | cx q[0],q[1]; 14 | tdg q[0]; 15 | tdg q[1]; 16 | t q[9]; 17 | cx q[9],q[1]; 18 | cx q[0],q[9]; 19 | cx q[1],q[0]; 20 | h q[9]; 21 | cx q[0],q[1]; 22 | h q[10]; 23 | t q[2]; 24 | t q[9]; 25 | t q[10]; 26 | cx q[9],q[2]; 27 | cx q[10],q[9]; 28 | cx q[2],q[10]; 29 | tdg q[9]; 30 | cx q[2],q[9]; 31 | tdg q[2]; 32 | tdg q[9]; 33 | t q[10]; 34 | cx q[10],q[9]; 35 | cx q[2],q[10]; 36 | cx q[9],q[2]; 37 | h q[10]; 38 | h q[9]; 39 | t q[1]; 40 | t q[2]; 41 | t q[9]; 42 | cx q[2],q[1]; 43 | cx q[9],q[2]; 44 | cx q[1],q[9]; 45 | tdg q[2]; 46 | cx q[1],q[2]; 47 | tdg q[1]; 48 | tdg q[2]; 49 | t q[9]; 50 | cx q[9],q[2]; 51 | cx q[1],q[9]; 52 | cx q[2],q[1]; 53 | h q[9]; 54 | cx q[1],q[2]; 55 | h q[11]; 56 | t q[3]; 57 | t q[10]; 58 | t q[11]; 59 | cx q[10],q[3]; 60 | cx q[11],q[10]; 61 | cx q[3],q[11]; 62 | tdg q[10]; 63 | cx q[3],q[10]; 64 | tdg q[3]; 65 | tdg q[10]; 66 | t q[11]; 67 | cx q[11],q[10]; 68 | cx q[3],q[11]; 69 | cx q[10],q[3]; 70 | h q[11]; 71 | h q[10]; 72 | t q[3]; 73 | t q[9]; 74 | t q[10]; 75 | cx q[9],q[3]; 76 | cx q[10],q[9]; 77 | cx q[3],q[10]; 78 | tdg q[9]; 79 | cx q[3],q[9]; 80 | tdg q[3]; 81 | tdg q[9]; 82 | t q[10]; 83 | cx q[10],q[9]; 84 | cx q[3],q[10]; 85 | cx q[9],q[3]; 86 | h q[10]; 87 | h q[9]; 88 | t q[2]; 89 | t q[3]; 90 | t q[9]; 91 | cx q[3],q[2]; 92 | cx q[9],q[3]; 93 | cx q[2],q[9]; 94 | tdg q[3]; 95 | cx q[2],q[3]; 96 | tdg q[2]; 97 | tdg q[3]; 98 | t q[9]; 99 | cx q[9],q[3]; 100 | cx q[2],q[9]; 101 | cx q[3],q[2]; 102 | h q[9]; 103 | cx q[2],q[3]; 104 | h q[11]; 105 | t q[4]; 106 | t q[10]; 107 | t q[11]; 108 | cx q[10],q[4]; 109 | cx q[11],q[10]; 110 | cx q[4],q[11]; 111 | tdg q[10]; 112 | cx q[4],q[10]; 113 | tdg q[4]; 114 | tdg q[10]; 115 | t q[11]; 116 | cx q[11],q[10]; 117 | cx q[4],q[11]; 118 | cx q[10],q[4]; 119 | h q[11]; 120 | h q[10]; 121 | t q[4]; 122 | t q[9]; 123 | t q[10]; 124 | cx q[9],q[4]; 125 | cx q[10],q[9]; 126 | cx q[4],q[10]; 127 | tdg q[9]; 128 | cx q[4],q[9]; 129 | tdg q[4]; 130 | tdg q[9]; 131 | t q[10]; 132 | cx q[10],q[9]; 133 | cx q[4],q[10]; 134 | cx q[9],q[4]; 135 | h q[10]; 136 | h q[9]; 137 | t q[3]; 138 | t q[4]; 139 | t q[9]; 140 | cx q[4],q[3]; 141 | cx q[9],q[4]; 142 | cx q[3],q[9]; 143 | tdg q[4]; 144 | cx q[3],q[4]; 145 | tdg q[3]; 146 | tdg q[4]; 147 | t q[9]; 148 | cx q[9],q[4]; 149 | cx q[3],q[9]; 150 | cx q[4],q[3]; 151 | h q[9]; 152 | cx q[3],q[4]; 153 | h q[11]; 154 | t q[5]; 155 | t q[10]; 156 | t q[11]; 157 | cx q[10],q[5]; 158 | cx q[11],q[10]; 159 | cx q[5],q[11]; 160 | tdg q[10]; 161 | cx q[5],q[10]; 162 | tdg q[5]; 163 | tdg q[10]; 164 | t q[11]; 165 | cx q[11],q[10]; 166 | cx q[5],q[11]; 167 | cx q[10],q[5]; 168 | h q[11]; 169 | h q[10]; 170 | t q[5]; 171 | t q[9]; 172 | t q[10]; 173 | cx q[9],q[5]; 174 | cx q[10],q[9]; 175 | cx q[5],q[10]; 176 | tdg q[9]; 177 | cx q[5],q[9]; 178 | tdg q[5]; 179 | tdg q[9]; 180 | t q[10]; 181 | cx q[10],q[9]; 182 | cx q[5],q[10]; 183 | cx q[9],q[5]; 184 | h q[10]; 185 | h q[9]; 186 | t q[4]; 187 | t q[5]; 188 | t q[9]; 189 | cx q[5],q[4]; 190 | cx q[9],q[5]; 191 | cx q[4],q[9]; 192 | tdg q[5]; 193 | cx q[4],q[5]; 194 | tdg q[4]; 195 | tdg q[5]; 196 | t q[9]; 197 | cx q[9],q[5]; 198 | cx q[4],q[9]; 199 | cx q[5],q[4]; 200 | h q[9]; 201 | cx q[4],q[5]; 202 | h q[11]; 203 | t q[6]; 204 | t q[10]; 205 | t q[11]; 206 | cx q[10],q[6]; 207 | cx q[11],q[10]; 208 | cx q[6],q[11]; 209 | tdg q[10]; 210 | cx q[6],q[10]; 211 | tdg q[6]; 212 | tdg q[10]; 213 | t q[11]; 214 | cx q[11],q[10]; 215 | cx q[6],q[11]; 216 | cx q[10],q[6]; 217 | h q[11]; 218 | h q[10]; 219 | t q[6]; 220 | t q[9]; 221 | t q[10]; 222 | cx q[9],q[6]; 223 | cx q[10],q[9]; 224 | cx q[6],q[10]; 225 | tdg q[9]; 226 | cx q[6],q[9]; 227 | tdg q[6]; 228 | tdg q[9]; 229 | t q[10]; 230 | cx q[10],q[9]; 231 | cx q[6],q[10]; 232 | cx q[9],q[6]; 233 | h q[10]; 234 | h q[9]; 235 | t q[5]; 236 | t q[6]; 237 | t q[9]; 238 | cx q[6],q[5]; 239 | cx q[9],q[6]; 240 | cx q[5],q[9]; 241 | tdg q[6]; 242 | cx q[5],q[6]; 243 | tdg q[5]; 244 | tdg q[6]; 245 | t q[9]; 246 | cx q[9],q[6]; 247 | cx q[5],q[9]; 248 | cx q[6],q[5]; 249 | h q[9]; 250 | cx q[5],q[6]; 251 | h q[11]; 252 | t q[7]; 253 | t q[10]; 254 | t q[11]; 255 | cx q[10],q[7]; 256 | cx q[11],q[10]; 257 | cx q[7],q[11]; 258 | tdg q[10]; 259 | cx q[7],q[10]; 260 | tdg q[7]; 261 | tdg q[10]; 262 | t q[11]; 263 | cx q[11],q[10]; 264 | cx q[7],q[11]; 265 | cx q[10],q[7]; 266 | h q[11]; 267 | h q[10]; 268 | t q[7]; 269 | t q[9]; 270 | t q[10]; 271 | cx q[9],q[7]; 272 | cx q[10],q[9]; 273 | cx q[7],q[10]; 274 | tdg q[9]; 275 | cx q[7],q[9]; 276 | tdg q[7]; 277 | tdg q[9]; 278 | t q[10]; 279 | cx q[10],q[9]; 280 | cx q[7],q[10]; 281 | cx q[9],q[7]; 282 | h q[10]; 283 | h q[9]; 284 | t q[6]; 285 | t q[7]; 286 | t q[9]; 287 | cx q[7],q[6]; 288 | cx q[9],q[7]; 289 | cx q[6],q[9]; 290 | tdg q[7]; 291 | cx q[6],q[7]; 292 | tdg q[6]; 293 | tdg q[7]; 294 | t q[9]; 295 | cx q[9],q[7]; 296 | cx q[6],q[9]; 297 | cx q[7],q[6]; 298 | h q[9]; 299 | cx q[6],q[7]; 300 | h q[11]; 301 | t q[8]; 302 | t q[10]; 303 | t q[11]; 304 | cx q[10],q[8]; 305 | cx q[11],q[10]; 306 | cx q[8],q[11]; 307 | tdg q[10]; 308 | cx q[8],q[10]; 309 | tdg q[8]; 310 | tdg q[10]; 311 | t q[11]; 312 | cx q[11],q[10]; 313 | cx q[8],q[11]; 314 | cx q[10],q[8]; 315 | h q[11]; 316 | h q[10]; 317 | t q[8]; 318 | t q[9]; 319 | t q[10]; 320 | cx q[9],q[8]; 321 | cx q[10],q[9]; 322 | cx q[8],q[10]; 323 | tdg q[9]; 324 | cx q[8],q[9]; 325 | tdg q[8]; 326 | tdg q[9]; 327 | t q[10]; 328 | cx q[10],q[9]; 329 | cx q[8],q[10]; 330 | cx q[9],q[8]; 331 | h q[10]; 332 | cx q[10],q[11]; 333 | -------------------------------------------------------------------------------- /configs/compression/config.jsonnet: -------------------------------------------------------------------------------- 1 | // Arline Benchmarks 2 | // Copyright (C) 2019-2022 Turation Ltd 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU Affero General Public License as 6 | // published by the Free Software Foundation, either version 3 of the 7 | // License, or (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU Affero General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Affero General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | // This is .jsonnet configuration file that defines a set of benchmarking experiments with custom compilation pipelines. 19 | // For a quick tutorial on .jsonnet format go to https://jsonnet.org/learning/tutorial.html 20 | 21 | // This config will be eventually converted into usual .json format during parsing. 22 | // The purpose of .jsonnet format is to provide sufficient flexibility and allows 23 | // to define nested loops over benchmarking parameters [e.g. hardware, target circuits, compilation pipeline]. 24 | 25 | 26 | // target -- class of target circuits, e.g. random_chain_cliford_t_target or circuits from .qasm 27 | // hardware -- class of hardware [defined by vendor and connectivity map], e.g. IbmAll2all or IbmRueschlikon 28 | 29 | local pipeline_config = import 'pipelines.jsonnet'; 30 | local plotter_config = import '../reports/plotter.jsonnet'; 31 | local latex_config = import '../reports/latex.jsonnet'; 32 | 33 | // ---------------------------------------------------------------------------- 34 | // Define Target 35 | // ---------------------------------------------------------------------------- 36 | local chain_length = 120; 37 | local num_chains = 10; 38 | 39 | 40 | local random_chain_target_list(num_qubits, chain_length, num_chains) = [ 41 | // Define random circuit targets from [Clifford, T] gate set 42 | { 43 | task: 'circuit_transformation', 44 | name: 'random_chain_clifford_t_' + num_qubits + 'q_' + chain_length, // random chain identificator 45 | hardware: { 46 | class: 'CliffordTAll2All', // name of hardware class [determines gateset of generated target circuit] 47 | args: { 48 | num_qubits: num_qubits, 49 | }, 50 | }, 51 | algo: 'random_chain', 52 | number: num_chains, // number of circuits to be generated 53 | seed: 10, // random seed 54 | // We define uniform distribution of gate probabilities in the gate chain. 55 | // Two-qubit gates acting on different qubits are sampled independently. 56 | // For N qubit circuits number of distinct CNOT placements is N*(N-1), so 57 | // that for large N probability of CNOT gates will be small. 58 | gate_distribution: 'uniform', 59 | chain_length: chain_length, // total number of gates in the chain 60 | }, 61 | // Define random circuit targets for [U3, CNOT] gate set 62 | // (U3 has 3 random angles phi, theta, psi drawn from uniform distribution [0, 2*pi]) 63 | { 64 | task: 'circuit_transformation', 65 | name: 'random_chain_cnot_u3_' + num_qubits + 'q_' + chain_length, // random chain identificator 66 | hardware: { 67 | gate_set: ['U3', 'Cnot'], 68 | num_qubits: num_qubits, 69 | }, 70 | algo: 'random_chain', 71 | number: num_chains, // number of circuits to be generated 72 | seed: 10, // random seed 73 | // We define uniform distribution of gate probabilities in the gate chain. 74 | // Two-qubit gates acting on different qubits are sampled independently. 75 | // For N qubit circuits number of distinct CNOT placements is N*(N-1), so 76 | // that for large N probability of CNOT gates will be small. 77 | gate_distribution: 'uniform', 78 | chain_length: chain_length, // total number of gates in the chain 79 | } 80 | ]; 81 | 82 | // Define qasm targets from a predefined circuit dataset (the dataset can be easily extended) 83 | local math_circuits_target_list = [ 84 | { 85 | name: 'math_qasm_circuits', 86 | task: 'circuit_transformation', 87 | algo: 'qasm', 88 | number: null, 89 | // List of paths of .qasm circuits 90 | // To run benchmark for all .qasm circuits in the folder provide the 91 | // path to the folder instead, e.g. -> qasm_path: '$ARLINE_BENCHMARKS/circuits/' 92 | qasm_path: [ 93 | '$ARLINE_BENCHMARKS/circuits/rd53_135.qasm', 94 | '$ARLINE_BENCHMARKS/circuits/mini-alu_167.qasm', 95 | '$ARLINE_BENCHMARKS/circuits/C17_204.qasm', 96 | '$ARLINE_BENCHMARKS/circuits/sym9_146.qasm', 97 | '$ARLINE_BENCHMARKS/circuits/one-two-three-v0_97.qasm', 98 | ], 99 | } 100 | ]; 101 | 102 | // ---------------------------------------------------------------------------- 103 | // Define Output Hardware 104 | // ---------------------------------------------------------------------------- 105 | 106 | // First - 2 qubit IBM hardware for kAk benchmarking 107 | local hardware_2q = [ 108 | { 109 | class: 'IbmAll2All', 110 | args: { 111 | num_qubits: 2, 112 | }, 113 | }, 114 | ]; 115 | 116 | // Second - 16 qubit IBM and Rigetti hardware 117 | local hardware_multi_q = [ 118 | { 119 | class: 'IbmAll2All', // IBM hardware with all-to-all connectivity 120 | args: { 121 | num_qubits: 16, 122 | }, 123 | }, 124 | { 125 | class: 'IbmRueschlikonSymmetrical', // IBM Rueschlikon 16q hardware with symmetrized connectivity map 126 | args: {}, 127 | }, 128 | /* { 129 | class: 'RigettiAspenSymmetrical', // Rigetti Aspen 16q hardware with symmetrized connectivity map 130 | args: {}, 131 | }, */ 132 | ]; 133 | 134 | 135 | // ---------------------------------------------------------------------------- 136 | // Final Config 137 | // ---------------------------------------------------------------------------- 138 | // Now we finally define parameters of benchmarking experiment 139 | // Nested .jsonnet lists expressed via "for loops" allow to 140 | // generate all possible combinations of targets, hardware and compilation pipelines 141 | // subject to benchmarking. 142 | { 143 | // -------------------------------------------------------------------------- 144 | // Define Parameters of Pipelines 145 | // -------------------------------------------------------------------------- 146 | pipelines: 147 | std.flattenArrays( // 2 qubit benchmarks 148 | [ 149 | pipeline_config.pipelines_set(target, hardware, 'kak') 150 | for hardware in hardware_2q 151 | for target in random_chain_target_list(num_qubits=2, chain_length=chain_length, num_chains=num_chains) 152 | ] 153 | ) + 154 | std.flattenArrays( // 16 qubit benchmarks 155 | [ 156 | pipeline_config.pipelines_set(target, hardware, 'multiqubit') 157 | for hardware in hardware_multi_q 158 | for target in std.flattenArrays( 159 | [ 160 | random_chain_target_list(num_qubits=16, chain_length=chain_length, num_chains=num_chains), 161 | math_circuits_target_list, 162 | ] 163 | ) 164 | ] 165 | ), 166 | // -------------------------------------------------------------------------- 167 | // Define Parameters of Plotter for Generating Images for LaTeX Report 168 | // -------------------------------------------------------------------------- 169 | plotter: 170 | plotter_config.plotter_config( 171 | pipeline_config.pipelines_settings, 172 | std.flattenArrays([hardware_2q, hardware_multi_q]), 173 | pipeline_config.compilation_stages_settings, 174 | pipeline_config.stages_settings, 175 | pipeline_config.initial_stage, 176 | pipeline_config.final_stage 177 | ), 178 | // -------------------------------------------------------------------------- 179 | // Define Parameters of LaTeX Report 180 | // -------------------------------------------------------------------------- 181 | latex: 182 | latex_config.latex_config( 183 | pipeline_config.initial_stage, 184 | pipeline_config.final_stage, 185 | plotter_config.fig_format, 186 | ) 187 | } 188 | -------------------------------------------------------------------------------- /configs/compression/pipelines.jsonnet: -------------------------------------------------------------------------------- 1 | // Arline Benchmarks 2 | // Copyright (C) 2019-2022 Turation Ltd 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU Affero General Public License as 6 | // published by the Free Software Foundation, either version 3 of the 7 | // License, or (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU Affero General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Affero General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | // This is .jsonnet configuration file that defines a set of benchmarking experiments with custom compilation pipelines. 19 | // For a quick tutorial on .jsonnet format go to https://jsonnet.org/learning/tutorial.html 20 | 21 | // This config will be eventually converted into usual .json format during parsing. 22 | // The purpose of .jsonnet format is to provide sufficient flexibility and allows 23 | // to define nested loops over benchmarking parameters [e.g. hardware, target circuits, compilation pipeline]. 24 | 25 | 26 | // List of compilation pipelines 27 | 28 | // 'target_analysis' calculates metrics for the input target circuit and saves results to 29 | // gate_chain_report.csv. This is not a true compilation stage but it is required for correct 30 | // generation of benchmarking report and must be present at the start of each pipeline. 31 | 32 | 33 | local target_analysis(id='target_analysis') = { 34 | id: id, 35 | strategy: 'target_analysis', 36 | args: {}, 37 | }; 38 | 39 | local initial_stage = 'target_analysis'; 40 | local final_stage = 'mapping_compression'; 41 | 42 | local pipelines_set(target, hardware, test_type) = [ 43 | // Qiskit-based compilation pipeline 44 | { 45 | id: 'QiskitPl', // pipeline identificator 46 | target: target, 47 | test_type: test_type, 48 | stages: [ 49 | target_analysis(), 50 | { 51 | id: 'mapping_compression', // stage identificator 52 | strategy: 'qiskit_transpile', 53 | args: {hardware: hardware}, 54 | }, 55 | ], 56 | }, 57 | // Cirq-based compilation pipeline 58 | { 59 | id: 'CirqPl', 60 | target: target, 61 | test_type: test_type, 62 | stages: [ 63 | target_analysis(), 64 | { 65 | id: 'mapping_compression', 66 | strategy: 'cirq_mapping_compression', 67 | args: {hardware: hardware}, 68 | }, 69 | ], 70 | }, 71 | ]; 72 | 73 | local pipelines_settings = { // {pipeline_id: {name: "Pipeline label on plot", color: "matplotlib color"}} 74 | CirqPl: { name: 'CirqPl', color: 'indianred' }, 75 | QiskitPl: { name: 'QiskitPl', color: 'mediumturquoise' }, 76 | }; 77 | local compilation_stages_settings = { // {stage_id: {name: "Stage label on plot", color: "matplotlib color"}} 78 | mapping_compression: { name: 'Mapping+Compression', color: 'teal' }, 79 | unroll: {name: 'Unroll', color: 'turquoise'}, 80 | }; 81 | local stages_settings = { // {stage_id: {name: "Stage label on plot", color: "matplotlib color"}} 82 | target_analysis: { name: 'Target', color: 'crimson' }, 83 | } + compilation_stages_settings; 84 | 85 | { 86 | pipelines_set: pipelines_set, 87 | pipelines_settings: pipelines_settings, 88 | compilation_stages_settings: compilation_stages_settings, 89 | stages_settings: stages_settings, 90 | initial_stage: initial_stage, 91 | final_stage: final_stage, 92 | } 93 | -------------------------------------------------------------------------------- /configs/compression/run_and_plot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Arline Benchmarks 4 | # Copyright (C) 2019-2022 Turation Ltd 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | # run benchmark comparison with configuration defined in ./config.jsonnet 21 | arline-benchmarks-runner -c config.jsonnet -o results/benchmarks 22 | 23 | # Draw figures for LaTeX Report 24 | arline-benchmarks-plotter --csv results/benchmarks/gate_chain_report.csv -j config.jsonnet -o results/figures 25 | 26 | # Run LaTeX report engine 27 | arline-benchmarks-latex-report-generator -j config.jsonnet -i results -o results/latex_report 28 | -------------------------------------------------------------------------------- /configs/reports/latex.jsonnet: -------------------------------------------------------------------------------- 1 | // Arline Benchmarks 2 | // Copyright (C) 2019-2022 Turation Ltd 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU Affero General Public License as 6 | // published by the Free Software Foundation, either version 3 of the 7 | // License, or (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU Affero General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Affero General Public License 15 | // along with this program. If not, see . 16 | 17 | // This is .jsonnet configuration file that defines a set of benchmarking experiments with custom compilation pipelines. 18 | // For a quick tutorial on .jsonnet format go to https://jsonnet.org/learning/tutorial.html 19 | 20 | // This config will be eventually converted into usual .json format during parsing. 21 | // The purpose of .jsonnet format is to provide sufficient flexibility. 22 | 23 | local latex_config( 24 | initial_stage, 25 | final_stage, 26 | fig_format, 27 | calculate_fidelity=false, 28 | compression_radar_with_cost=false, 29 | ) = { 30 | local gate_metrics = [ 31 | { 32 | name: "Depth", 33 | fig_name: "depth", 34 | }, 35 | { 36 | name: "Total Gate Count", 37 | fig_name: "total_gate_count", 38 | }, 39 | { 40 | name: "Single-Qubit Gate Count", 41 | fig_name: "single_qubit_gate_count", 42 | }, 43 | { 44 | name: "Two-Qubit Gate Count", 45 | fig_name: "two_qubit_gate_count" 46 | }, 47 | { 48 | name: "Single-Qubit Gate Depth", 49 | fig_name: "single_qubit_gate_depth" 50 | }, 51 | { 52 | name: "Two-Qubit Gate Depth", 53 | fig_name: "two_qubit_gate_depth" 54 | }, 55 | ], 56 | local circuit_metrics = ( 57 | if calculate_fidelity then [ 58 | { 59 | name: "Circuit Cost Function", 60 | fig_name: "circuit_cost_function", 61 | }, 62 | { 63 | name: "Measurement Infidelity", 64 | fig_name: "measurement_infidelity", 65 | }, 66 | ] 67 | else [ 68 | { 69 | name: "Circuit Cost Function", 70 | fig_name: "circuit_cost_function", 71 | }, 72 | ] 73 | ), 74 | local time_metrics = [ 75 | { 76 | name: "Execution Time", 77 | fig_name: "execution_time", 78 | } 79 | ], 80 | local all_metrics = ( 81 | std.flattenArrays ([ 82 | gate_metrics, 83 | circuit_metrics, 84 | time_metrics, 85 | ]) 86 | ), 87 | local scatter_fig_list = [ 88 | "total_gate_count_vs_depth", 89 | "two_qubit_gate_count_vs_depth", 90 | "two_qubit_gate_count_vs_single_qubit_gate_count", 91 | "total_execution_time_vs_total_gate_count", 92 | "single_qubit_gate_depth_vs_single_qubit_gate_count", 93 | "two_qubit_gate_depth_vs_two_qubit_gate_count", 94 | ], 95 | initial_stage: initial_stage, 96 | final_stage: final_stage, 97 | fig_format: fig_format, 98 | gate_metrics: gate_metrics, 99 | circuit_metrics: circuit_metrics, 100 | time_metrics: time_metrics, 101 | all_metrics: all_metrics, 102 | scatter_fig_list: scatter_fig_list, 103 | compression_radar_with_cost: compression_radar_with_cost, 104 | }; 105 | 106 | 107 | { 108 | latex_config: latex_config, 109 | } -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/arline_benchmarks_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArlineQ/arline_benchmarks/d93ab31415fa400c5bf01a7fa0b0bf65db867336/docs/_static/arline_benchmarks_logo.png -------------------------------------------------------------------------------- /docs/_static/arline_favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArlineQ/arline_benchmarks/d93ab31415fa400c5bf01a7fa0b0bf65db867336/docs/_static/arline_favicon.ico -------------------------------------------------------------------------------- /docs/arline_benchmarks.rst: -------------------------------------------------------------------------------- 1 | .. _arline_benchmarks: 2 | 3 | Arline Benchmarks 4 | ================= 5 | 6 | Platform for quantum framework comparison 7 | 8 | Configuration Parser 9 | -------------------- 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | config_parser 15 | 16 | Engine 17 | ------ 18 | 19 | .. toctree:: 20 | :maxdepth: 2 21 | 22 | engine 23 | 24 | Metrics 25 | ------- 26 | 27 | .. toctree:: 28 | :maxdepth: 2 29 | 30 | metrics 31 | 32 | Pipeline 33 | -------- 34 | 35 | .. toctree:: 36 | :maxdepth: 2 37 | 38 | pipeline 39 | 40 | Reports 41 | ------- 42 | 43 | .. toctree:: 44 | :maxdepth: 2 45 | 46 | reports 47 | 48 | Strategies 49 | ---------- 50 | 51 | .. toctree:: 52 | :maxdepth: 2 53 | 54 | strategies 55 | 56 | Targets 57 | ------- 58 | 59 | .. toctree:: 60 | :maxdepth: 2 61 | 62 | targets 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /docs/circuits.rst: -------------------------------------------------------------------------------- 1 | .. _circuits: 2 | 3 | Circuits 4 | ======== 5 | 6 | QASM Circuits 7 | 8 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | # Configuration file for the Sphinx documentation builder. 18 | # 19 | # This file only contains a selection of the most common options. For a full 20 | # list see the documentation: 21 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 22 | 23 | # -- Path setup -------------------------------------------------------------- 24 | 25 | # If extensions (or modules to document with autodoc) are in another directory, 26 | # add these directories to sys.path here. If the directory is relative to the 27 | # documentation root, use os.path.abspath to make it absolute, like shown here. 28 | # 29 | # import os 30 | # import sys 31 | # sys.path.insert(0, os.path.abspath('.')) 32 | 33 | # -- Project information ----------------------------------------------------- 34 | import os 35 | import sys 36 | import sphinx_rtd_theme 37 | 38 | sys.path.insert(0, os.path.abspath("../")) 39 | autodoc_mock_imports = [ 40 | '_jsonnet', 41 | 'pylatex', 42 | 'cpuinfo', 43 | 'psutil', 44 | 'pandas', 45 | 'tqdm', 46 | 'seaborn', 47 | 'matplotlib', 48 | 'cirq', 49 | 'qiskit', 50 | 'arline_quantum', 51 | ] 52 | 53 | project = "Arline Benchmarks" 54 | copyright = "Copyright (C) 2019-2022 Turation Ltd" 55 | author = "Turation Ltd" 56 | 57 | # The full version, including alpha/beta/rc tags 58 | release = "0.1.8" 59 | 60 | # The master toctree document. 61 | master_doc = "index" 62 | # -- General configuration --------------------------------------------------- 63 | 64 | # Add any Sphinx extension module names here, as strings. They can be 65 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 66 | # ones. 67 | extensions = ["sphinx.ext.autodoc", "sphinx.ext.inheritance_diagram", "sphinx.ext.intersphinx", "sphinx.ext.napoleon"] 68 | 69 | intersphinx_mapping = { 70 | "python": ("https://docs.python.org/3", None), 71 | } 72 | 73 | # Add any paths that contain templates here, relative to this directory. 74 | templates_path = ["_templates"] 75 | 76 | # List of patterns, relative to source directory, that match files and 77 | # directories to ignore when looking for source files. 78 | # This pattern also affects html_static_path and html_extra_path. 79 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 80 | 81 | # -- Options for HTML output ------------------------------------------------- 82 | 83 | # The theme to use for HTML and HTML Help pages. See the documentation for 84 | # a list of builtin themes. 85 | html_theme = 'sphinx_rtd_theme' 86 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 87 | 88 | html_sidebars = { 89 | "index": ["localtoc.html", "searchbox.html"], 90 | "**": ["about.html", "localtoc.html", "relations.html", "searchbox.html"], 91 | } 92 | 93 | # Add any paths that contain custom static files (such as style sheets) here, 94 | # relative to this directory. They are copied after the builtin static files, 95 | # so a file named "default.css" will overwrite the builtin "default.css". 96 | html_static_path = ["_static"] 97 | html_favicon = "_static/arline_favicon.ico" 98 | 99 | autodoc_default_flags = ["members"] 100 | autosummary_generate = True 101 | -------------------------------------------------------------------------------- /docs/config_parser.rst: -------------------------------------------------------------------------------- 1 | .. _config_parser: 2 | 3 | Configuration Parser 4 | ==================== 5 | 6 | .. automodule:: arline_benchmarks.config_parser.pipeline_config_parser 7 | :members: 8 | :inherited-members: 9 | :show-inheritance: 10 | :undoc-members: 11 | -------------------------------------------------------------------------------- /docs/configs.rst: -------------------------------------------------------------------------------- 1 | .. _configs: 2 | 3 | Configs 4 | ======== 5 | 6 | Configs 7 | 8 | -------------------------------------------------------------------------------- /docs/engine.rst: -------------------------------------------------------------------------------- 1 | .. _engine: 2 | 3 | Engine 4 | ====== 5 | 6 | .. automodule:: arline_benchmarks.engine.pipeline_engine 7 | :members: 8 | :inherited-members: 9 | :show-inheritance: 10 | :undoc-members: 11 | 12 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. rst-class:: hide-header 2 | 3 | Arline Benchmarks Documentation 4 | =============================== 5 | 6 | .. image:: _static/arline_benchmarks_logo.png 7 | :alt: Arline 8 | :align: center 9 | :target: https://arline.io 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | :caption: Contents: 14 | 15 | Arline Benchmarks 16 | ----------------- 17 | .. toctree:: 18 | :maxdepth: 2 19 | 20 | arline_benchmarks 21 | 22 | 23 | Circuits 24 | -------- 25 | .. toctree:: 26 | :maxdepth: 2 27 | 28 | circuits 29 | 30 | 31 | Configs 32 | ------- 33 | .. toctree:: 34 | :maxdepth: 2 35 | 36 | configs -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/metrics.rst: -------------------------------------------------------------------------------- 1 | .. _metrics: 2 | 3 | Metrics 4 | ======= 5 | 6 | .. automodule:: arline_benchmarks.metrics.gate_chain_analyser 7 | :members: 8 | :inherited-members: 9 | :show-inheritance: 10 | :undoc-members: 11 | 12 | -------------------------------------------------------------------------------- /docs/pipeline.rst: -------------------------------------------------------------------------------- 1 | .. _pipeline: 2 | 3 | Pipelines 4 | ========= 5 | 6 | .. automodule:: arline_benchmarks.pipeline.pipeline 7 | :members: 8 | :inherited-members: 9 | :show-inheritance: 10 | :undoc-members: 11 | 12 | -------------------------------------------------------------------------------- /docs/reports.rst: -------------------------------------------------------------------------------- 1 | .. _reports: 2 | 3 | Plot Benchmarks 4 | =============== 5 | 6 | .. automodule:: arline_benchmarks.reports.plot_benchmarks 7 | :members: 8 | :inherited-members: 9 | :show-inheritance: 10 | :undoc-members: 11 | 12 | 13 | Results Logger 14 | ============== 15 | 16 | .. automodule:: arline_benchmarks.reports.results_logger 17 | :members: 18 | :inherited-members: 19 | :show-inheritance: 20 | :undoc-members: 21 | 22 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy>=1.18.3 2 | scipy>=1.3.1 3 | sphinx-rtd-theme==0.4.3 -------------------------------------------------------------------------------- /docs/strategies.rst: -------------------------------------------------------------------------------- 1 | .. _strategies: 2 | 3 | 4 | Base Class 5 | ========== 6 | 7 | .. automodule:: arline_benchmarks.strategies.strategy 8 | :members: 9 | :inherited-members: 10 | :show-inheritance: 11 | :undoc-members: 12 | 13 | 14 | Target Analysis 15 | =============== 16 | 17 | .. inheritance-diagram:: arline_benchmarks.strategies.target_analysis 18 | :parts: 1 19 | 20 | .. automodule:: arline_benchmarks.strategies.target_analysis 21 | :members: 22 | :inherited-members: 23 | :show-inheritance: 24 | :undoc-members: 25 | 26 | 27 | Cirq Compression 28 | ================ 29 | 30 | .. inheritance-diagram:: arline_benchmarks.strategies.cirq_compression 31 | :parts: 1 32 | 33 | .. automodule:: arline_benchmarks.strategies.cirq_compression 34 | :members: 35 | :inherited-members: 36 | :show-inheritance: 37 | :undoc-members: 38 | 39 | 40 | Cirq Mapping 41 | ============ 42 | 43 | .. inheritance-diagram:: arline_benchmarks.strategies.cirq_mapping 44 | :parts: 1 45 | 46 | .. automodule:: arline_benchmarks.strategies.cirq_mapping 47 | :members: 48 | :inherited-members: 49 | :show-inheritance: 50 | :undoc-members: 51 | 52 | 53 | Qiskit Compression 54 | ================== 55 | 56 | .. inheritance-diagram:: arline_benchmarks.strategies.qiskit_compression 57 | :parts: 1 58 | 59 | .. automodule:: arline_benchmarks.strategies.qiskit_compression 60 | :members: 61 | :inherited-members: 62 | :show-inheritance: 63 | :undoc-members: 64 | 65 | 66 | Qiskit Mapping 67 | ============== 68 | 69 | .. inheritance-diagram:: arline_benchmarks.strategies.qiskit_mapping 70 | :parts: 1 71 | 72 | .. automodule:: arline_benchmarks.strategies.qiskit_mapping 73 | :members: 74 | :inherited-members: 75 | :show-inheritance: 76 | :undoc-members: 77 | 78 | -------------------------------------------------------------------------------- /docs/targets.rst: -------------------------------------------------------------------------------- 1 | .. _traget: 2 | 3 | Target 4 | ====== 5 | 6 | .. automodule:: arline_benchmarks.targets.target 7 | :members: 8 | :inherited-members: 9 | :show-inheritance: 10 | :undoc-members: 11 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "wheel"] 3 | 4 | [tool.black] 5 | line-length = 120 6 | target-version = ['py36'] 7 | include = '\.pyi?$' 8 | exclude = ''' 9 | ( 10 | /( 11 | | .git 12 | )/ 13 | ) 14 | ''' 15 | -------------------------------------------------------------------------------- /scripts/arline-benchmarks-latex-report-generator: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Arline Benchmarks 4 | # Copyright (C) 2019-2022 Turation Ltd 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | import argparse 21 | from arline_benchmarks.reports.latex_report import LatexReport 22 | 23 | 24 | def main(): 25 | from arline_benchmarks.config_parser.pipeline_config_parser import PipelineConfigParser 26 | 27 | parser = argparse.ArgumentParser(description="Plot curves", formatter_class=argparse.ArgumentDefaultsHelpFormatter) 28 | parser.add_argument("--input_dir", "-i", type=str, help="Directory with generated benchmark data") 29 | parser.add_argument("--output_dir", "-o", type=str, help="Directory for Latex output") 30 | parser.add_argument("--config", "-j", type=str, help="Jsonnet config", required=True) 31 | args = parser.parse_args() 32 | 33 | config = PipelineConfigParser(args.config) 34 | latex_report = LatexReport(input_dir=args.input_dir, output_dir=args.output_dir, config=config) 35 | latex_report.generate_report() 36 | 37 | 38 | if __name__ == "__main__": 39 | main() -------------------------------------------------------------------------------- /scripts/arline-benchmarks-plotter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Arline Benchmarks 4 | # Copyright (C) 2019-2022 Turation Ltd 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | import argparse 20 | import pandas as pd 21 | 22 | from arline_benchmarks.reports.plot_benchmarks import BenchmarkPlotter 23 | 24 | 25 | def main(): 26 | from arline_benchmarks.config_parser.pipeline_config_parser import PipelineConfigParser 27 | 28 | parser = argparse.ArgumentParser(description="Plot curves", formatter_class=argparse.ArgumentDefaultsHelpFormatter) 29 | parser.add_argument("--csv", "-c", type=str, required=True, help="path to csv file", nargs="+") 30 | parser.add_argument("--output_dir", "-o", type=str, help="Output directory", required=True) 31 | parser.add_argument("--config", "-j", type=str, help="Jsonnet config", required=True) 32 | parser.add_argument("--dpi", "-r", type=int, default=150, required=False, help="Output resolution") 33 | args = parser.parse_args() 34 | 35 | data = [] 36 | for f in args.csv: 37 | data.append(pd.read_csv(f)) 38 | config = PipelineConfigParser(args.config) 39 | bp = BenchmarkPlotter(data=pd.concat(data), output_path=args.output_dir, config=config) 40 | bp.plot() 41 | 42 | 43 | if __name__ == "__main__": 44 | main() 45 | -------------------------------------------------------------------------------- /scripts/arline-benchmarks-runner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Arline Benchmarks 4 | # Copyright (C) 2019-2022 Turation Ltd 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as 8 | # published by the Free Software Foundation, either version 3 of the 9 | # License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | 20 | import argparse 21 | import sys 22 | 23 | from arline_benchmarks.config_parser.pipeline_config_parser import PipelineConfigParser 24 | from arline_benchmarks.engines.pipeline_engine import PipelineEngine 25 | 26 | 27 | def main(): 28 | parser = argparse.ArgumentParser(description="Run Benchmark Engine", add_help=True) 29 | parser.add_argument("--config", "-c", type=str, required=True, help="Configuration", default=None) 30 | parser.add_argument("--output", "-o", type=str, required=True, help="Output directory") 31 | parser.add_argument("--visualize", "-v", action="store_true", help="Print stats in terminal") # TODO check result 32 | args = parser.parse_args() 33 | 34 | cfg = PipelineConfigParser(args.config) 35 | engine = PipelineEngine(cfg, args) 36 | exit_code = engine.run() 37 | sys.exit(exit_code) 38 | 39 | 40 | if __name__ == "__main__": 41 | main() 42 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Arline Benchmarks 2 | # Copyright (C) 2019-2022 Turation Ltd 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU Affero General Public License as 6 | # published by the Free Software Foundation, either version 3 of the 7 | # License, or (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU Affero General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU Affero General Public License 15 | # along with this program. If not, see . 16 | 17 | import setuptools 18 | 19 | with open("README.md", "r") as fh: 20 | long_description = fh.read() 21 | 22 | setuptools.setup( 23 | name="arline-benchmarks", 24 | version="0.1.8", 25 | author="Turation Ltd", 26 | author_email="info@arline.io", 27 | description="Automated benchmarking platform for quantum compilers", 28 | long_description=long_description, 29 | long_description_content_type="text/markdown", 30 | url="https://github.com/ArlineQ/arline_benchmarks", 31 | packages=setuptools.find_packages(exclude=['tests*']), 32 | license="GNU Affero General Public License v3 (AGPLv3)", 33 | install_requires=[ 34 | "numpy>=1.18.3", 35 | "scipy>=1.4", 36 | "jsonnet>=0.15.0", 37 | "pylatex>=1.3.1", 38 | "py-cpuinfo~=5.0.0", 39 | "psutil>=5.7.0", 40 | "pandas>=0.25.3", 41 | "tqdm>=4.46.0", 42 | "seaborn>=0.10.1", 43 | "matplotlib==3.2.1", 44 | "cirq==0.13.1", 45 | "qiskit~=0.34.2", 46 | "pyzx==0.6.0", 47 | "pytket==0.6.0", 48 | # old qiskit version to support pytket-qiskit 49 | # "qiskit~=0.18.0", 50 | "arline-quantum~=0.1.8", 51 | "jkq.qcec==1.5" 52 | ], 53 | classifiers=[ 54 | "Programming Language :: Python :: 3", 55 | "License :: OSI Approved :: GNU Affero General Public License v3", 56 | "Operating System :: OS Independent", 57 | ], 58 | scripts=[ 59 | "scripts/arline-benchmarks-runner", 60 | "scripts/arline-benchmarks-plotter", 61 | "scripts/arline-benchmarks-latex-report-generator", 62 | ], 63 | python_requires=">=3.6", 64 | include_package_data=True, 65 | ) 66 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd -------------------------------------------------------------------------------- /tests/qasm_files/general/2q.qasm: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Turation Ltd 2 | 3 | OPENQASM 2.0; 4 | include "qelib1.inc"; 5 | 6 | qreg q[2]; 7 | 8 | u3(0.07*pi,-0.50*pi,0) q[0]; 9 | u3(0,0.10*pi,0.50*pi) q[1]; 10 | u2(0.20*pi,-0.50*pi) q[0]; 11 | u2(0,pi) q[1]; 12 | u1(-2*pi) q[0]; 13 | u1(2*pi) q[1]; 14 | cx q[0], q[1]; 15 | cx q[1], q[0]; 16 | id q[0]; 17 | id q[1]; 18 | x q[0]; 19 | x q[1]; 20 | y q[0]; 21 | y q[1]; 22 | z q[0]; 23 | z q[1]; 24 | h q[0]; 25 | h q[1]; 26 | s q[0]; 27 | s q[1]; 28 | sdg q[0]; 29 | sdg q[1]; 30 | t q[0]; 31 | t q[1]; 32 | tdg q[0]; 33 | tdg q[1]; 34 | rx(-2*pi) q[0]; 35 | rx(0.25*pi) q[1]; 36 | ry(0) q[0]; 37 | ry(-pi) q[1]; 38 | rz(-0.06*pi) q[0]; 39 | rz(-0.14*pi) q[1]; 40 | cy q[0], q[1]; 41 | cy q[1], q[0]; 42 | cz q[0], q[1]; 43 | cz q[1], q[0]; 44 | ch q[0], q[1]; 45 | ch q[1], q[0]; 46 | crz(0.25*pi) q[0], q[1]; 47 | crz(2*pi) q[1], q[0]; 48 | cu1(0.08*pi) q[0], q[1]; 49 | cu1(-2*pi) q[1], q[0]; 50 | cu3(0.07*pi,-0.50*pi,0) q[0], q[1]; 51 | cu3(-2*pi,-2*pi,-2*pi) q[1], q[0]; 52 | u3(pi,-0.50*pi,0) q[0]; 53 | u3(0,0.05*pi,0.50*pi) q[1]; 54 | u2(0.20*pi,-0.50*pi) q[0]; 55 | u2(0,-pi) q[1]; 56 | u1(-2*pi) q[0]; 57 | u1(2*pi) q[1]; 58 | cx q[0], q[1]; 59 | cx q[1], q[0]; 60 | id q[0]; 61 | id q[1]; 62 | x q[0]; 63 | x q[1]; 64 | y q[0]; 65 | y q[1]; 66 | z q[0]; 67 | z q[1]; 68 | h q[0]; 69 | h q[1]; 70 | s q[0]; 71 | s q[1]; 72 | sdg q[0]; 73 | sdg q[1]; 74 | t q[0]; 75 | t q[1]; 76 | tdg q[0]; 77 | tdg q[1]; 78 | rx(-2*pi) q[0]; 79 | rx(0.25*pi) q[1]; 80 | ry(0) q[0]; 81 | ry(-pi) q[1]; 82 | rz(-0.06*pi) q[0]; 83 | rz(-0.29*pi) q[1]; 84 | cy q[0], q[1]; 85 | cy q[1], q[0]; 86 | cz q[0], q[1]; 87 | cz q[1], q[0]; 88 | ch q[0], q[1]; 89 | ch q[1], q[0]; 90 | r(0.35*pi,0.13*pi) q[0]; 91 | r(-0.1,0.20*pi) q[1]; 92 | crz(0.25*pi) q[0], q[1]; 93 | crz(2*pi) q[1], q[0]; 94 | cu1(-pi) q[0], q[1]; 95 | cu1(-2*pi) q[1], q[0]; 96 | cu3(0.03*pi,-0.50*pi,0) q[0], q[1]; 97 | cu3(-2*pi,-2*pi,-2*pi) q[1], q[0]; 98 | crx(0.50*pi) q[0], q[1]; 99 | crx(0.06*pi) q[1], q[0]; 100 | cry(0.40*pi) q[0], q[1]; 101 | cry(0.14*pi) q[1], q[0]; 102 | crz(0.60*pi) q[0], q[1]; 103 | ry(0.60*pi) q[0]; 104 | rz(-0.60*pi) q[1]; 105 | rx(-0.17*pi) q[0]; 106 | ry(-0.05*pi) q[0]; 107 | swap q[0], q[1]; 108 | swap q[1], q[0]; 109 | rxx(0.03*pi) q[0], q[1]; 110 | rxx(-0.02*pi) q[1], q[0]; 111 | rzz(0.06*pi) q[0], q[1]; 112 | rzz(-0.12) q[1], q[0]; 113 | ryy(0.06*pi) q[0], q[1]; 114 | ryy(-0.12) q[1], q[0]; 115 | -------------------------------------------------------------------------------- /tests/qasm_files/general/5q.qasm: -------------------------------------------------------------------------------- 1 | OPENQASM 2.0; 2 | include "qelib1.inc"; 3 | qreg q[5]; 4 | crz(4.18903307314928) q[2],q[4]; 5 | crz(0.974772988147736) q[0],q[1]; 6 | tdg q[3]; 7 | ry(5.75214016748052) q[3]; 8 | crz(5.68457556000926) q[4],q[0]; 9 | id q[2]; 10 | s q[1]; 11 | s q[0]; 12 | rz(1.70018004146770) q[1]; 13 | rx(2.00018004146770) q[3]; 14 | t q[1]; 15 | u1(0.0107703516720153) q[3]; 16 | u3(-2.21570891198386,4.27675860086779,3.09083678357702) q[0]; 17 | crz(0.341189340188316) q[1],q[2]; 18 | swap q[3],q[4]; 19 | rx(1.66256446396177) q[3]; 20 | id q[2]; 21 | cy q[4],q[0]; 22 | crz(2.27591189721525) q[2],q[4]; 23 | crz(2.70254736247971) q[0],q[1]; 24 | z q[3]; 25 | rz(5.27850273540894) q[2]; 26 | u2(1.19057124399939,5.89811692894815) q[4]; 27 | z q[3]; 28 | x q[1]; 29 | cy q[1],q[0]; 30 | crz(0.359453424830142) q[4],q[2]; 31 | s q[2]; 32 | ch q[0],q[1]; 33 | y q[3]; 34 | tdg q[1]; 35 | u2(2.91045176943671,5.55522017488596) q[2]; 36 | ry(3.61950920014788) q[1]; 37 | cy q[2],q[4]; 38 | z q[3]; 39 | s q[4]; 40 | rz(1.71836482443307) q[1]; 41 | u3(0.147618097105755,1.77266886453511,0.0720831907116083) q[0]; 42 | h q[3]; 43 | cu3(3.94997579584029,5.28377931911799,-1.29355393385064) q[3],q[0]; 44 | cu1(3.50514820171887) q[2],q[1]; 45 | u1(4.45091989084745) q[4]; 46 | ry(1.14989349465363) q[2]; 47 | h q[3]; 48 | -------------------------------------------------------------------------------- /tests/qasm_files/general/small_angle.qasm: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Turation Ltd 2 | 3 | OPENQASM 2.0; 4 | include "qelib1.inc"; 5 | 6 | qreg q0[2]; 7 | 8 | u3(2.63088593277993,-2.25694024241796,3.88027677100982) q0[0]; 9 | u3(2.89127351830689,-2.80593324121091,2.57809858256605) q0[1]; 10 | cx q0[0], q0[1]; 11 | u3(1.41197126558121,-3.14159365158979,-2.22044604925031) q0[0]; 12 | u3(1.027169196961,0.740612630355959,3.97177635002873) q0[1]; 13 | cx q0[0], q0[1]; 14 | u3(0.179227305312944,-2.71238898038469,-1.77635683940025) q0[0]; 15 | u3(3.5707963267949,-2.5707963267949,-1.14159265358979) q0[1]; 16 | cx q0[0], q0[1]; 17 | u3(1.45559581365424,2.87867886642037,0.0285143038436324) q0[0]; 18 | u3(1.40890231220471,2.47473212047056,-1.22626370056528) q0[1]; 19 | -------------------------------------------------------------------------------- /tests/targets/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | -------------------------------------------------------------------------------- /tests/targets/test_target.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2022 Turation Ltd 2 | 3 | import unittest 4 | 5 | import numpy as np 6 | 7 | from arline_benchmarks.targets.target import RandomChainTarget 8 | 9 | from arline_quantum.gates.cnot import Cnot 10 | 11 | 12 | class TestTarget(unittest.TestCase): 13 | def test_random_chain_wo_2qubit_limit_creation(self): 14 | chain_length = 100 15 | hw_cfg = { 16 | "gate_set": ["Rx(2*pi/30)", "Cnot"], 17 | "qubit_connectivity": { 18 | "adj_matrix": [[0, 1], [1, 0]], 19 | "args": { 20 | "num_qubits": 2, 21 | } 22 | } 23 | } 24 | target_cfg = { 25 | "task": "decomposition", 26 | "algo": "random_chain", 27 | "number": -1, 28 | "seed": 10, 29 | "gate_distribution": "uniform", 30 | "chain_length": chain_length, 31 | "hardware": hw_cfg, 32 | } 33 | t = RandomChainTarget(target_cfg) 34 | 35 | for i in range(100): 36 | target_chain, _ = next(t) 37 | self.assertEqual(len(target_chain), chain_length) 38 | 39 | def test_random_chain_depth_limit(self): 40 | depth_limit = 5 41 | hw_cfg = { 42 | "gate_set": ["Rx(2*pi/30)", "Cnot"], 43 | "qubit_connectivity": { 44 | "class": "All2All", 45 | "args": { 46 | "num_qubits": 4, 47 | } 48 | } 49 | 50 | } 51 | target_cfg = { 52 | "task": "circuit_transformation", 53 | "algo": "random_chain", 54 | "number": -1, 55 | "seed": 10, 56 | "gate_distribution": "uniform", 57 | "chain_length": 1000, 58 | "depth_limit": depth_limit, 59 | "hardware": hw_cfg, 60 | } 61 | t = RandomChainTarget(target_cfg) 62 | 63 | for i in range(100): 64 | chain, chain_id = next(t) 65 | self.assertEqual(chain.get_depth(), depth_limit) 66 | 67 | def test_random_chain_gate_distribution(self): 68 | hw_cfg = { 69 | "gate_set": ["Rx(2*pi/30)", "Cnot"], 70 | "qubit_connectivity": { 71 | "adj_matrix": np.ones((3, 3)).tolist(), 72 | "args": { 73 | "num_qubits": 2, 74 | } 75 | } 76 | 77 | } 78 | target_cfg = { 79 | "task": "decomposition", 80 | "algo": "random_chain", 81 | "number": -1, 82 | "seed": 10, 83 | "gate_distribution": {"Rx(2*pi/30)": 0.1, "Cnot": 0.9}, 84 | "chain_length": 1000, 85 | "hardware": hw_cfg, 86 | } 87 | t = RandomChainTarget(target_cfg) 88 | 89 | target_chain, _ = next(t) 90 | cnt = target_chain.get_gate_count() 91 | 92 | self.assertGreaterEqual(cnt["Rx(2*pi/30)"], 1) 93 | self.assertGreaterEqual(cnt["Cnot"], 1) 94 | 95 | self.assertGreaterEqual(cnt["Cnot"] / len(target_chain), 0.85) 96 | self.assertLessEqual(cnt["Cnot"] / len(target_chain), 0.95) 97 | 98 | def test_random_chain_2qubit_limit(self): 99 | for chain_length in [1, 100]: 100 | with self.subTest(chain_length=chain_length): 101 | cnot_number = 1 102 | hw_cfg = { 103 | "gate_set": ["Rx(2*pi/30)", "Cnot"], 104 | "qubit_connectivity": { 105 | "adj_matrix": [[0, 1], [1, 0]], 106 | "args": { 107 | "num_qubits": 2, 108 | } 109 | } 110 | } 111 | 112 | target_cfg = { 113 | "task": "decomposition", 114 | "algo": "random_chain", 115 | "number": -1, 116 | "seed": 10, 117 | "gate_distribution": "uniform", 118 | "two_qubit_gate_num_upper_bound": cnot_number, 119 | "chain_length": chain_length, 120 | "hardware": hw_cfg, 121 | } 122 | t = RandomChainTarget(target_cfg) 123 | 124 | total_cnot_cnt = 0 125 | 126 | for i in range(100): 127 | target_chain, _ = next(t) 128 | self.assertLessEqual(target_chain.get_gate_count_by_gate_type(Cnot), cnot_number) 129 | self.assertEqual(len(target_chain), chain_length) 130 | total_cnot_cnt += target_chain.get_gate_count_by_gate_type(Cnot) 131 | 132 | self.assertGreater(total_cnot_cnt, 0) 133 | 134 | def test_random_chain_exact_2qubit_limit(self): 135 | for chain_length in [3, 100]: 136 | with self.subTest(chain_length=chain_length): 137 | cnot_number = 3 138 | hw_cfg = { 139 | "gate_set": ["Rx(2*pi/30)", "Cnot"], 140 | "qubit_connectivity": { 141 | "adj_matrix": [[0, 1], [1, 0]], 142 | "args": { 143 | "num_qubits": 2, 144 | } 145 | } 146 | } 147 | target_cfg = { 148 | "task": "decomposition", 149 | "algo": "random_chain", 150 | "number": -1, 151 | "seed": 10, 152 | "gate_distribution": "uniform", 153 | "two_qubit_gate_num_upper_bound": cnot_number, 154 | "two_qubit_gate_num_lower_bound": cnot_number, 155 | "chain_length": chain_length, 156 | "hardware": hw_cfg, 157 | } 158 | t = RandomChainTarget(target_cfg) 159 | 160 | for i in range(100): 161 | target_chain, _ = next(t) 162 | self.assertLessEqual(target_chain.get_gate_count_by_gate_type(Cnot), cnot_number) 163 | self.assertEqual(len(target_chain), chain_length) 164 | 165 | 166 | if __name__ == "__main__": 167 | unittest.main() 168 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py36, py37 3 | 4 | [testenv] 5 | deps = 6 | commands = 7 | python -m unittest discover -s tests 8 | --------------------------------------------------------------------------------