Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding noise simulator #40

Open
wants to merge 24 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8e400fd
adding noise simulator
WilliamBerquist Sep 12, 2022
8f07128
add generic circ sim and review on noise
danlkv Sep 18, 2022
2a6add6
add x and y to qiskit opfactory
danlkv Sep 29, 2022
6643a0d
fix the set up of qiskit noisy simulation
danlkv Oct 6, 2022
1357658
add readme and add H error to qtensor noise model
danlkv Oct 6, 2022
8f77244
fixed qtensor noise model so it matches the qiskit noise model. Ran s…
WilliamBerquist Oct 8, 2022
721c9c9
Fix qiskit simulation even one more time
danlkv Oct 9, 2022
6ef5419
fixed qiskit density matrix simulator function calls so they are used…
WilliamBerquist Oct 10, 2022
53fea74
minor fixes
WilliamBerquist Oct 10, 2022
9d1dee2
fixed correct number of circuit check. Only checks now if we choose t…
WilliamBerquist Oct 11, 2022
17bbc13
add hpc scripts
Oct 11, 2022
6f792dd
change to n=5
Oct 11, 2022
3dbbadb
temporary fix for _get_args(). Needs a full rewrite eventually
WilliamBerquist Oct 11, 2022
4aeb6b5
added a better fix to _get_args()
WilliamBerquist Oct 11, 2022
089223f
adding parallelized tensor slicing file. Can be used on multi gpu nod…
WilliamBerquist Jan 20, 2023
a7b8c94
small updates
WilliamBerquist Jan 20, 2023
d0c05c4
fixed imports
WilliamBerquist Jan 20, 2023
57b9fd1
fixed some documentation
WilliamBerquist Jan 22, 2023
b6cf5c5
added CupyBackend support for noisy simulations
WilliamBerquist Jan 22, 2023
c8e29b2
tentative cupy functionality added. Needs refactoring
WilliamBerquist Jan 23, 2023
9ca45a5
added an example jupyter notebook on how to use the stochastic noise …
WilliamBerquist Mar 13, 2023
91183d2
state reconstruction and obtaining a classical shadow implemented
WilliamBerquist May 30, 2023
4016e35
fixed a few minor bugs in NoiseSimulator. Cleaned up some comments.
WilliamBerquist Jul 12, 2023
23a8c5a
removed some obsolete comments
WilliamBerquist Jul 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307 changes: 307 additions & 0 deletions examples/Stochastic_noise_usage.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Create noise channel(s)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from qtensor.noise_simulator.NoiseChannels import DepolarizingChannel\n",
"from qtensor.noise_simulator.NoiseModel import NoiseModel\n",
"\n",
"# Depolarizing channel for a single qubit. The probability of the error occuring is related to 0.003\n",
"depol_chan_1Q = DepolarizingChannel(param = 0.003, num_qubits = 1)\n",
"# Depolarizing channel for two qubits. The probability of the error occuring is related to 0.03\n",
"depol_chan_2Q = DepolarizingChannel(param = 0.03, num_qubits = 2)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Create noise model"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"noise_model = NoiseModel()\n",
"# If a circuit uses this noise model, all H, XPhase, and ZPhase gates will experience depolarizing noise \n",
"# based on the single qubit depolarizing channel created above\n",
"noise_model.add_channel_to_all_qubits(channel = depol_chan_1Q, gates = ['H', 'XPhase', 'ZPhase'])\n",
"# If a circuit uses this noise model, all cX gates will experience depolarizing noise \n",
"# based on the two-qubit depolarizing channel created above\n",
"noise_model.add_channel_to_all_qubits(channel = depol_chan_2Q, gates = ['cX'])"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Create a circuit. Here we create a QAOA circuit. "
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"from qtree.operators import from_qiskit_circuit\n",
"from qtensor import QiskitQAOAComposer, QtreeSimulator\n",
"import qtensor\n",
"import numpy as np\n",
"import networkx as nx\n",
"\n",
"# degree of graph\n",
"d = 3\n",
"num_qubits = 4\n",
"G = nx.random_regular_graph(d, num_qubits)\n",
"\n",
"# optimal gamma and beta parameters previously found for these values of d and n\n",
"gammabeta = np.array(qtensor.tools.BETHE_QAOA_VALUES[str(d)]['angles'])\n",
"gamma = -gammabeta[:d]\n",
"beta = gammabeta[d:]\n",
"\n",
"# composes a qaoa circuit of type qiskit\n",
"qiskit_comp = QiskitQAOAComposer(G, gamma=gamma, beta=beta)\n",
"qiskit_comp.ansatz_state()\n",
"\n",
"# converts the circuit to qtensor type, which is just a list \n",
"n, circ = from_qiskit_circuit(qiskit_comp.circuit)\n",
"# from_qiskiit_circuit returns each gate as a list so we remove the lists from the gates. Might want to fix that.\n",
"circ = sum(circ, [])"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Instatiate simulator with noise model and then simulate the circuit with noise. "
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.14060763, 0.0349968 , 0.04040751, 0.06550023, 0.05163103,\n",
" 0.06425988, 0.03407733, 0.06851953, 0.06851953, 0.03407733,\n",
" 0.06425988, 0.05163103, 0.06550023, 0.04040751, 0.0349968 ,\n",
" 0.14060763])"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from qtensor.noise_simulator.NoiseSimulator import NoiseSimulator\n",
"\n",
"noise_sim = NoiseSimulator(noise_model)\n",
"\n",
"num_circs = 10\n",
"# simulate an ensemble of 10 circuits with stochastic noise\n",
"noise_sim.simulate_batch_ensemble(circ, num_circs, num_qubits)\n",
"# get the approximate noisy probabilities \n",
"qtensor_probs = noise_sim.normalized_ensemble_probs\n",
"qtensor_probs"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"This same circuit can also be simulated without noise."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.26962495, 0.03924902, 0.03924902, 0.02445963, 0.03924902,\n",
" 0.02445963, 0.02445963, 0.03924902, 0.03924902, 0.02445963,\n",
" 0.02445963, 0.03924902, 0.02445963, 0.03924902, 0.03924902,\n",
" 0.26962495])"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ideal_sim = QtreeSimulator()\n",
"amplitudes = ideal_sim.simulate_batch(circ, num_qubits)\n",
"ideal_probs = np.abs(amplitudes)**2\n",
"ideal_probs"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"We can check how well our simulation approximated the exact noisy state by running the same circuit with a density matrix simulator and then calculating the fidelity between the exact and approximate noisy states."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.13403107, 0.05506911, 0.05646327, 0.0514643 , 0.05139734,\n",
" 0.0499991 , 0.04779918, 0.05377664, 0.05377664, 0.04779918,\n",
" 0.0499991 , 0.05139734, 0.0514643 , 0.05646327, 0.05506911,\n",
" 0.13403107])"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import qiskit.providers.aer.noise as noise\n",
"from qiskit.providers.aer import AerSimulator\n",
"\n",
"# Create the same noise model with the same channels and noisy gates in Qiskits framework\n",
"depol_chan_qiskit_1Q = noise.depolarizing_error(param = 0.003, num_qubits = 1)\n",
"depol_chan_qiskit_2Q = noise.depolarizing_error(param = 0.03, num_qubits = 2)\n",
"\n",
"noise_model_qiskit = noise.NoiseModel()\n",
"noise_model_qiskit.add_all_qubit_quantum_error(depol_chan_qiskit_1Q, ['rz', 'rx', 'h'])\n",
"noise_model_qiskit.add_all_qubit_quantum_error(depol_chan_qiskit_2Q, ['cx'])\n",
"\n",
"# Take the Qiskit circuit we created before, and add some final touches to it. These do not effect any measurement outcomes \n",
"qiskit_circ = qiskit_comp.circuit\n",
"\n",
"# Qiskit uses little endian notation by default, and Qtensor uses big endian, so we change the Qiskit circuit to match qtensor\n",
"qiskit_circ = qiskit_circ.reverse_bits()\n",
"qiskit_circ.save_density_matrix()\n",
"qiskit_circ.measure_all(add_bits = False)\n",
"\n",
"# Simulate the circuit\n",
"backend = AerSimulator(method='density_matrix', noise_model=noise_model_qiskit, fusion_enable=False, fusion_verbose=True)\n",
"result = backend.run(qiskit_circ).result()\n",
"\n",
"# The stochastic noisy simulation gives us a probability density vector, so we need to save the diagonal elements of the density matrix for our comparison\n",
"qiskit_probs = np.diagonal(np.asarray(result.results[0].data.density_matrix).real)\n",
"qiskit_probs"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.9851105052526412"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# The fidelity is defined for probability amplitudes, so we need to take the square root of our probability density vectors\n",
"A = np.sqrt(qtensor_probs)\n",
"B = np.sqrt(qiskit_probs)\n",
"fidelity = np.dot(A, B)**2\n",
"fidelity"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"We can increase our fidelity by increasing the number of circuits in the ensemble."
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.9954629065353349"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"num_circs = 100\n",
"noise_sim.simulate_batch_ensemble(circ, num_circs, num_qubits)\n",
"qtensor_probs = noise_sim.normalized_ensemble_probs\n",
"A = np.sqrt(qtensor_probs)\n",
"B = np.sqrt(qiskit_probs)\n",
"fidelity = np.dot(A, B)**2\n",
"fidelity"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.2"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}
8 changes: 8 additions & 0 deletions qtensor/OpFactory.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ def cX(cls):
def cZ(cls):
return qiskit_lib.CZGate

@property
def X(cls):
return qiskit_lib.XGate

@property
def Y(cls):
return qiskit_lib.YGate

@property
def Z(cls):
return qiskit_lib.ZGate
Expand Down
Loading