From 1628752dcada1c3a386619bfa8a2709899079457 Mon Sep 17 00:00:00 2001 From: gonfeco Date: Thu, 23 May 2024 11:37:50 +0200 Subject: [PATCH] Added qpu package to the QQuantLib of the BTC_02_AE. Corrected oracle calls counts in CQPEAE --- .../QQuantLib/AE/ae_classical_qpe.py | 29 +- .../BTC_02_AE/QQuantLib/qpu/NoisyModels.ipynb | 1529 +++++++++++++++++ tnbs/BTC_02_AE/QQuantLib/qpu/REAME.md | 3 + tnbs/BTC_02_AE/QQuantLib/qpu/__init__.py | 0 tnbs/BTC_02_AE/QQuantLib/qpu/get_qpu.py | 84 + tnbs/BTC_02_AE/QQuantLib/qpu/model_noise.py | 169 ++ .../qpu/noise_test_bank_functions.py | 109 ++ tnbs/BTC_02_AE/QQuantLib/qpu/qpu_ideal.json | 24 + tnbs/BTC_02_AE/QQuantLib/qpu/qpu_noisy.json | 192 +++ tnbs/BTC_02_AE/QQuantLib/qpu/select_qpu.py | 131 ++ 10 files changed, 2257 insertions(+), 13 deletions(-) create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/NoisyModels.ipynb create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/REAME.md create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/__init__.py create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/get_qpu.py create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/model_noise.py create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/noise_test_bank_functions.py create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/qpu_ideal.json create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/qpu_noisy.json create mode 100644 tnbs/BTC_02_AE/QQuantLib/qpu/select_qpu.py diff --git a/tnbs/BTC_02_AE/QQuantLib/AE/ae_classical_qpe.py b/tnbs/BTC_02_AE/QQuantLib/AE/ae_classical_qpe.py index c173abb..9f5281b 100644 --- a/tnbs/BTC_02_AE/QQuantLib/AE/ae_classical_qpe.py +++ b/tnbs/BTC_02_AE/QQuantLib/AE/ae_classical_qpe.py @@ -1,16 +1,18 @@ """ -This module contains a wrapper class of the PE_QFT class from -QQuantLib/PE/phase_estimation_wqft module for adapting classical -phase estimation algorithm to solve amplitude estimation problems. -Following references were used: +This module contains the CQPEAE class. Given a quantum oracle operator, +this class estimates the amplitude of a given target state using the +classical QPE algorithm (with QFT). This module uses the +QQuantLib.PE.classical_qpe one. - Brassard, G., Hoyer, P., Mosca, M., & Tapp, A. (2000). +The following references were used: + + *Brassard, G., Hoyer, P., Mosca, M., & Tapp, A. (2000). Quantum amplitude amplification and estimation. AMS Contemporary Mathematics Series, 305. - https://arxiv.org/abs/quant-ph/0005055v1 + https://arxiv.org/abs/quant-ph/0005055v1* - NEASQC deliverable: D5.1: Review of state-of-the-art for Pricing - and Computation of VaR + *NEASQC deliverable: D5.1: Review of state-of-the-art for Pricing + and Computation of VaR* Author: Gonzalo Ferro Costas & Alberto Manzano Herrero @@ -20,6 +22,7 @@ #from copy import deepcopy import numpy as np import qat.lang.AQASM as qlm +from QQuantLib.qpu.get_qpu import get_qpu from QQuantLib.PE.classical_qpe import CQPE from QQuantLib.AA.amplitude_amplification import grover from QQuantLib.utils.utils import check_list_type @@ -67,9 +70,9 @@ def __init__(self, oracle: qlm.QRoutine, target: list, index: list, **kwargs): # Set the QPU to use self.linalg_qpu = kwargs.get("qpu", None) - # Provide QPU if self.linalg_qpu is None: - raise ValueError("Not QPU was provide. Please provide it!") + print("Not QPU was provide. PyLinalg will be used") + self.linalg_qpu = get_qpu("python") self.auxiliar_qbits_number = kwargs.get("auxiliar_qbits_number", 8) self.shots = int(kwargs.get("shots", 100)) @@ -228,9 +231,9 @@ def run(self): end = time.time() self.run_time = end - start #Total number of oracle calls - self.oracle_calls = self.shots * np.sum( - [2 * (2 ** i) + 1 for i in range(self.auxiliar_qbits_number)] - ) + self.oracle_calls = self.shots * (np.sum( + [2 * (2 ** i) for i in range(self.auxiliar_qbits_number)] + ) + 1) #Maximum number of oracle applications self.max_oracle_depth = 2 ** (int(self.auxiliar_qbits_number)-1) + 1 self.quantum_times = self.cqpe.quantum_times diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/NoisyModels.ipynb b/tnbs/BTC_02_AE/QQuantLib/qpu/NoisyModels.ipynb new file mode 100644 index 0000000..b6b3ace --- /dev/null +++ b/tnbs/BTC_02_AE/QQuantLib/qpu/NoisyModels.ipynb @@ -0,0 +1,1529 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7612c2a4-9e5e-4c08-8c27-24e761b10478", + "metadata": {}, + "source": [ + "# Noise Model Test Bank (only on QLM)\n", + "\n", + "The module **model_noise** from **QQuantLib.qpu** package allows to create in an easy way noise model for simulation. The following noisy channels can be added to the noisy model in an easy way.\n", + "\n", + "1. Depolarizing channel.\n", + "2. Amplitude Damping.\n", + "3. Dephasing (only if there is Amplitude Damping).\n", + "4. Measurement Channel.\n", + "\n", + "In order to configure a noisy model an input dictionary with the following format should ben provided:\n", + "\n", + "{\n", + "\n", + " 'qpu': \"noisy\",# ideal or noisy\n", + " \n", + " 't_gate_1qb': 35,# ns\n", + " \n", + " 't_gate_2qbs': 660,# ns\n", + " \n", + " 't_readout': 4000, # ns\n", + " \n", + " 'depol_channel': {\n", + " 'active': True, # True or False\n", + " 'error_gate_1qb': 1.0e-4,# float\n", + " 'error_gate_2qbs': 1.0e-3 # float\n", + " },\n", + " \n", + " 'idle': {\n", + " 'amplitude_damping': True, # True or False\n", + " 'dephasing_channel': True, # True or False\n", + " 't1': 0.2e6, #ns\n", + " 't2': 0.1e6 #ns\n", + " },\n", + " \n", + " 'meas': {\n", + " 'active': True, # True or False\n", + " 'readout_error': 1.370e-2# float\n", + " }\n", + "}\n", + "\n", + "The implemented noise modle in **model_noise** module have the following assumptions:\n", + "\n", + "1. The time for 1-qubit gates will be the same for all the possible 1-qubit gates: **t_gate_1qb**. Hardware model set all the 1-qubit gates (used or not) to this value.\n", + "2. The time for 2-qubit gates will be the same for all the possible 2-qubit gates: **t_gate_2qbs**. Hardware model set all the 2-qubit gates (used or not) to this value.\n", + "3. Times for 3-qubits gates (or more) **WON'T BE FIXED**. A rewritter plugin is recomended to use (in the module a toffoli rewritter is added to the final qpu).\n", + "4. Amplitude Damping channels and Dephasing channel should be enabled under the *idle* key of the dictionary:\n", + " * Dephasing channel will be enabled only applied if Amplitude Damping channel was enabled too. This is because $T_1$ and $T_2$ are needed for generating paramented $T_{\\varphi}$ for Dephasing channel.\n", + " * $T_{\\varphi} = \\frac{1}{\\frac{1}{T_2} - \\frac{1}{2 T_1}}$\n", + "6. Depolarizing channel should be enabled and configured under the *depol_channel* key:\n", + " * In the *Depolarizing channel* each time an ideal gate is applied then the depolarizing channel is applied\n", + " * The *Depolarizing channel* will be the same for the 1 and 2 qubit gates.\n", + " * The error asociated to all the 1-qubit gates will be the same: **error_gate_1qb**\n", + " * The error asociated to all the 2-qubit gates will be the same: : **error_gate_2qbs**\n", + "7. Only default gates in Qaptiva **DefaultHardwareModel** can be used. If *hw_model* is a **DefaultHardwareModel** object the default Qaptiva gates can be listed in the following dictionaries:\n", + " * hw_model.gates_specification.quantum_channels: Gates and corresponding definitions. Gates can be of the following type: \n", + " * QuantumChannelKraus. Using *arity* attribute e can know if they are of 1, 2 or more qubits.\n", + " * _ParametricChannel (paramétric gates of 1 qubit)\n", + " * _CtrlParametricChannel (controlled parametric gates: 2 qubits)\n", + " * hw_model.gates_specification.gate_times: dictionary with pair key (gate name) value (execution time of the gate)" + ] + }, + { + "cell_type": "markdown", + "id": "3f4f50c7-cf3f-467c-8ac3-6e2e3d12ada2", + "metadata": {}, + "source": [ + "### Toshiko\n", + "\n", + "T1 = 50 # us\n", + "T2= 30 # us\n", + "F1 = 99.9 # %\n", + "F2 = 92 # %\n", + "F_ro = 90 # %" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df1a3ee8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append(\"../../\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd9e1b0b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import qat.lang.AQASM as qlm\n", + "import json\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd3ff415-c947-4c00-b497-02a964ce1b46", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from qat.qpus import LinAlg" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e44fb05f-b1fa-49d2-a738-80973049fe25", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ideal_qpu = LinAlg()" + ] + }, + { + "cell_type": "markdown", + "id": "97a6ba69-74cf-4638-8883-fa0d5f50b4d1", + "metadata": {}, + "source": [ + "## List of gates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf7ac396-03bc-46f7-8ac3-b17f2da07d54", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from qat.hardware import DefaultHardwareModel" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f0a3029-a74f-4d0b-854e-a2b43948e10e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "hw_md = DefaultHardwareModel()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9dd490a3-6688-4d24-ae5b-0e632bbee898", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Gates and asociated quantum channels\n", + "hw_md.gates_specification.quantum_channels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ff0da3c-2d00-42e4-836c-89360ae9e0e3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# The Kraus operator is the ideal gate\n", + "hw_md.gates_specification.quantum_channels[\"H\"].kraus_operators" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c544156a-8e53-48fb-8b07-9906bd3e8a51", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# time of the gates\n", + "hw_md.gates_specification.gate_times" + ] + }, + { + "cell_type": "markdown", + "id": "8bf3980f", + "metadata": {}, + "source": [ + "## 1. Price Option Problem\n", + "\n", + "We are going to use a price estimation problem for playing with the noise models." + ] + }, + { + "cell_type": "markdown", + "id": "9c0d1868-12d8-4d33-960a-605439b9c3c8", + "metadata": {}, + "source": [ + "### 1. Price Estimation Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e76e75f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from QQuantLib.utils.benchmark_utils import create_pe_problem, combination_for_list, create_ae_pe_solution" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb71f7eb", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "folder = \"/home/gferro/FinancialApplications/benchmark/q_ae_price/jsons/\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f2042e4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "with open(folder + \"domain_configuration.json\") as json_file:\n", + " domain_cfg = json.load(json_file)\n", + "with open(folder + \"density_probability.json\") as json_file:\n", + " density_cfg = json.load(json_file)\n", + "with open(folder+ \"european_untracked.json\") as json_file:\n", + " payoff_cfg = json.load(json_file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "70230003", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pe_problem = create_pe_problem(domain_cfg, payoff_cfg, density_cfg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aac9bcd2-39dc-4d31-a8f3-a86ff5cf4740", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pe_problem" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "87d1213c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "price_problem = pe_problem[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ac3dec1-6e87-4781-a256-3dbc9b5f5ab8", + "metadata": { + "scrolled": true, + "tags": [] + }, + "outputs": [], + "source": [ + "price_problem" + ] + }, + { + "cell_type": "markdown", + "id": "58b12979-ea13-44ab-8d12-707ae1d7c978", + "metadata": {}, + "source": [ + "### 2. Create associated arrays" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf512636-c034-47dd-95bb-e2636436805b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from noise_test_bank_functions import create_arrays" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fff75a1b-58e5-4c2c-97c1-51e8dbd0ab51", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "domain, norm_pay_off, norm_p_x, pay_off_normalisation, p_x_normalisation = create_arrays(price_problem)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b7006d4-cbc4-4908-96c2-1062ee202a5f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(domain, norm_p_x, '-o')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd62d4ca-e52f-426a-8098-140e8ce5089d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(domain, norm_pay_off, '-o')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1968a832-9441-47f9-a227-b07ea4b8b41e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "integral = np.sum(norm_p_x * norm_pay_off)\n", + "integral" + ] + }, + { + "cell_type": "markdown", + "id": "b1eadc50-0226-4fa4-88f4-68dc299500f8", + "metadata": {}, + "source": [ + "### 3. Load arrays in an Quantum circuit " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54736c01-03cb-4e8a-940d-2ae51c2886ba", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from QQuantLib.DL.encoding_protocols import Encoding" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fec08a26-54e7-4e48-a3bb-ec613efdc663", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "encode_class = Encoding(\n", + " array_function=norm_pay_off,\n", + " array_probability=norm_p_x,\n", + " encoding=2\n", + ")\n", + "encode_class.run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "282a5d13-8a07-4f8e-831a-ca474e9e544f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "c = encode_class.oracle\n", + "%qatdisplay c" + ] + }, + { + "cell_type": "markdown", + "id": "c2112421-55e1-4293-bd26-592fce05e626", + "metadata": {}, + "source": [ + "### 4. Amplitude Estimation Algorithm\n", + "\n", + "We are going to use a **AE** algorithm." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "33cbac17-b9d3-469b-9c56-b4f6273b7a82", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# primero carga la configuración del algoritmo AE\n", + "with open(folder+ \"rqae_configuration_untracked.json\") as json_file:\n", + " ae_cfg = json.load(json_file)\n", + "ae_solver_rqae = combination_for_list(ae_cfg)\n", + "ae_problem = ae_solver_rqae[0]\n", + "ae_problem.update({\"qpu\": ideal_qpu})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b14ca52f-82a5-406d-bc20-0e7a678301cc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ae_problem" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5f6b7aa-0bb3-4f53-9038-a10c2b830696", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from QQuantLib.AE.real_quantum_ae import RQAE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee808ef5-3b34-48b0-93f8-a39d9af4f239", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "rqae_object = RQAE(\n", + " oracle=encode_class.oracle,\n", + " target=encode_class.target,\n", + " index=encode_class.index,\n", + " **ae_problem\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "15deb90f-5e23-4c74-9709-f8528a6b9f86", + "metadata": { + "tags": [] + }, + "source": [ + "### 5. First circuit\n", + "\n", + "We are going to use **RQAE**. Some typical **RQAE** parameters are needed. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ed9e561-e9b2-49e8-b4aa-a13b24da6865", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from noise_test_bank_functions import first_step" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9483f21b-1b54-458a-aa2c-377daef9ba1e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "rqae_object.epsilon, rqae_object.ratio, rqae_object.gamma" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7aa70353-6986-4a02-831c-25317e18a659", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "shift, n_i, gamma_i, theoretical_epsilon = first_step(rqae_object.epsilon, rqae_object.ratio, rqae_object.gamma)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c6d19b6-36f6-4e49-8067-8cdccb323bc2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "shift" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b39b1fc-e327-4dd4-85d6-691d7b58d900", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Setting the shift for the first circuit in RQAE\n", + "rqae_object.shifted_oracle = 2.0 * shift\n", + "routine = rqae_object._shifted_oracle" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7779a28-d2ca-4bf4-91d4-1cf569459628", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%qatdisplay routine" + ] + }, + { + "cell_type": "markdown", + "id": "60bc3bdf", + "metadata": { + "tags": [] + }, + "source": [ + "### 6. Solving the problem Problema\n", + "\n", + "The following code is used for solving first step of RQAE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4484019a-09cf-4aeb-adb6-1891a927a113", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from QQuantLib.utils.data_extracting import get_results\n", + "from QQuantLib.utils.utils import measure_state_probability\n", + "\n", + "def first_step(rutina, qpu, shots, target, shift, gamma, rqae_object):\n", + " \"\"\"\n", + " This function implements the first step of the RQAE paper. The result\n", + " is a first estimation of the desired amplitude.\n", + " \n", + " Parameters\n", + " ----------\n", + " shift : float\n", + " shift for the first iteration\n", + " shots : int\n", + " number of measurements\n", + " gamma : float\n", + " accuracy\n", + " \n", + " Returns\n", + " ----------\n", + " amplitude_min : float\n", + " lower bound for the amplitude to be estimated\n", + " amplitude_max : float\n", + " upper bound for the amplitude to be estimated\n", + " \n", + " \"\"\"\n", + " \n", + " results, circuit, _, _ = get_results(\n", + " rutina, qpu, shots=shots\n", + " )\n", + " \n", + " \n", + " probability_sum = measure_state_probability(\n", + " results, [0] + list(target)\n", + " )\n", + " \n", + " #probability_diff = results[\"Probability\"].iloc[\n", + " # bitfield_to_int([1] + list(self.target))\n", + " #]\n", + " probability_diff = measure_state_probability(\n", + " results, [1] + list(target)\n", + " )\n", + " \n", + " return (probability_sum - probability_diff) / (4 * shift)\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "89406be8-c081-46b3-aee7-4cb067713eeb", + "metadata": {}, + "source": [ + "## 7. Ideal Solution\n", + "\n", + "In order to get the ideal solution we need to instantiate a ideal qpu. For loading a ideal qpu we can use the typical **get_qpu** from **QQuantLib.qpu** package. In order to have a better integration between ideal QPUs and noisy QPUs a wrapper function called *select_qpu* inside of the **QQuantLib.qpu.select_qpu** module was implemented. \n", + "\n", + "The input of the *select_qpu* function is a dictionary like the used for configuring a noise model:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "590614bf-994c-41c7-8ca9-115038de0cef", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from QQuantLib.qpu.select_qpu import select_qpu" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0fce1c0b-3369-4981-81b4-59caec0d42f2", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "qpus = [\"c\", \"python\", \"linalg\", \"mps\", \"qlmass_linalg\", \"qlmass_mps\"]\n", + "conf_ideal = [{\n", + " \"qpu_type\": [qpus[2]],\n", + " \"t_gate_1qb\" : [None],\n", + " \"t_gate_2qbs\" : [None],\n", + " \"t_readout\": [None],\n", + " \"depol_channel\" : [{\n", + " \"active\": False,\n", + " \"error_gate_1qb\" : None,\n", + " \"error_gate_2qbs\" : None\n", + " }],\n", + " \"idle\" : [{\n", + " \"amplitude_damping\": False,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : None,\n", + " \"t2\" : None\n", + " }],\n", + " \"meas\": [{\n", + " \"active\":False,\n", + " \"readout_error\": None\n", + " }]\n", + "}]\n", + "\n", + "# We use the combination_for_list for getting the proper format for the dictionary\n", + "ideal_qpu_conf = combination_for_list(conf_ideal)[0]\n", + "print(ideal_qpu_conf)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e3ab16e-c5a6-4cd5-8112-b62db34561b1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ideal_qpu = select_qpu(ideal_qpu_conf)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4fa48787-6dce-4cf4-a366-62c802a5c9ac", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Ideal Solution\n", + "ideal_meas = first_step(routine, ideal_qpu, 0, rqae_object.target, shift, gamma_i, rqae_object)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cbaac171-a8d3-4799-ac66-cdd1a1d8378a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ideal_meas" + ] + }, + { + "cell_type": "markdown", + "id": "0d6b09c7-3f49-42f0-a9ee-d75ff81b7a1a", + "metadata": {}, + "source": [ + "## 8. Solution with Noisy hardware\n", + "\n", + "For simulating the noisy hardware we need to configure the noisy hardware model and create a noisy QPU. This can be done with the *create_qpu* from **QQuantLib.qpu.model_noise**. However we recommend to use the wrapper function *select_qpu* from **QQuantLib.qpu.select_qpu** module " + ] + }, + { + "cell_type": "markdown", + "id": "27f44a1d-74d4-451c-aed4-cc48b9e1bffd", + "metadata": {}, + "source": [ + "### 8.1 No Noise and Toffoli rewritter\n", + "\n", + "We can use an ideal qpu but ask for a rewritting of toffolis to 1 and 2 qubits gates. This can be by configuring the noise dictionary in the following way:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b0425ee-21e5-4254-a014-362b7f22fc33", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ideal_toffoli_rewritter = [{\n", + " \"qpu_type\": [\"ideal\"],\n", + " \"t_gate_1qb\" : [None],\n", + " \"t_gate_2qbs\" : [None],\n", + " \"t_readout\": [None],\n", + " \"depol_channel\" : [{\n", + " \"active\": False,\n", + " \"error_gate_1qb\" : None,\n", + " \"error_gate_2qbs\" : None\n", + " }],\n", + " \"idle\" : [{\n", + " \"amplitude_damping\": False,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : None,\n", + " \"t2\" : None\n", + " }],\n", + " \"meas\": [{\n", + " \"active\":False,\n", + " \"readout_error\": None\n", + " }]\n", + "}]\n", + "conf_ideal_no_toffoli = combination_for_list(ideal_toffoli_rewritter)[0]\n", + "conf_ideal_no_toffoli" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79f439dc-951f-496e-a44d-ddfd055b0aaf", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ideal_qpu_toffoli_rew = select_qpu(conf_ideal_no_toffoli)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fb8b186-beb9-40df-84e5-33bc6651f705", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Original Circuit has Toffolis\n", + "%qatdisplay routine --depth" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e633d778-383e-4f88-a1e6-ac114e176167", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Compile circuit for rewrite toffolis\n", + "from qat.core import Job, Batch\n", + "batch = Batch(jobs=[routine.to_circ().to_job()])\n", + "new_circ = ideal_qpu_toffoli_rew.compile(batch).jobs[0].circuit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21623c0e-487f-4656-bb35-1dfd9deaa675", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# New circuit has not Toffolis\n", + "%qatdisplay new_circ --svg" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c5554fe-b4cb-4b47-b023-515d6c995f2a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# deal soltuion. No Toffoli circuit\n", + "ideal_no_toffoli_meas = first_step(routine, ideal_qpu_toffoli_rew, 0, rqae_object.target, shift, gamma_i, rqae_object)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "934dcc88-611a-4fb5-b627-2e83a02dfa51", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#Shoud be simmilar\n", + "ideal_no_toffoli_meas, ideal_meas" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aeff7dc0-24cd-4e40-8d4e-097fba17d919", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "np.abs(ideal_no_toffoli_meas-ideal_meas)" + ] + }, + { + "cell_type": "markdown", + "id": "8e193c8c-bff8-4dcc-8276-28e38a817027", + "metadata": { + "tags": [] + }, + "source": [ + "### 8.2 Depolarizing channel" + ] + }, + { + "cell_type": "markdown", + "id": "2961c7cd-5500-45b5-82d2-f22716506b6c", + "metadata": { + "tags": [] + }, + "source": [ + "### Toshiko\n", + "\n", + "T1 = 50 # us\n", + "T2= 30 # us\n", + "F1 = 99.9 # %\n", + "F2 = 92 # %\n", + "F_ro = 90 # %" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99a831f2-bbc6-4182-a2f0-0afd7ca59a54", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Configuring test for Deploarizing channel\n", + "conf_noise = [{\n", + " \"qpu_type\": [\"noisy\"],\n", + " \"t_gate_1qb\" : [35],\n", + " \"t_gate_2qbs\" : [660],\n", + " \"t_readout\": [0],\n", + " \"depol_channel\" : [\n", + " {\n", + " \"active\": True,\n", + " \"error_gate_1qb\" : 1.0e-9,\n", + " \"error_gate_2qbs\" : 1.0e-8\n", + " },\n", + " {\n", + " \"active\": True,\n", + " \"error_gate_1qb\" : 1.0e-8,\n", + " \"error_gate_2qbs\" : 1.0e-7\n", + " }, \n", + " {\n", + " \"active\": True,\n", + " \"error_gate_1qb\" : 1.0e-7,\n", + " \"error_gate_2qbs\" : 1.0e-6\n", + " }, \n", + " {\n", + " \"active\": True,\n", + " \"error_gate_1qb\" : 1.0e-6,\n", + " \"error_gate_2qbs\" : 1.0e-5\n", + " }, \n", + " {\n", + " \"active\": True,\n", + " \"error_gate_1qb\" : 1.0e-5,\n", + " \"error_gate_2qbs\" : 1.0e-4\n", + " }, \n", + " {\n", + " \"active\": True,\n", + " \"error_gate_1qb\" : 2.27e-4, # brisbane\n", + " \"error_gate_2qbs\" : 7.741e-3 # brisbane\n", + " }, \n", + " {\n", + " \"active\": True,\n", + " \"error_gate_1qb\" : 0.001, # Toshiko\n", + " \"error_gate_2qbs\" : 0.08 # Toshiko\n", + " }, \n", + " ],\n", + " \"idle\" : [{\n", + " \"amplitude_damping\": False,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : None,\n", + " \"t2\" : None\n", + " }],\n", + " \"meas\": [{\n", + " \"active\":False,\n", + " \"readout_error\": None\n", + " }]\n", + "}]\n", + "# Now we have a list with different dictionaries\n", + "noisy_conf_list = combination_for_list(conf_noise)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb06c24d-d5af-45e2-8cb8-bef0cd3ecdd1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Now we are going to solve the circuit with all the different depolarising channel configurations\n", + "a_depol = []\n", + "\n", + "error1 = []\n", + "for hw_m in noisy_conf_list:\n", + " my_noisy_qpu = select_qpu(hw_m)\n", + " print(hw_m)\n", + " error1.append(hw_m[\"depol_channel\"][\"error_gate_1qb\"])\n", + " step = first_step(routine, my_noisy_qpu, 0, rqae_object.target, shift, gamma_i, rqae_object)\n", + " a_depol.append(step)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "076a85f2-b44f-42bc-8aa6-7ea311797d21", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(error1, np.abs(a_depol - ideal_no_toffoli_meas), '-o')\n", + "#plt.axhline(medida_no_toffoli, c='r')\n", + "plt.yscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(\"Error 1 qubit gate\")\n", + "plt.ylabel(r\"$\\hat{a}-a_{ideal}$\")\n", + "plt.title(\"k=0. Only depolarizing channel. No iddle qubit\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81227266-0c70-47c3-ba07-14202946a850", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(error1, a_depol, '-o')\n", + "plt.axhline(ideal_no_toffoli_meas, c='r')\n", + "#plt.yscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(\"Error 1 qubit gate\")\n", + "plt.ylabel(r\"$\\hat{a}$\")\n", + "plt.title(\"k=0. Only depolarizing channel. No iddle qubit\")" + ] + }, + { + "cell_type": "markdown", + "id": "454696a9-f71d-4538-8657-b314d81ebd98", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "### 8.3 Amplitude Damping Channel (No Dephasing)" + ] + }, + { + "cell_type": "markdown", + "id": "a23ba314-384a-4a34-b275-980eeef96edc", + "metadata": { + "tags": [] + }, + "source": [ + "### Toshiko\n", + "\n", + "T1 = 50 # us\n", + "T2= 30 # us\n", + "F1 = 99.9 # %\n", + "F2 = 92 # %\n", + "F_ro = 90 # %" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf63f1dd-64a8-4dc5-884e-139d8da60d19", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "conf_noise = [{\n", + " \"qpu_type\": [\"noisy\"],\n", + " \"t_gate_1qb\" : [35],\n", + " \"t_gate_2qbs\" : [660],\n", + " \"t_readout\": [0],\n", + " \"depol_channel\" : [\n", + " {\n", + " \"active\": False,\n", + " \"error_gate_1qb\" : None,\n", + " \"error_gate_2qbs\" : None\n", + " } \n", + " ],\n", + " \"idle\" : [\n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : 1000e6,\n", + " \"t2\" : None\n", + " },\n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : 100e6,\n", + " \"t2\" : None\n", + " }, \n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : 10e6,\n", + " \"t2\" : None\n", + " }, \n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : 1e6,\n", + " \"t2\" : None\n", + " }, \n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : 0.231e6, # brisbane\n", + " \"t2\" : None \n", + " }, \n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : 50e3, # Toshiko: 50 us\n", + " \"t2\" : None \n", + " } \n", + " ],\n", + " \"meas\": [{\n", + " \"active\":False,\n", + " \"readout_error\": None\n", + " }]\n", + "}]\n", + "noisy_conf_list = combination_for_list(conf_noise)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2979c3a6-65a0-4960-8b85-83322e9284e0", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "a_ad = []\n", + "\n", + "error1 = []\n", + "for hw_m in noisy_conf_list:\n", + " my_noisy_qpu = select_qpu(hw_m)\n", + " print(hw_m)\n", + " error1.append(hw_m[\"idle\"][\"t1\"])\n", + " step = first_step(routine, my_noisy_qpu, 0, rqae_object.target, shift, gamma_i, rqae_object)\n", + " a_ad.append(step)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d89c25d7-1871-43c6-8973-5235c3c62fab", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "plt.plot(error1, ideal_no_toffoli_meas - a_ad, '-o')\n", + "#plt.axhline(medida_no_toffoli, c='r')\n", + "#plt.yscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(\"T1 (ns)\")\n", + "plt.ylabel(r\"$\\hat{a}-a_{ideal}$\")\n", + "plt.title(\"k=0. Only Amplitude Damping. Ideal Gates\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e257a2da-c2c0-472b-b18a-c9089e9d2ef8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(error1, a_ad, '-o')\n", + "plt.axhline(ideal_no_toffoli_meas, c='r')\n", + "#plt.yscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(\"T1 (ns)\")\n", + "plt.ylabel(r\"$\\hat{a}$\")\n", + "plt.title(\"k=0. Only depolarizing channel. No iddle qubit\")" + ] + }, + { + "cell_type": "markdown", + "id": "a11ee806-27d9-4cd9-bf8e-668f6320b014", + "metadata": {}, + "source": [ + "### 8.4 Amplitude Damping and Dephasing Channels" + ] + }, + { + "cell_type": "markdown", + "id": "80d46c0e-771b-4d7a-9fba-09175c4fc204", + "metadata": { + "tags": [] + }, + "source": [ + "### Toshiko\n", + "\n", + "T1 = 50 # us\n", + "T2= 30 # us\n", + "F1 = 99.9 # %\n", + "F2 = 92 # %\n", + "F_ro = 90 # %" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8100dd84-bd6b-47b0-91fc-dd682fee3e41", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "conf_noise = [{\n", + " \"qpu_type\": [\"noisy\"],# Palabara para generar qpus ruidosas\n", + " \"t_gate_1qb\" : [35],\n", + " \"t_gate_2qbs\" : [660],\n", + " \"t_readout\": [0],\n", + " \"depol_channel\" : [\n", + " {\n", + " \"active\": False,\n", + " \"error_gate_1qb\" : None,\n", + " \"error_gate_2qbs\" : None\n", + " } \n", + " ],\n", + " \"idle\" : [\n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": True,\n", + " \"t1\" : 1000e6,\n", + " \"t2\" : 500e6\n", + " },\n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": True,\n", + " \"t1\" : 100e6,\n", + " \"t2\" : 50e6\n", + " }, \n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": True,\n", + " \"t1\" : 10e6,\n", + " \"t2\" : 5e6\n", + " }, \n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": True,\n", + " \"t1\" : 1e6,\n", + " \"t2\" : 0.5e6\n", + " }, \n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": True,\n", + " \"t1\" : 0.231e6, # brisbane\n", + " \"t2\" : 0.132e6 # brisbane\n", + " }, \n", + " {\n", + " \"amplitude_damping\": True,\n", + " \"dephasing_channel\": True,\n", + " \"t1\" : 50e3, # Toshiko: 50 us\n", + " \"t2\" : 30e3 # Toshiko: 30 us\n", + " }, \n", + " ],\n", + " \"meas\": [{\n", + " \"active\":False,\n", + " \"readout_error\": None\n", + " }]\n", + "}]\n", + "noisy_conf_list = combination_for_list(conf_noise)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "323612f8-466b-4779-a646-2f847b4bc76a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "a_ad_d = []\n", + "\n", + "error1 = []\n", + "for hw_m in noisy_conf_list:\n", + " my_noisy_qpu = select_qpu(hw_m)\n", + " print(hw_m)\n", + " error1.append(hw_m[\"idle\"][\"t1\"])\n", + " step = first_step(routine, my_noisy_qpu, 0, rqae_object.target, shift, gamma_i, rqae_object)\n", + " a_ad_d.append(step)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "730e9c40-9819-4939-b6a1-13c4bdb14d72", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(error1, np.abs(a_ad_d - ideal_no_toffoli_meas), '-o')\n", + "#plt.axhline(medida_no_toffoli, c='r')\n", + "plt.yscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(\"T1 (ns)\")\n", + "plt.ylabel(r\"$\\hat{a}-a_{ideal}$\")\n", + "plt.title(\"k=0. Amplitude Damping and Dephasing. Ideal Gates\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5625c9d1-0409-4508-8e8f-a0e1e8ea0d5f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(error1, a_ad_d, '-o')\n", + "plt.axhline(ideal_no_toffoli_meas, c='r')\n", + "plt.yscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(\"T1 (ns)\")\n", + "plt.ylabel(r\"$\\hat{a}$\")\n", + "plt.title(\"k=0. Amplitude Damping and Dephasing. Ideal Gates\")" + ] + }, + { + "attachments": { + "2bd71b2c-9576-4106-a83c-ba16680fcf30.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "id": "65550258-558d-4eff-a4b8-911f058e9599", + "metadata": {}, + "source": [ + "![image.png](attachment:2bd71b2c-9576-4106-a83c-ba16680fcf30.png)" + ] + }, + { + "cell_type": "markdown", + "id": "849971a3-1a1c-4cab-9098-bfe03524a10b", + "metadata": {}, + "source": [ + "### 8.5 Redout error" + ] + }, + { + "cell_type": "markdown", + "id": "421b48d3-a4cd-4b8f-83bb-92d60bc3b120", + "metadata": { + "tags": [] + }, + "source": [ + "### Toshiko\n", + "\n", + "T1 = 50 # us\n", + "T2= 30 # us\n", + "F1 = 99.9 # %\n", + "F2 = 92 # %\n", + "F_ro = 90 # %" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2594a2fe-d13d-4a17-867d-c70944d8ff36", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "conf_noise = [{\n", + " \"qpu_type\": [\"noisy\"],\n", + " \"t_gate_1qb\" : [35],\n", + " \"t_gate_2qbs\" : [660],\n", + " \"t_readout\": [0],\n", + " \"depol_channel\" : [\n", + " {\n", + " \"active\": False,\n", + " \"error_gate_1qb\" : None,\n", + " \"error_gate_2qbs\" : None\n", + " } \n", + " ],\n", + " \"idle\" : [\n", + " {\n", + " \"amplitude_damping\": False,\n", + " \"dephasing_channel\": False,\n", + " \"t1\" : None,\n", + " \"t2\" : None\n", + " } \n", + " ],\n", + " \"meas\": [\n", + " {\n", + " \"active\":True,\n", + " \"readout_error\": 1e-6\n", + " },\n", + " {\n", + " \"active\":True,\n", + " \"readout_error\": 1e-5\n", + " },\n", + " {\n", + " \"active\":True,\n", + " \"readout_error\": 1e-4\n", + " }, \n", + " {\n", + " \"active\":True,\n", + " \"readout_error\": 1e-3\n", + " }, \n", + " {\n", + " \"active\":True,\n", + " \"readout_error\": 1.300e-2 # brisbane\n", + " },\n", + " {\n", + " \"active\":True,\n", + " \"readout_error\": 0.1 #Toshiko\n", + " } \n", + " ]\n", + "}]\n", + "noisy_conf_list = combination_for_list(conf_noise)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9207b9c8-4f92-4eb3-8383-833c9c87d839", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "a_read = []\n", + "\n", + "error1 = []\n", + "for hw_m in noisy_conf_list:\n", + " my_noisy_qpu = select_qpu(hw_m)\n", + " print(hw_m)\n", + " error1.append(hw_m[\"meas\"][\"readout_error\"])\n", + " step = first_step(routine, my_noisy_qpu, 0, rqae_object.target, shift, gamma_i, rqae_object)\n", + " a_read.append(step)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c7e5e23-a03b-49b2-bf91-bc83f41cca54", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(error1, np.abs(a_read - ideal_no_toffoli_meas), '-o')\n", + "#plt.axhline(medida_no_toffoli, c='r')\n", + "plt.yscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(\"Readout Error\")\n", + "plt.ylabel(r\"$\\hat{a}-a_{ideal}$\")\n", + "plt.title(\"k=0. Only Readout Error.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3edd547-1dde-4880-8097-b348fe8b2b12", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.plot(error1, a_read, '-o')\n", + "plt.axhline(ideal_no_toffoli_meas, c='r')\n", + "#plt.yscale(\"log\")\n", + "plt.xscale(\"log\")\n", + "plt.xlabel(\"Readout Error\")\n", + "plt.ylabel(r\"$\\hat{a}$\")\n", + "plt.title(\"k=0. Only Readout Error.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ddc2ca3-a5fc-4fb6-a93f-8a59f64f0976", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.16" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/REAME.md b/tnbs/BTC_02_AE/QQuantLib/qpu/REAME.md new file mode 100644 index 0000000..8a7665c --- /dev/null +++ b/tnbs/BTC_02_AE/QQuantLib/qpu/REAME.md @@ -0,0 +1,3 @@ +# Noisy Models + +At the momement the noisy models from model_noise can be only used in a QLM. diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/__init__.py b/tnbs/BTC_02_AE/QQuantLib/qpu/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/get_qpu.py b/tnbs/BTC_02_AE/QQuantLib/qpu/get_qpu.py new file mode 100644 index 0000000..2594f11 --- /dev/null +++ b/tnbs/BTC_02_AE/QQuantLib/qpu/get_qpu.py @@ -0,0 +1,84 @@ +""" +This module implements the get_qpu function that allows to the user +select a **EVIDEN QPU** for ideal simulation. The qpu variable is a +string that should take some of the following values: + + + **qlmass_linalg**. + For selecting the linear algebra simulator LinAlg. This QPU + can be used only with QaptivaÔäó Appliance when the user sends the computations to a remote QPU. The user must have remote + access to a remote QLM using the Qaptiva Access (QLM as a Service) + library. + **qlmass_mps**. + For selecting the Matrix Product State (MPS) simulator. This QPU + can be used only with QaptivaÔäó Appliance when the user sends the computations to a remote QPU. The user must have remote + access to a remote QLM using the Qaptiva Access (QLM as a Service) + library. + **python**. + For selecting the linear algebra simulator PyLinalg. This a pure + Python algebra simulator. This QPU is provided by the myQLM + library. It can not be used with QaptivaÔäó Appliance. + **c** + For selecting the linear algebra simulator CLinalg. This a pure + C algebra simulator. This QPU is provided by the myQLM + library. It can not be used with QaptivaÔäó Appliance. + **linalg** + For selecting the linear algebra simulator LinAlg. This QPU + can be used only with QaptivaÔäó Appliance when the user is locally + in a QLM. + **mps** + For selecting the Matrix Product State (MPS) simulator This QPU + can be used only with QaptivaÔäó Appliance when the user is locally + in a QLM. +""" + +def get_qpu(qpu=None): + """ + Function for selecting solver. + + Parameters + ---------- + + qpu : str + string with the desired qpu + + Returns + ---------- + + linal_qpu : solver for quantum jobs + """ + + if qpu is None: + raise ValueError( + "qpu CAN NOT BE NONE. Please select one of the three" + + " following options: qlmass, python, c") + if qpu == "qlmass_linalg": + try: + from qlmaas.qpus import LinAlg + linalg_qpu = LinAlg() + except (ImportError, OSError) as exception: + raise ImportError( + "Problem Using QLMaaS. Please create config file" + + "or use mylm solver") from exception + elif qpu == "qlmass_mps": + try: + from qlmaas.qpus import MPS + #linalg_qpu = MPS(lnnize=True) + linalg_qpu = MPS() + except (ImportError, OSError) as exception: + raise ImportError( + "Problem Using QLMaaS. Please create config file" + + "or use mylm solver") from exception + elif qpu == "python": + from qat.qpus import PyLinalg + linalg_qpu = PyLinalg() + elif qpu == "c": + from qat.qpus import CLinalg + linalg_qpu = CLinalg() + elif qpu == "linalg": + from qat.qpus import LinAlg + linalg_qpu = LinAlg() + elif qpu == "mps": + from qat.qpus import MPS + linalg_qpu = MPS() + return linalg_qpu diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/model_noise.py b/tnbs/BTC_02_AE/QQuantLib/qpu/model_noise.py new file mode 100644 index 0000000..b2258b2 --- /dev/null +++ b/tnbs/BTC_02_AE/QQuantLib/qpu/model_noise.py @@ -0,0 +1,169 @@ +""" +This module implements several functions for configuring a noisy +hardware model for creating the corresponding noisy qpu. +**BE AWARE** +The functions of this module can be only used with the Qaptiva™ Appliance +and when the user is locally in a QLM. The Qaptiva Access library **CAN +NOT BE** used with these functions. +""" + +import numpy as np + +# Obtenido de ibm_brisbane: 2024/04/04 +# error_gate_1qb = 2.27e-4 +# error_gate_2qbs = 7.741e-3 +# t_gate_1qb = 35 #ns +# t_gate_2qbs = 660 #ns +# t1 = 231.94e3 +# t2 = 132.71e3 + +def set_gate_times(t_gate_1qb=35, t_gate_2qbs=660, t_readout=4000): + """ + Set the gate times for a noise model. + + Parameters + ---------- + + t_gate_1qb : int + time for 1 qubit gate length in ns + t_gate_2qbs : int + time for 2 qubits gate length in ns + t_readout : int + time for readout gate in ns + + Return + ------ + + gate_time_dict : dict + dictionary with the default gates and their time length + + """ + from qat.hardware import DefaultHardwareModel + from qat.hardware.default import _CtrlParametricChannel, _ParametricChannel + from qat.quops.quantum_channels import QuantumChannelKraus + hw_m = DefaultHardwareModel() + gate_time_dict = {} + for gate, value in hw_m.gates_specification.quantum_channels.items(): + if gate not in ["measure", "reset", "logic"]: + if isinstance(value, _CtrlParametricChannel): + gate_time_dict.update({gate: lambda angle: t_gate_2qbs}) + if isinstance(value, _ParametricChannel): + gate_time_dict.update({gate: lambda angle: t_gate_1qb}) + if isinstance(value, QuantumChannelKraus): + if value.arity == 1: + gate_time_dict.update({gate: t_gate_1qb}) + if value.arity == 2: + gate_time_dict.update({gate: t_gate_2qbs}) + else: + if gate == "measure": + gate_time_dict.update({gate: t_readout}) + return gate_time_dict + +def noisy_hw_model(hw_cfg): + """ + My noisy hardware model: It is composed by 3 types of noise channels: + Amplitude Damping and Dephasing channels for idle qubits + Depolarizing channel applied after any gate. + + Parameters + ---------- + + hw_cfg : dict + Python dictionary with parameters for the noisy hardware: + * error_gate_1qb : Error for 1-qubit gate (for Depolarizing channel) + * error_gate_2qbs: Error for 2-qubits gates (for Depolarizing channel) + * t_gate_1qb : duration time in nanoseconds for 1 qubit gates + * t_gate_2qbs : duration time in nanoseconds for 2 qubit gates + * t1 : T1 time in nanoseconds (Amplitude Damping and Dephasing channels) + * t2 : T2 time in nanoseconds (Dephasing channel) + + Return + ------ + + my_hw_model : Qaptiva HardwareModel + my HardwareModel definition + """ + t_gate_1qb = hw_cfg.get("t_gate_1qb", 35) + t_gate_2qbs = hw_cfg.get("t_gate_2qbs", 660) + t_readout = hw_cfg.get("t_readout", 4000) + #Gates Specification + gate_time_dict = set_gate_times(t_gate_1qb, t_gate_2qbs, t_readout) + depol_channel = hw_cfg.get("depol_channel") + if depol_channel["active"]: + from qat.hardware import make_depolarizing_hardware_model + # Hardware model for depolarizing channel + error_gate_1qb = depol_channel.get("error_gate_1qb", 2.27e-4) + error_gate_2qbs = depol_channel.get("error_gate_2qbs", 7.741e-3) + my_hw_model = make_depolarizing_hardware_model( + eps1=error_gate_1qb, eps2=error_gate_2qbs + ) + else: + from qat.hardware import DefaultHardwareModel + my_hw_model = DefaultHardwareModel() + # Setting time for the gates + my_hw_model.gates_specification.gate_times.update(gate_time_dict) + idle = hw_cfg.get("idle") + idle_noise_list = [] + if idle["amplitude_damping"]: + from qat.quops import ParametricAmplitudeDamping + # Setting AmplitudeDamping iddle channel + t1 = idle.get("t1", 231.94e3) + idle_noise_list.append(ParametricAmplitudeDamping(T_1=t1)) + if idle["dephasing_channel"]: + from qat.quops import ParametricPureDephasing + # Setting Dephasing iddle channel + t2 = idle.get("t2", 132.71e3) + tphi = 1/(1/t2 - 1/(2 * t1)) + idle_noise_list.append(ParametricPureDephasing(T_phi=tphi)) + # Setting idle channels + my_hw_model.idle_noise = idle_noise_list + meas = hw_cfg.get("meas") + if meas["active"]: + # Setting Measurement noise channel + readout_error = meas["readout_error"] + meas_prep = np.array([[readout_error, 0.0],[0.0, 1.0-readout_error]]) + my_hw_model.gates_specification.meas = meas_prep + return my_hw_model + +def create_qpu(hw_cfg): + """ + Create QPU. Using an input hardware configuration this function creates + a QPU. It could be a noisy or a ideal qpu depending on the value of the key + qpu of the hw_cfg dictionary. Additionally adds a plugin for rewiting the + Toffolis using CNOTS and local gates. + + Parameters + ---------- + + hw_cfg : dict + Python dictionary with parameters for configuring the QPU + * qpu : If noisy the function creates a Noisy QPU. Else create the corresponding ideal QPU. + * error_gate_1qb : Error for 1-qubit gate (for Depolarizing channel) + * error_gate_2qbs: Error for 2-qubits gates (for Depolarizing channel) + * t_gate_1qb : duration time in nanoseconds for 1 qubit gates + * t_gate_2qbs : duration time in nanoseconds for 2 qubit gates + * t1 : T1 time in nanoseconds (Amplitude Damping and Dephasing channels) + * t2 : T2 time in nanoseconds (Dephasing channel) + Return + ------ + + my_qpu : Qaptiva QPU + generated QPU (can be a noisy one) + """ + + from qat.synthopline.compiler import EXPANSION_COLLECTION + from qat.pbo import PatternManager + from qat.qpus import NoisyQProc, LinAlg + # Rewritter for Toffolis + toffoli_plugin = PatternManager(collections=[EXPANSION_COLLECTION[:1]]) + if hw_cfg["qpu_type"] == "noisy": + model_noisy = noisy_hw_model(hw_cfg) + my_qpu= NoisyQProc( + hardware_model=model_noisy, + sim_method="deterministic-vectorized", + backend_simulator=LinAlg() + ) + else: + my_qpu = LinAlg() + my_qpu = toffoli_plugin | toffoli_plugin | my_qpu + return my_qpu diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/noise_test_bank_functions.py b/tnbs/BTC_02_AE/QQuantLib/qpu/noise_test_bank_functions.py new file mode 100644 index 0000000..681f624 --- /dev/null +++ b/tnbs/BTC_02_AE/QQuantLib/qpu/noise_test_bank_functions.py @@ -0,0 +1,109 @@ +""" +Auxiliary functions for using with the demo notebook: NoisyModels.ipynb +""" +import sys +import numpy as np +sys.path.append("../../") +from QQuantLib.DL.encoding_protocols import Encoding +from QQuantLib.finance.probability_class import DensityProbability +from QQuantLib.finance.payoff_class import PayOff + + + +def create_arrays(price_problem): + """ + This function creates the mandatory arrays for configuring an option + price estimation problem for notebook NoisyModels.ipynb + + Parameters + ---------- + + price_problem : dict + Python dictionary with a complete dictionary for configuring + the arrays for a option price estimation problem + + Returns + ------- + + domain : numpy array + numpy array with the domain for the price estimation problem + norm_pay_off : array + numpy array with the normalised payoff + norm_p_x : numpy array + numpy array with the normalised probability density + pay_off_normalisation : float + normalization constant for the payoff + p_x_normalisation : float + normalization constant for the probability density + + """ + n_qbits = price_problem.get("n_qbits", None) + x0 = price_problem.get("x0", 1.0) + xf = price_problem.get("xf", 3.0) + domain = np.linspace(x0, xf, 2**n_qbits) + #Building the Probability distribution + pc = DensityProbability(**price_problem) + p_x = pc.probability(domain) + #Normalisation of the probability distribution + p_x_normalisation = np.sum(p_x) + 1e-8 + norm_p_x = p_x / p_x_normalisation + #Building the option payoff + po = PayOff(**price_problem) + pay_off = po.pay_off(domain) + #Normalisation of the pay off + pay_off_normalisation = np.max(np.abs(pay_off)) + 1e-8 + norm_pay_off = pay_off / pay_off_normalisation + return domain, norm_pay_off, norm_p_x, pay_off_normalisation, p_x_normalisation + + +def first_step(epsilon, ratio, gamma): + """ + Configuration of the first step for a RQAE algorithm. This is an + auxiliary function for notebook NoisyModels.ipynb + + Parameters + ---------- + + epsilon : float + epsilon for RQAE + ratio : float + ratio (q) for RQAE + gamma : float + gamma for RQAE + + Returns + ------- + + shift : float + shift for first step of RQAE + n_i : int + number of shots for first step of RQAE + gamma_i : float + failure probability for first step of RQAE + theoretical_epsilon : float + theoretical epsilon for first step of RQAE + """ + epsilon = 0.5 * epsilon + theoretical_epsilon = 0.5 * np.sin(np.pi / (2 * (ratio + 2))) ** 2 + k_max = int( + np.ceil( + np.arcsin(np.sqrt(2 * theoretical_epsilon)) + / np.arcsin(2 * epsilon) + * 0.5 + - 0.5 + ) + ) + bigk_max = 2 * k_max + 1 + big_t = np.log( + ratio + * ratio + * (np.arcsin(np.sqrt(2 * theoretical_epsilon))) + / (np.arcsin(2 * epsilon)) + ) / np.log(ratio) + gamma_i = gamma / big_t + n_i = int( + np.ceil(1 / (2 * theoretical_epsilon**2) * np.log(2 * big_t / gamma)) + ) + epsilon_probability = np.sqrt(1 / (2 * n_i) * np.log(2 / gamma_i)) + shift = theoretical_epsilon / np.sin(np.pi / (2 * (ratio + 2))) + return shift, n_i, gamma_i, theoretical_epsilon diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/qpu_ideal.json b/tnbs/BTC_02_AE/QQuantLib/qpu/qpu_ideal.json new file mode 100644 index 0000000..98aad11 --- /dev/null +++ b/tnbs/BTC_02_AE/QQuantLib/qpu/qpu_ideal.json @@ -0,0 +1,24 @@ + +[ + { + "qpu_type": ["c", "python", "linalg", "mps", "qlmass_linalg", "qlmass_mps"], + "t_gate_1qb" : [null], + "t_gate_2qbs" : [null], + "t_readout": [null], + "depol_channel" : [{ + "active": false, + "error_gate_1qb" : null, + "error_gate_2qbs" : null + }], + "idle" : [{ + "amplitude_damping": false, + "dephasing_channel": false, + "t1" : null, + "t2" : null + }], + "meas": [{ + "active":false, + "readout_error": null + }] + } +] diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/qpu_noisy.json b/tnbs/BTC_02_AE/QQuantLib/qpu/qpu_noisy.json new file mode 100644 index 0000000..9b3f7df --- /dev/null +++ b/tnbs/BTC_02_AE/QQuantLib/qpu/qpu_noisy.json @@ -0,0 +1,192 @@ + +[ + { + "qpu_type": ["ideal"], + "t_gate_1qb" : [null], + "t_gate_2qbs" : [null], + "t_readout": [null], + "depol_channel" : [{ + "active": false, + "error_gate_1qb" : null, + "error_gate_2qbs" : null + }], + "idle" : [{ + "amplitude_damping": false, + "dephasing_channel": false, + "t1" : null, + "t2" : null + }], + "meas": [{ + "active":false, + "readout_error": null + }] + }, + { + "qpu_type": ["noisy"], + "t_gate_1qb" : [35], + "t_gate_2qbs" : [660], + "t_readout": [4000], + "depol_channel" : [{ + "active": true, + "error_gate_1qb" : 1.0e-4, + "error_gate_2qbs" : 1.0e-3 + }], + "idle" : [{ + "amplitude_damping": false, + "dephasing_channel": false, + "t1" : null, + "t2" : null + }], + "meas": [{ + "active":false, + "readout_error": null + }] + }, + { + "qpu_type": ["noisy"], + "t_gate_1qb" : [35], + "t_gate_2qbs" : [660], + "t_readout": [4000], + "depol_channel" : [{ + "active": true, + "error_gate_1qb" : 1.0e-4, + "error_gate_2qbs" : 1.0e-3 + }], + "idle" : [{ + "amplitude_damping": true, + "dephasing_channel": false, + "t1" : 0.2e6, + "t2" : null + }], + "meas": [{ + "active":false, + "readout_error": null + }] + }, + { + "qpu_type": ["noisy"], + "t_gate_1qb" : [35], + "t_gate_2qbs" : [660], + "t_readout": [4000], + "depol_channel" : [{ + "active": true, + "error_gate_1qb" : 1.0e-4, + "error_gate_2qbs" : 1.0e-3 + }], + "idle" : [{ + "amplitude_damping": false, + "dephasing_channel": true, + "t1" : 0.2e6, + "t2" : 0.1e6 + }], + "meas": [{ + "active":false, + "readout_error": null + }] + }, + { + "qpu_type": ["noisy"], + "t_gate_1qb" : [35], + "t_gate_2qbs" : [660], + "t_readout": [4000], + "depol_channel" : [{ + "active": true, + "error_gate_1qb" : 1.0e-4, + "error_gate_2qbs" : 1.0e-3 + }], + "idle" : [{ + "amplitude_damping": true, + "dephasing_channel": true, + "t1" : 0.2e6, + "t2" : 0.1e6 + }], + "meas": [{ + "active":false, + "readout_error": null + }] + }, + { + "qpu_type": ["noisy"], + "t_gate_1qb" : [35], + "t_gate_2qbs" : [660], + "t_readout": [4000], + "depol_channel" : [{ + "active": true, + "error_gate_1qb" : 1.0e-4, + "error_gate_2qbs" : 1.0e-3 + }], + "idle" : [{ + "amplitude_damping": false, + "dephasing_channel": false, + "t1" : null, + "t2" : null + }], + "meas": [{ + "active":true, + "readout_error": 1.370e-2 + }] + }, + { + "qpu_type": ["noisy"], + "t_gate_1qb" : [35], + "t_gate_2qbs" : [660], + "t_readout": [4000], + "depol_channel" : [{ + "active": true, + "error_gate_1qb" : 1.0e-4, + "error_gate_2qbs" : 1.0e-3 + }], + "idle" : [{ + "amplitude_damping": true, + "dephasing_channel": true, + "t1" : 0.2e6, + "t2" : 0.1e6 + }], + "meas": [{ + "active":true, + "readout_error": 1.370e-2 + }] + }, + { + "qpu_type": ["noisy"], + "t_gate_1qb" : [35], + "t_gate_2qbs" : [660], + "t_readout": [4000], + "depol_channel" : [{ + "active": false, + "error_gate_1qb" : null, + "error_gate_2qbs" : null + }], + "idle" : [{ + "amplitude_damping": true, + "dephasing_channel": true, + "t1" : 0.2e6, + "t2" : 0.1e6 + }], + "meas": [{ + "active":true, + "readout_error": 1.370e-2 + }] + }, + { + "qpu_type": ["noisy"], + "t_gate_1qb" : [35], + "t_gate_2qbs" : [660], + "t_readout": [4000], + "depol_channel" : [{ + "active": false, + "error_gate_1qb" : null, + "error_gate_2qbs" : null + }], + "idle" : [{ + "amplitude_damping": false, + "dephasing_channel": false, + "t1" : null, + "t2" : null + }], + "meas": [{ + "active":true, + "readout_error": 1.370e-2 + }] + } +] diff --git a/tnbs/BTC_02_AE/QQuantLib/qpu/select_qpu.py b/tnbs/BTC_02_AE/QQuantLib/qpu/select_qpu.py new file mode 100644 index 0000000..6a9c252 --- /dev/null +++ b/tnbs/BTC_02_AE/QQuantLib/qpu/select_qpu.py @@ -0,0 +1,131 @@ +""" +This module implements the select_qpu function that allows to the user +select a complete QPU. The input of this function is a Python dictionary +with the following keys: + + **qpu_type** + The value is a Python string for selecting the type of QPU. The + values can be: *c, python, linalg, mps, qlmass_linalg, qlmass_mps* + for using with pure ideal QPU (the get_qpu function from + QQuantLib.qpu.get_qpu module is used for getting the QPU). + Additionally, the values can be: *ideal* for using an ideal qpu + with a Toffoli rewritter pluging or *noisy* for configuring and + using a noisy QPU. In both cases the create_qpu function from + QQuantLib.qpu.model_noise module is used for creating the QPU. + + **t_gate_1qb** + For setting the time for the 1-qubit gates (in ns). Only valid + if *qpu_type* is noisy. + + **t_gate_2qbs** + For setting the time for the 2-qubit gates (in ns). Only valid + if *qpu_type* is noisy. + + **t_readout** + For setting the time for the measuring operations (in ns). Only + valid if *qpu_type* is noisy. + + **depol_channel** + For setting the parameters for a depolarizing channel. The value + is a complete dictionary with the following keys: **active** + the boolean key for activating or not the channel. **error_gate_1qb** + error for 1-qubit gates. **error_gate_2qbs** error for 2-qubits + gates. + + **idle** + For setting the parameters for idle qubits. The value is a + complete dictionary with the following keys: **amplitude_damping** + the boolean key for activating or not an Amplitude Damping channel. + **dephasing_channel** boolean key for activating or not a + Dephasing channel. **t1** time T1 of the qubits (in ns) + **t2** time T2 of the qubits (in nsa). + + **meas** + For setting the parameters for a measuring error. The value is a + complete dictionary with the following keys: **active** boolean + key for activating or not this error. **readout_error** measuring + error. +""" + +def select_qpu(hw_cfg): + """ + This function allows to select a QPU (a ideal or a noisy one). + + Parameters + ---------- + + hw_cfg : dict + Python dictionary for configuring a complete (ideal or noisy) + QPU. When an "ideal" QPU is selected the get_qpu from get_qpu + module is used. If a "noisy" QPU is selected then the differents + keys of the dictionary are used for configruing a noisy hardware + model using functions from model_noise module. + """ + + if hw_cfg["qpu_type"] in ["noisy", "ideal"]: + from QQuantLib.qpu.model_noise import create_qpu + qpu = create_qpu(hw_cfg) + else: + from QQuantLib.qpu.get_qpu import get_qpu + qpu = get_qpu(hw_cfg["qpu_type"]) + return qpu + +if __name__ == "__main__": + import json + import argparse + import sys + sys.path.append("../../") + from QQuantLib.utils.benchmark_utils import combination_for_list + + parser = argparse.ArgumentParser() + parser.add_argument( + "--count", + dest="count", + default=False, + action="store_true", + help="For counting elements on the list", + ) + parser.add_argument( + "--print", + dest="print", + default=False, + action="store_true", + help="For printing " + ) + parser.add_argument( + "-id", + dest="id", + type=int, + help="For executing only one element of the list", + default=None, + ) + parser.add_argument( + "-json_qpu", + dest="json_qpu", + type=str, + default="jsons/qpu.json", + help="JSON with the qpu configuration", + ) + parser.add_argument( + "--exe", + dest="execution", + default=False, + action="store_true", + help="For executing program", + ) + args = parser.parse_args() + print(args) + with open(args.json_qpu) as json_file: + noisy_cfg = json.load(json_file) + final_list = combination_for_list(noisy_cfg) + if args.count: + print(len(final_list)) + if args.print: + if args.id is not None: + print(final_list[args.id]) + else: + print(final_list) + if args.execution: + if args.id is not None: + print(select_qpu(final_list[args.id])) +