├── .DS_Store ├── LICENSE ├── setup_save_account.ipynb ├── helper_file_1.0.ipynb └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Quantum-Computing-with-Python-and-IBM-Quantum-Second-Edition/HEAD/.DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /setup_save_account.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from qiskit_ibm_runtime import QiskitRuntimeService\n", 10 | " \n", 11 | "# README FIRST: UPDATE WITH YOUR TOKEN ID FIRST BEFORE RUNNING ANY CODE. TOKEN CAN BE FOUND IN YOUR ACCOUNT DETAILS ON THE IBM QUANTUM PLATFORM\n", 12 | "\n", 13 | "#Save an IBM Quantum account and set it as your default account.\n", 14 | "QiskitRuntimeService.save_account(channel=\"ibm_quantum\", token=\"YOUR-API_TOKEN\", set_as_default=True, overwrite=True)\n", 15 | " " 16 | ] 17 | } 18 | ], 19 | "metadata": { 20 | "kernelspec": { 21 | "display_name": "Python 3", 22 | "language": "python", 23 | "name": "python3" 24 | }, 25 | "language_info": { 26 | "codemirror_mode": { 27 | "name": "ipython", 28 | "version": 3 29 | }, 30 | "file_extension": ".py", 31 | "mimetype": "text/x-python", 32 | "name": "python", 33 | "nbconvert_exporter": "python", 34 | "pygments_lexer": "ipython3", 35 | "version": "3.11.9" 36 | } 37 | }, 38 | "nbformat": 4, 39 | "nbformat_minor": 2 40 | } 41 | -------------------------------------------------------------------------------- /helper_file_1.0.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "fc2e29ae-3acb-4a56-a2a0-d04ba37521e7", 6 | "metadata": {}, 7 | "source": [ 8 | "# Quantum helper file\n", 9 | "This file contains various helper functions to allow ease of use and to update as code changes progress and evolve. Rather than changing code across all chapters, this will serve as a single source of reference for all functionality." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 3, 15 | "id": "a43ded54", 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "# Load helper file\n", 20 | "%run setup_save_account.ipynb\n" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 4, 26 | "id": "11f3591c-3506-4252-8abc-586e1a17067f", 27 | "metadata": { 28 | "tags": [] 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "# Import libraries and objects\n", 33 | "from qiskit import QuantumCircuit, transpile\n", 34 | "from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler\n", 35 | "from qiskit_ibm_runtime import Options\n", 36 | "from qiskit_ibm_runtime import Session\n", 37 | "from qiskit.primitives import StatevectorSampler\n", 38 | "from qiskit.providers.basic_provider import BasicSimulator\n", 39 | "from qiskit.quantum_info import Statevector\n", 40 | "from qiskit_ibm_runtime.fake_provider import FakeManilaV2\n", 41 | "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n", 42 | "from qiskit.visualization import *\n", 43 | "\n", 44 | "\n", 45 | "service = QiskitRuntimeService()" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 5, 51 | "id": "f207b68e", 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "from qiskit import QuantumCircuit, ClassicalRegister\n", 56 | "from qiskit.providers.fake_provider import GenericBackendV2\n", 57 | "\n", 58 | "def create_circuit(num_qubits, add_measurements):\n", 59 | "\n", 60 | " # Create a circuit with classical control\n", 61 | " meas = ClassicalRegister(num_qubits)\n", 62 | " qc = QuantumCircuit(num_qubits)\n", 63 | " qc.add_register(meas)\n", 64 | " if add_measurements:\n", 65 | " for i in range(num_qubits):\n", 66 | " qc.measure(i, meas[i])\n", 67 | " \n", 68 | " # Define backend with custom basis gates\n", 69 | " #backend = GenericBackendV2(\n", 70 | " # num_qubits=num_qubits,\n", 71 | " # basis_gates=[\"ecr\", \"id\", \"rz\", \"sx\", \"x\"],\n", 72 | " # control_flow=True,\n", 73 | " #)\n", 74 | " \n", 75 | " return qc" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": null, 81 | "id": "735525bf", 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "# Run a Statevector simulator: \n", 86 | "def run_sv_simulator(qc):\n", 87 | " from qiskit.quantum_info import Statevector\n", 88 | " statevector = Statevector(qc)\n", 89 | " return statevector \n", 90 | "\n" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": null, 96 | "id": "01a7878d", 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "# Run a Unitary simulator: \n", 101 | "def run_unitary_simulator(qc):\n", 102 | " from qiskit.quantum_info import Operator\n", 103 | " result = Operator(qc).data\n", 104 | " return result\n" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "id": "b350b827", 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "# Run a QASM simulator: \n", 115 | "def run_qasm_simulator(qc):\n", 116 | " from qiskit.providers.basic_provider import BasicSimulator\n", 117 | " backend = BasicSimulator() \n", 118 | " result = backend.run(qc).result()\n", 119 | " return result\n" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": 7, 125 | "id": "119dbfb4", 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "# Execute circuit on the the State vector sampler\n", 130 | "def run_sv_circuit(qc):\n", 131 | " # Run the circuit and return the state vector object result\n", 132 | " stateVectorResult = Statevector(qc)\n", 133 | " #qsphere = stateVectorResult.draw('qsphere')\n", 134 | " #bloch_sphere = stateVectorResult.draw('bloch')\n", 135 | " #circuit_image = qc.draw(output='mpl')\n", 136 | " return stateVectorResult\n", 137 | " " 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 9, 143 | "id": "9abb90eb", 144 | "metadata": {}, 145 | "outputs": [], 146 | "source": [ 147 | "# Execute circuit on the Basic Aer qasm simulator, RENAMED from run_qasm_circuit to run_simulated_circuit\n", 148 | "def run_simulated_circuit(qc, backend, options):\n", 149 | " #Check if option object is set\n", 150 | " if options == None:\n", 151 | " options = Options(optimization_level=3)\n", 152 | " \n", 153 | " #Check if backend is defined\n", 154 | " if backend == None:\n", 155 | " backend = BasicSimulator()\n", 156 | " \n", 157 | " transpiled_qc = transpile(qc, backend)\n", 158 | " result = backend.run(transpiled_qc).result()\n", 159 | " \n", 160 | " return transpiled_qc, result\n", 161 | "\n", 162 | "\n" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "id": "5a99f1fd", 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [ 172 | "# Execute circuit on the Basic Aer qasm simulator\n", 173 | "def simulate_on_sampler(qc, backend, options):\n", 174 | "\n", 175 | " # Construct an ideal simulator with Sampler \n", 176 | " from qiskit.primitives import StatevectorSampler\n", 177 | " sampler = StatevectorSampler()\n", 178 | "\n", 179 | " # Transpile circuit\n", 180 | " pm = generate_preset_pass_manager(optimization_level=1)\n", 181 | " transpiled_qc = pm.run(qc)\n", 182 | "\n", 183 | " # Run using sampler\n", 184 | " state_vector_result = sampler.run([qc])\n", 185 | " \n", 186 | " result = state_vector_result.result()\n", 187 | " \n", 188 | " return transpiled_qc, result, state_vector_result\n", 189 | "\n", 190 | "\n", 191 | "\n", 192 | "\n", 193 | "\n" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": 10, 199 | "id": "b4fa2390-1bd0-4285-aa34-e2d56fd08ede", 200 | "metadata": { 201 | "tags": [] 202 | }, 203 | "outputs": [], 204 | "source": [ 205 | "# Execute a circuit on a real backend - Sampler\n", 206 | "def execute_circuit(qc, simulator, service, backend, options):\n", 207 | " # If executing on a qasm simulator\n", 208 | " if simulator:\n", 209 | " return run_qasm_circuit(qc, backend, options)\n", 210 | " \n", 211 | " if options == None:\n", 212 | " options = Options(optimization_level=3)\n", 213 | " \n", 214 | " with Session(service=service, backend=backend) as session:\n", 215 | " # Submit a request to the Sampler primitive within the session.\n", 216 | " sampler = Sampler(session=session, options=options)\n", 217 | " job = sampler.run(circuits=qc)\n", 218 | " result = job.result()\n", 219 | " return result\n" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 12, 225 | "id": "e9f7cf98", 226 | "metadata": {}, 227 | "outputs": [], 228 | "source": [ 229 | "# Will run the circuit on the state vector (sv) simulator\n", 230 | "# Returns state vector results, circuit diagram, Sphere & Bloch sphere \n", 231 | "def execute_circuit_sv(quantum_circuit):\n", 232 | " stateVectorResults = run_sv_circuit(quantum_circuit)\n", 233 | " \n", 234 | " #Draw the circuit diagram\n", 235 | " circuit_diagram = quantum_circuit.draw(output=\"mpl\")\n", 236 | " #Draw the Qsphere \n", 237 | " q_sphere = stateVectorResults.draw('qsphere')\n", 238 | " #Draw the Bloch sphere \n", 239 | " bloch_sphere = stateVectorResults.draw('bloch') \n", 240 | " #Return the results, circuit diagram, and QSphere\t\t\n", 241 | " return stateVectorResults, circuit_diagram, q_sphere, bloch_sphere" 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 14, 247 | "id": "36177fe7", 248 | "metadata": {}, 249 | "outputs": [], 250 | "source": [ 251 | "# Will execute the circuit on the qasm simulator\n", 252 | "# Returns results, circuit diagram, and histogram \n", 253 | "def execute_circuit_returns(quantum_circuit):\n", 254 | " from qiskit.primitives import Sampler\n", 255 | " sampler = Sampler()\n", 256 | " \n", 257 | " result = sampler.run(quantum_circuit, shots=1024).result()\n", 258 | " quasi_dists = result.quasi_dists\n", 259 | "\n", 260 | " # Convert the output to bit strings\n", 261 | " counts = quasi_dists[0].binary_probabilities()\n", 262 | "\n", 263 | " #Draw the circuit diagram\n", 264 | " circuit_diagram = quantum_circuit.draw(output=\"mpl\")\n", 265 | " #Create a histogram of the counts\n", 266 | " histogram = plot_distribution(counts)\n", 267 | " #Return the results, circuit diagram, and histogram\n", 268 | " return counts, circuit_diagram, histogram\n" 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": 15, 274 | "id": "dcd52a64", 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [ 278 | "# Will execute the circuit on the qasm simulator\n", 279 | "# Returns results, circuit diagram, and histogram \n", 280 | "def execute_param_circuit(quantum_circuit, params):\n", 281 | " from qiskit.primitives import Sampler\n", 282 | " sampler = Sampler()\n", 283 | " \n", 284 | " result = sampler.run(quantum_circuit, shots=1024).result()\n", 285 | " quasi_dists = result.quasi_dists\n", 286 | "\n", 287 | " # Convert the output to bit strings\n", 288 | " counts = quasi_dists[0].binary_probabilities()\n", 289 | "\n", 290 | " circuit_diagram = quantum_circuit.draw(output=\"mpl\")\n", 291 | " #Create a histogram of the counts\n", 292 | " histogram = plot_distribution(counts)\n", 293 | " #Return the results, circuit diagram, and histogram\n", 294 | " return counts, circuit_diagram, histogram" 295 | ] 296 | }, 297 | { 298 | "cell_type": "code", 299 | "execution_count": 55, 300 | "id": "5574095d", 301 | "metadata": {}, 302 | "outputs": [ 303 | { 304 | "name": "stdout", 305 | "output_type": "stream", 306 | "text": [ 307 | "The number of bitstrings is: 1024\n", 308 | "The counts are: {'000': 498, '111': 526}\n" 309 | ] 310 | } 311 | ], 312 | "source": [ 313 | "#Flag to set to run test cell below, simply change Flase to True:\n", 314 | "test = True\n", 315 | "if test:\n", 316 | " import qiskit\n", 317 | " from qiskit.primitives import StatevectorSampler\n", 318 | "\n", 319 | " # Construct an ideal simulator with SamplerV2 \n", 320 | " sampler = StatevectorSampler()\n", 321 | "\n", 322 | " # Generate 3-qubit GHZ state\n", 323 | " circuit = qiskit.QuantumCircuit(3)\n", 324 | " circuit.h(0)\n", 325 | " circuit.cx(0, 1)\n", 326 | " circuit.cx(1, 2)\n", 327 | " circuit.measure_all()\n", 328 | "\n", 329 | "\n", 330 | " # Transpile circuit\n", 331 | " pm = generate_preset_pass_manager(optimization_level=1)\n", 332 | " isa_circuit = pm.run(circuit)\n", 333 | "\n", 334 | " # Run using sampler\n", 335 | " result = sampler.run([circuit]).result()\n", 336 | "\n", 337 | " # Access result data for PUB 0\n", 338 | " data_pub = result[0].data\n", 339 | "\n", 340 | " # Access bitstring for the classical register \"meas\"\n", 341 | " bitstrings = data_pub.meas.get_bitstrings()\n", 342 | " print(f\"The number of bitstrings is: {len(bitstrings)}\")\n", 343 | "\n", 344 | " # Get counts for the classical register \"meas\"\n", 345 | " counts = data_pub.meas.get_counts()\n", 346 | " print(f\"The counts are: {counts}\")" 347 | ] 348 | } 349 | ], 350 | "metadata": { 351 | "kernelspec": { 352 | "display_name": "Python 3 (ipykernel)", 353 | "language": "python", 354 | "name": "python3" 355 | }, 356 | "language_info": { 357 | "codemirror_mode": { 358 | "name": "ipython", 359 | "version": 3 360 | }, 361 | "file_extension": ".py", 362 | "mimetype": "text/x-python", 363 | "name": "python", 364 | "nbconvert_exporter": "python", 365 | "pygments_lexer": "ipython3", 366 | "version": "3.11.4" 367 | }, 368 | "widgets": { 369 | "application/vnd.jupyter.widget-state+json": { 370 | "state": {}, 371 | "version_major": 2, 372 | "version_minor": 0 373 | } 374 | } 375 | }, 376 | "nbformat": 4, 377 | "nbformat_minor": 5 378 | } 379 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
This is the code repository for Learn Quantum Computing with Python and IBM Quantum, Second Edition, published by Packt. 4 |
5 | 6 |10 | Robert Loredo
11 | 12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
27 |
28 | The IBM Quantum Platform was built to enable developers to learn the basics of quantum computing by providing access to high performant quantum computers and provide documentation and courses to help get up to speed with the latest features in quantum computing.
29 |
30 | Updated with new examples and changes to the platform, this edition begins with an introduction to the IBM Quantum Platform and the Quantum Information Science Kit (Qiskit) SDK. You will become well versed in the IBM Quantum Composer interface as well as running your quantum circuits on a real quantum computer. Along the way, you’ll learn some of the fundamental principles regarding quantum mechanics, qubits, quantum gates, quantum circuits, and the error mitigation techniques that are used to perform operations on qubits.
31 |
32 | As you build on your knowledge, you’ll understand the functionality of IBM Qiskit and the developer-focused resources so you can create your own quantum algorithms. You’ll learn how to monitor and optimize your quantum circuits. Lastly, you’ll look at the fundamental quantum algorithms and understand how they can be applied effectively.
33 |
34 | By the end of this quantum computing book, you'll know how to build quantum algorithms and will have gained a practical understanding of quantum computation that you can apply to your research or business.
35 |