A sample implementation of solving linear system of equations using Qiskit's HHL implementation. The fluid flow use-cases are following the work of Bharadwaj & Srinivasan (2020). The implementations are using python scripts and Jupyter notebooks which use Quiskit libraries. See Qiskit it get started with installation to local conda environments. Or run on IBM quantum-computing platform.
-
Reference: M. Gopalakrishnan Meena, K. C. Gottiparthi, J. Lietz, A. Georgiadou, and E. A. Coello Pérez, "Solving the Hele-Shaw flow using the Harrow-Hassidim-Lloyd algorithm on superconducting devices: A study of efficiency and challenges," 2024
-
Contributors:
- Murali Gopalakrishnan Meena (Oak Ridge National Laboratory)
- Kalyan Gottiparthi (Oak Ridge National Laboratory)
- Justin Lietz (Oak Ridge National Laboratory; Now at NVIDIA)
-
[Optional] Steps for your own mini-conda installation
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p /path/to/your/local/dir/for/miniconda source /path/to/your/local/dir/for/miniconda/bin/activate
-
Make custom conda env
conda create --name env-qlsa python=3.11 conda activate env-qlsa
-
Install qiskit
pip install -r requirements.txt --no-cache-dir
-
Test qiskit installation:
test_qiskit_installation.py
python test_qiskit_installation.py -backtyp ideal
Click here for sample output from the test code
Backend: qasm_simulator Job status is JobStatus.DONE Total count for 00 and 11 are: {'11': 476, '00': 524} ┌───┐ ┌─┐ q_0: ┤ H ├──■──┤M├─── └───┘┌─┴─┐└╥┘┌─┐ q_1: ─────┤ X ├─╫─┤M├ └───┘ ║ └╥┘ c: 2/═══════════╩══╩═ 0 1
- Change
-backtyp
for different backends. - To run using IBM Provider, you need to add your IBM Quantum Computing API KEY and instance to the
keys.sh
file and source activate it. NOTE: You may have to port your codes to the latest Qiskit version for this.
- Change
-
Test linear solver package:
test_linear_solver.py
python test_linear_solver.py -nq 2
Click here for sample output from the test code:
Simulator: aer_simulator_statevector Time elapsed for classical: 0 min 0.00 sec Time elapsed for naive HHL: 0 min 0.53 sec Time elapsed for tridi-Toep: 0 min 1.68 sec classical state: [1.14545455 0.43636364 0.16363636 0.05454545] naive state: ┌──────────────┐┌──────┐ ┌─────────┐ q9_0: ┤0 ├┤4 ├────────┤4 ├ │ circuit-165 ││ │ │ │ q9_1: ┤1 ├┤5 ├────────┤5 ├ └──────────────┘│ │┌──────┐│ │ q10_0: ───────────────┤0 ├┤3 ├┤0 ├ │ QPE ││ ││ QPE_dg │ q10_1: ───────────────┤1 ├┤2 ├┤1 ├ │ ││ ││ │ q10_2: ───────────────┤2 ├┤1 1/x ├┤2 ├ │ ││ ││ │ q10_3: ───────────────┤3 ├┤0 ├┤3 ├ └──────┘│ │└─────────┘ q11: ───────────────-─────────┤4 ├─────────── └──────┘ tridiagonal state: ┌──────────────┐┌──────┐ ┌─────────┐ q82_0:┤0 ├┤4 ├────────┤4 ├ │ circuit-521 ││ │ │ │ q82_1:┤1 ├┤5 ├────────┤5 ├ └──────────────┘│ │┌──────┐│ │ q83_0:────────────────┤0 ├┤3 ├┤0 ├ │ ││ ││ │ q83_1:────────────────┤1 QPE ├┤2 ├┤1 QPE_dg ├ │ ││ ││ │ q83_2:────────────────┤2 ├┤1 ├┤2 ├ │ ││ 1/x ││ │ q83_3:────────────────┤3 ├┤0 ├┤3 ├ │ ││ ││ │ a1: ────────────────┤6 ├┤ ├┤6 ├ └──────┘│ │└─────────┘ q84: ────────────────────────┤4 ├─────────── └──────┘ classical Euclidean norm: 1.237833351044751 naive Euclidean norm: 1.2099806231118977 (diff (%): 2.250e+00) tridiagonal Euclidean norm: 1.2099204004859732 (diff (%): 2.255e+00) classical state: [1.14545455 0.43636364 0.16363636 0.05454545] full solution vector (naive): # of elements in solution vector: 128 [1.11266151 0.43866345 0.16004585 0.08942688] diff (%): [ 2.86288363 0.52703993 2.1942013 63.94928497] full solution vector (tridi): # of elements in solution vector: 256 [1.11261363 0.4386119 0.16005021 0.08945291] diff (%): [ 2.8670642 0.5152269 2.19153945 63.9969963 ] ===========Data not saved===========
- Change
-nq
to change size of system of equations.
- Change
- Load Python environemnt:
source /path/to/your/local/dir/for/miniconda/bin/activate conda activate env-qlsa
- Run generalized QLSA script for various use-cases:
linear_solver.py
python linear_solver.py -case sample-tridiag -casefile input_vars.yaml -s 1000
-
See
input_vars.yaml
andfunc_matrix_vector.py
for various cases available.Click here for sample output for Hele-Shaw flow, solving for pressure:
Case: Hele-Shaw Solving analytically... Solving numerically... =====Solving for pressure...===== Using analytical pressure profile... Determinant of resulting matrix: 1.0 Condition # of resulting matrix: 1.0 Determinant of resulting matrix: 1.0 Size of A & B are not power of 2: Next 2 power of 6 = 8 Value to be padded = 2 Padded shape of A: (6, 6) -> (8, 8) Padded shape of B: (6,) -> (8,) Padded A with diag 1: [[1. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0.] [0. 0. 1. 0. 0. 0. 0. 0.] [0. 0. 0. 1. 0. 0. 0. 0.] [0. 0. 0. 0. 1. 0. 0. 0.] [0. 0. 0. 0. 0. 1. 0. 0.] [0. 0. 0. 0. 0. 0. 1. 0.] [0. 0. 0. 0. 0. 0. 0. 1.]] Padded B: [200. 0. 200. 0. 200. 0. 0. 0.] Determinant of resulting matrix: 1.0 Reformatted A_herm: [[1. 0. 0. 0. 0. 0. 0. 0.] [0. 1. 0. 0. 0. 0. 0. 0.] [0. 0. 1. 0. 0. 0. 0. 0.] [0. 0. 0. 1. 0. 0. 0. 0.] [0. 0. 0. 0. 1. 0. 0. 0.] [0. 0. 0. 0. 0. 1. 0. 0.] [0. 0. 0. 0. 0. 0. 1. 0.] [0. 0. 0. 0. 0. 0. 0. 1.]] B_herm: [217.32050808 17.32050808 217.32050808 17.32050808 217.32050808 17.32050808 17.32050808 17.32050808] Determinant of resulting matrix: 1.0 Condition # of resulting matrix: 1.0 Using 'ideal' simulator with 'statevector' backend Backend: AerSimulator('aer_simulator') Time elapsed for classical: 0 min 0.00 sec **************************Quantum circuit generation, transpile & running************************* ==================Making a circuit and simulating it================ Time elapsed for generating HHL circuit: 0 min 1.42 sec Circuit: ┌──────────────┐┌──────┐ ┌─────────┐ q9_0: ┤0 ├┤5 ├────────┤5 ├ │ ││ │ │ │ q9_1: ┤1 circuit-165 ├┤6 ├────────┤6 ├ │ ││ │ │ │ q9_2: ┤2 ├┤7 ├────────┤7 ├ └──────────────┘│ │┌──────┐│ │ q10_0:────────────────┤0 ├┤4 ├┤0 ├ │ QPE ││ ││ QPE_dg │ q10_1:────────────────┤1 ├┤3 ├┤1 ├ │ ││ ││ │ q10_2:────────────────┤2 ├┤2 ├┤2 ├ │ ││ 1/x ││ │ q10_3:────────────────┤3 ├┤1 ├┤3 ├ │ ││ ││ │ q10_4:────────────────┤4 ├┤0 ├┤4 ├ └──────┘│ │└─────────┘ q11: ────────────────────────┤5 ├─────────── └──────┘ Time elapsed for transpiling the circuit: 0 min 0.16 sec Time elapsed for running the circuit: 0 min 0.04 sec counts: {'100000101': 9, '100000011': 6, '100000110': 10, '100000010': 1682, '100000111': 15, '100000100': 1645, '100000001': 7, '100000000': 1626} All counts of ancila (only the first 2**nq represent solution vector): [('100000000', 1626), ('100000001', 7), ('100000010', 1682), ('100000011', 6), ('100000100', 1645), ('100000101', 9), ('100000110', 10), ('100000111', 15)] Counts vector should approach exact vector in infinite limit counts_vector: [0.5702631 0.03741657 0.58 0.03464102 0.57358522 0.04242641 0.04472136 0.05477226] exact_vector/norm: [0.57431815 0.04577332 0.57431815 0.04577332 0.57431815 0.04577332 0.04577332 0.04577332] true solution: [0.57431815 0.04577332 0.57431815 0.04577332 0.57431815 0.04577332 0.04577332 0.04577332] counts solution vector: [0.5702631 0.03741657 0.58 0.03464102 0.57358522 0.04242641 0.04472136 0.05477226] diff with true solution (%): [ 0.70606392 18.25681403 0.98932091 24.32051541 0.12761819 7.31193938 2.29820551 19.65977172] Fidelity: 0.9996637113875608 exact solution vector: [0.57431815 0.04577332 0.57431815 0.04577332 0.57431815 0.04577332 0.04577332 0.04577332] diff with true solution (%): [1.93311499e-13 6.74586741e-12 3.28629548e-13 4.07783895e-12 5.79934496e-14 6.59427488e-12 3.31987632e-12 6.82166367e-13] Fidelity: 1.0
-
- Run error modeling and mitigation studies:
linear_solver_errormitigation.py
python linear_solver_errormitigation.py -nq 1 -s 1000
- NOTE: Please note that you may have to port the code to the latest Qiskit version as this script is meant to use IBM's hardware/simulators.
Model outputs and data needed for the plotting routines are provided here: 10.5281/zenodo.13738192
- plot_Hele-Shaw.ipynb: visualizing the implementation of Qiskit's HHL for solving 2D Hele-Shaw flow problem.
- plot_errormitigation.ipynb: visualizing the results of the error modeling and mitigation/suppression studies.
- plot_metrics.ipynb: visualizing the computational cost and other metrics with varying system size.
- Resources:
- Always install and start JupyterLab in your base conda env.
- Use custom kernels as needed. See below for how to install custom kernels.
- To import your custom conda env to JupyterLab, follow the steps below which are modified from OLCF Jupyter docs:
- Install JupyterLab in your custom conda env. Do the rest of the steps in your base env.
- Follow steps 1-2 in OLCF Jupyter docs: Open a Terminal on JupyterLab using the Launcher.
- Skip step 3: You don't have to create your own custom conda env as you have already done this.
- Follow step 4 (source activate your custom env) using the custom env you created.
- Follow step 5 (make your env visible in JupyterLab) using your desired env name:
python -m ipykernel install --user --name [env-name] --display-name [env-name]
. You may have to pip install the librarywcwidth
on the Jupyter terminal:pip install wcwidth
- Finally refresh your page and the Lancher (and kernel selector for notebooks) will have your env.