From 49477762a8033e293af01ace454afb438c03ccca Mon Sep 17 00:00:00 2001 From: Max Radin Date: Fri, 6 Dec 2024 12:36:55 -0800 Subject: [PATCH 01/11] Initial implementation of physical resource estimates --- scripts/compute_all_LREs_script.py | 114 ++++++++++++++++++++++------- setup.cfg | 1 + 2 files changed, 87 insertions(+), 28 deletions(-) diff --git a/scripts/compute_all_LREs_script.py b/scripts/compute_all_LREs_script.py index d0bd861f..e3889d20 100755 --- a/scripts/compute_all_LREs_script.py +++ b/scripts/compute_all_LREs_script.py @@ -30,10 +30,20 @@ import pandas as pd from pyLIQTR.utils.resource_analysis import estimate_resources +from qualtran.surface_code.algorithm_summary import AlgorithmSummary +from qualtran.surface_code.ccz2t_cost_model import ( + get_ccz2t_costs_from_grid_search, + iter_ccz2t_factories, +) from qb_gsee_benchmark.qre import get_df_qpe_circuit from qb_gsee_benchmark.utils import retrieve_fcidump_from_sftp + +class NoFactoriesFoundError(Exception): + pass + + logger = logging.getLogger() logger.setLevel(logging.INFO) console_handler = logging.StreamHandler() @@ -45,6 +55,30 @@ logger.addHandler(h) +def get_physical_cost( + num_logical_qubits: int, + num_T_gates: int, + hardware_failure_tolerance_per_shot: float, + n_factories: int, + physical_error_rate: float, +): + n_magic = AlgorithmSummary(t_gates=num_T_gates) + try: + best_cost, best_factory, best_data_block = get_ccz2t_costs_from_grid_search( + n_magic=n_magic, + n_algo_qubits=num_logical_qubits, + error_budget=hardware_failure_tolerance_per_shot, + phys_err=physical_error_rate, + factory_iter=iter_ccz2t_factories(n_factories=n_factories), + cost_function=(lambda pc: pc.duration_hr), + ) + return best_cost.duration_hr * 60 * 60, best_cost.footprint + except TypeError: + raise NoFactoriesFoundError( + f"No factories found that meet the performance requirements." + ) + + def get_lqre( problem_instance: dict, username: str, ppk_path: str, config: dict ) -> dict[str, Any]: @@ -153,37 +187,61 @@ def get_lqre( ).total_seconds() logging.info(f"Resource estimation time (seconds): {LRE_calc_time}") - solution_data.append( - { - "task_uuid": task["task_uuid"], - "error_bound": error_tolerance, - "confidence_level": failure_tolerance, - "quantum_resources": { - "logical": { - "num_logical_qubits": logical_resources["LogicalQubits"], - "num_T_gates_per_shot": logical_resources["T"], - "num_shots": math.ceil(num_shots), - "hardware_failure_tolerance_per_shot": hardware_failure_tolerance_per_shot, - } + task_solution_data = { + "task_uuid": task["task_uuid"], + "error_bound": error_tolerance, + "confidence_level": failure_tolerance, + "quantum_resources": { + "logical": { + "num_logical_qubits": logical_resources["LogicalQubits"], + "num_T_gates_per_shot": logical_resources["T"], + "num_shots": math.ceil(num_shots), + "hardware_failure_tolerance_per_shot": hardware_failure_tolerance_per_shot, + } + }, + "run_time": { + "preprocessing_time": { + "wall_clock_start_time": circuit_generation_start_time.strftime( + "%Y-%m-%dT%H:%M:%S.%f" + ) + + "Z", + "wall_clock_stop_time": circuit_generation_end_time.strftime( + "%Y-%m-%dT%H:%M:%S.%f" + ) + + "Z", + "seconds": ( + circuit_generation_end_time - circuit_generation_start_time + ).total_seconds(), }, - "run_time": { - "preprocessing_time": { - "wall_clock_start_time": circuit_generation_start_time.strftime( - "%Y-%m-%dT%H:%M:%S.%f" - ) - + "Z", - "wall_clock_stop_time": circuit_generation_end_time.strftime( - "%Y-%m-%dT%H:%M:%S.%f" - ) - + "Z", - "seconds": ( - circuit_generation_end_time - - circuit_generation_start_time - ).total_seconds(), - } + }, + } + + try: + algorithm_runtime_seconds, num_physical_qubits = get_physical_cost( + num_logical_qubits=logical_resources["LogicalQubits"], + num_T_gates=logical_resources["T"], + hardware_failure_tolerance_per_shot=hardware_failure_tolerance_per_shot, + n_factories=config["hardware_parameters"]["n_factories"], + physical_error_rate=config["hardware_parameters"][ + "physical_error_rate" + ], + ) + task_solution_data["run_time"]["algorithm_run_time"] = ( + { + "seconds": algorithm_runtime_seconds, }, + ) + task_solution_data["run_time"]["overall_time"] = { + "seconds": ( + circuit_generation_end_time - circuit_generation_start_time + ).total_seconds() + + algorithm_runtime_seconds } - ) + except NoFactoriesFoundError: + logging.info( + f"No factories found that meet the performance requirements. Skipping physical cost estimation." + ) + solution_data.append(task_solution_data) solution_uuid = str(uuid4()) current_time = datetime.datetime.now(datetime.timezone.utc) diff --git a/setup.cfg b/setup.cfg index db604795..38263306 100644 --- a/setup.cfg +++ b/setup.cfg @@ -25,6 +25,7 @@ python_requires = >=3.8 install_requires = pyLIQTR>=1.2.0 + qualtran==0.2.0 pyscf openfermion openfermionpyscf From d9830f9902234fc36c4064526397823db7604942 Mon Sep 17 00:00:00 2001 From: Max Radin Date: Fri, 6 Dec 2024 14:19:27 -0800 Subject: [PATCH 02/11] Updating config --- scripts/LRE_config.json | 7 ++++++- scripts/compute_all_LREs_script.py | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/LRE_config.json b/scripts/LRE_config.json index 7da759d7..9181a2a6 100644 --- a/scripts/LRE_config.json +++ b/scripts/LRE_config.json @@ -3,9 +3,14 @@ "algorithm_parameters": { "overlap": 0.8, "df_threshold": 1e-3, - "max_orbitals": 32 + "max_orbitals": 37 }, "algorithm_description": "Double factorized QPE resource estimates based on methodology of arXiv:2406.06335. Note that the truncation error is not included in the error bounds and that the SCF compute time is not included in the preprocessing time. Also note that unlike arXiv:2406.06335, the ground-state overlaps are not computed from DMRG but instead set to a nominal value.", + "quantum_hardware_parameters": { + "num_factories": 4, + "physical_error_rate": 1e-3 + }, + "quantum_hardware_description": "foo", "contact_info": [ { "name": "Max Radin", diff --git a/scripts/compute_all_LREs_script.py b/scripts/compute_all_LREs_script.py index e3889d20..160b7971 100755 --- a/scripts/compute_all_LREs_script.py +++ b/scripts/compute_all_LREs_script.py @@ -217,15 +217,20 @@ def get_lqre( } try: + physical_resource_estimation_start = datetime.datetime.now() algorithm_runtime_seconds, num_physical_qubits = get_physical_cost( num_logical_qubits=logical_resources["LogicalQubits"], num_T_gates=logical_resources["T"], hardware_failure_tolerance_per_shot=hardware_failure_tolerance_per_shot, - n_factories=config["hardware_parameters"]["n_factories"], + n_factories=config["hardware_parameters"]["num_factories"], physical_error_rate=config["hardware_parameters"][ "physical_error_rate" ], ) + physical_resource_estimation_end = datetime.datetime.now() + logging.info( + f"Physical resource estimation time: {(physical_resource_estimation_end - physical_resource_estimation_start).total_seconds()} seconds." + ) task_solution_data["run_time"]["algorithm_run_time"] = ( { "seconds": algorithm_runtime_seconds, From 733c194031a0eb66682fe1c016c746e1984f9e79 Mon Sep 17 00:00:00 2001 From: Max Radin Date: Fri, 6 Dec 2024 15:09:07 -0800 Subject: [PATCH 03/11] Renaming LRE to QRE --- README.md | 6 ++-- schemas/solution.schema.0.0.1.json | 10 +++++- scripts/{LRE_config.json => QRE_config.json} | 0 ...overlaps.json => QRE_config_overlaps.json} | 0 ...s_script.py => compute_all_QREs_script.py} | 32 ++++++++++++++----- 5 files changed, 36 insertions(+), 12 deletions(-) rename scripts/{LRE_config.json => QRE_config.json} (100%) rename scripts/{LRE_config_overlaps.json => QRE_config_overlaps.json} (100%) rename scripts/{compute_all_LREs_script.py => compute_all_QREs_script.py} (91%) diff --git a/README.md b/README.md index c087a717..f896aadf 100644 --- a/README.md +++ b/README.md @@ -38,17 +38,17 @@ Contact the repository maintainers to get these. ### Generating Logical Quantum Resource Estimates -The [`scripts/compute_all_LREs_script.py`](scripts/compute_all_LREs_script.py) script can be used to generate LQREs. +The [`scripts/compute_all_QREs_script.py`](scripts/compute_all_QREs_script.py) script can be used to generate LQREs. In order to run this script, first ensure that the qb-gsee-benchmark package is installed as described above. Then, several files are required: * A PPK file containing a key to access the SFTP server that provides access to FCIDUMP files as described above. -* A configuration file similar to [`scripts/LRE_config.json`](scripts/LRE_config.json) or [`scripts/LRE_config.json`](scripts/LRE_config_overlaps.json) which specifies algorithm parameters, solver UUID, and other information. +* A configuration file similar to [`scripts/QRE_config.json`](scripts/QRE_config.json) or [`scripts/QRE_config.json`](scripts/QRE_config_overlaps.json) which specifies algorithm parameters, solver UUID, and other information. * If the `algorithm_parameters` object in the config file specifies a value for `overlap_csv`, then this CSV file must also be present. See for example [`scripts/overlaps.csv`](scripts/overlaps.csv) The paths to these files must be passed as arguments to the script, for example: ```bash -python compute_all_LREs_script.py -i ../problem_instances -o ../solution_files --LRE_config_file LRE_config.json --sftp_username darpa-qb --sftp_key_file path_to_ppk_file +python compute_all_QREs_script.py -i ../problem_instances -o ../solution_files --QRE_config_file QRE_config.json --sftp_username darpa-qb --sftp_key_file path_to_ppk_file ```