diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0144b207..cbef0bdd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -139,6 +139,8 @@ jobs: - uses: ./.github/actions/install-algorithms - run: make lint shell: bash + - run: make mypy + shell: bash - name: Algorithms Unit Tests under Python ${{ matrix.python-version }} uses: ./.github/actions/run-tests with: diff --git a/Makefile b/Makefile index 2ace92c1..378cf4a4 100644 --- a/Makefile +++ b/Makefile @@ -35,29 +35,32 @@ endif # You can set this variable from the command line. SPHINXOPTS = -.PHONY: lint style black test test_ci spell copyright html doctest clean_sphinx coverage clean +.PHONY: lint mypy style black test test_ci spell copyright html doctest clean_sphinx coverage clean -all_check: spell style lint copyright clean_sphinx html doctest +all_check: spell style lint copyright mypy clean_sphinx html doctest lint: pylint -rn qiskit_algorithms test tools python tools/verify_headers.py qiskit_algorithms test tools +mypy: + python -m mypy qiskit_algorithms test tools + style: - black --check qiskit_algorithms test tools + python -m black --check qiskit_algorithms test tools docs black: - black qiskit_algorithms test tools + python -m black qiskit_algorithms test tools docs test: python -m unittest discover -v test test_ci: echo "Detected $(NPROCS) CPUs running with $(CONCURRENCY) workers" - stestr run --concurrency $(CONCURRENCY) + python -m stestr run --concurrency $(CONCURRENCY) spell: - pylint -rn --disable=all --enable=spelling --spelling-dict=en_US qiskit_algorithms test tools + python -m pylint -rn --disable=all --enable=spelling --spelling-dict=en_US qiskit_algorithms test tools sphinx-build -M spelling docs docs/_build -W -T --keep-going $(SPHINXOPTS) copyright: @@ -73,10 +76,10 @@ clean_sphinx: make -C docs clean coverage: - coverage3 run --source qiskit_algorithms -m unittest discover -s test -q - coverage3 report + python -m coverage3 run --source qiskit_algorithms -m unittest discover -s test -q + python -m coverage3 report coverage_erase: - coverage erase + python -m coverage erase clean: clean_sphinx coverage_erase; diff --git a/docs/conf.py b/docs/conf.py index 10cde338..85d90927 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -27,7 +27,7 @@ sys.path.append(os.path.abspath(".")) project = "Qiskit Algorithms" -copyright = f"2017-{datetime.date.today().year}, Qiskit Algorithms Development Team" # pylint: disable=redefined-builtin +copyright = f"2017-{datetime.date.today().year}, Qiskit Algorithms Development Team" # pylint: disable=redefined-builtin author = "Qiskit Algorithms Development Team" # The short X.Y version @@ -55,7 +55,7 @@ "matplotlib.sphinxext.plot_directive", "sphinx.ext.doctest", "qiskit_sphinx_theme", - "nbsphinx" + "nbsphinx", ] rst_prolog = """ @@ -81,7 +81,9 @@ __""" vers = version.split(".") -link_str = f" https://github.com/qiskit-community/qiskit-algorithms/blob/stable/{vers[0]}.{vers[1]}/docs/" +link_str = ( + f" https://github.com/qiskit-community/qiskit-algorithms/blob/stable/{vers[0]}.{vers[1]}/docs/" +) nbsphinx_prolog += link_str + "{{ docname }}" nbsphinx_timeout = 360 @@ -162,4 +164,3 @@ # >> code # output doctest_test_doctest_blocks = "" - diff --git a/docs/tutorials/01_algorithms_introduction.ipynb b/docs/tutorials/01_algorithms_introduction.ipynb index 5976277f..709eac93 100644 --- a/docs/tutorials/01_algorithms_introduction.ipynb +++ b/docs/tutorials/01_algorithms_introduction.ipynb @@ -141,13 +141,15 @@ "source": [ "from qiskit.quantum_info import SparsePauliOp\n", "\n", - "H2_op = SparsePauliOp.from_list([\n", - " (\"II\", -1.052373245772859),\n", - " (\"IZ\", 0.39793742484318045),\n", - " (\"ZI\", -0.39793742484318045),\n", - " (\"ZZ\", -0.01128010425623538),\n", - " (\"XX\", 0.18093119978423156)\n", - "])" + "H2_op = SparsePauliOp.from_list(\n", + " [\n", + " (\"II\", -1.052373245772859),\n", + " (\"IZ\", 0.39793742484318045),\n", + " (\"ZI\", -0.39793742484318045),\n", + " (\"ZZ\", -0.01128010425623538),\n", + " (\"XX\", 0.18093119978423156),\n", + " ]\n", + ")" ] }, { @@ -305,8 +307,9 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/02_vqe_advanced_options.ipynb b/docs/tutorials/02_vqe_advanced_options.ipynb index ecf74726..be08ede5 100644 --- a/docs/tutorials/02_vqe_advanced_options.ipynb +++ b/docs/tutorials/02_vqe_advanced_options.ipynb @@ -298,9 +298,7 @@ " values.append(mean)\n", "\n", "\n", - "vqe = VQE(\n", - " estimator, ansatz, optimizer, callback=store_intermediate_result, gradient=gradient\n", - ")\n", + "vqe = VQE(estimator, ansatz, optimizer, callback=store_intermediate_result, gradient=gradient)\n", "\n", "result = vqe.compute_minimum_eigenvalue(operator=H2_op)\n", "print(f\"Value using Gradient: {result.eigenvalue.real:.5f}\")" @@ -435,9 +433,7 @@ "ansatz1 = TwoLocal(rotation_blocks=\"ry\", entanglement_blocks=\"cz\")\n", "optimizer1 = SLSQP(maxiter=1000)\n", "\n", - "vqe1 = VQE(\n", - " estimator1, ansatz1, optimizer1, gradient=gradient1, initial_point=initial_pt\n", - ")\n", + "vqe1 = VQE(estimator1, ansatz1, optimizer1, gradient=gradient1, initial_point=initial_pt)\n", "result1 = vqe1.compute_minimum_eigenvalue(operator=H2_op)\n", "print(result1)\n", "\n", @@ -507,7 +503,7 @@ "import qiskit.tools.jupyter\n", "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/03_vqe_simulation_with_noise.ipynb b/docs/tutorials/03_vqe_simulation_with_noise.ipynb index 7d71cd0c..b91c4ac5 100644 --- a/docs/tutorials/03_vqe_simulation_with_noise.ipynb +++ b/docs/tutorials/03_vqe_simulation_with_noise.ipynb @@ -120,6 +120,7 @@ "counts = []\n", "values = []\n", "\n", + "\n", "def store_intermediate_result(eval_count, parameters, mean, std):\n", " counts.append(eval_count)\n", " values.append(mean)" @@ -162,15 +163,11 @@ "# instantiate and run VQE\n", "from qiskit_algorithms import VQE\n", "\n", - "vqe = VQE(\n", - " noiseless_estimator, ansatz, optimizer=spsa, callback=store_intermediate_result\n", - ")\n", + "vqe = VQE(noiseless_estimator, ansatz, optimizer=spsa, callback=store_intermediate_result)\n", "result = vqe.compute_minimum_eigenvalue(operator=H2_op)\n", "\n", "print(f\"VQE on Aer qasm simulator (no noise): {result.eigenvalue.real:.5f}\")\n", - "print(\n", - " f\"Delta from reference energy value is {(result.eigenvalue.real - ref_value):.5f}\"\n", - ")" + "print(f\"Delta from reference energy value is {(result.eigenvalue.real - ref_value):.5f}\")" ] }, { @@ -324,9 +321,7 @@ "result1 = vqe.compute_minimum_eigenvalue(operator=H2_op)\n", "\n", "print(f\"VQE on Aer qasm simulator (with noise): {result1.eigenvalue.real:.5f}\")\n", - "print(\n", - " f\"Delta from reference energy value is {(result1.eigenvalue.real - ref_value):.5f}\"\n", - ")" + "print(f\"Delta from reference energy value is {(result1.eigenvalue.real - ref_value):.5f}\")" ] }, { @@ -442,7 +437,7 @@ "import qiskit.tools.jupyter\n", "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/04_vqd.ipynb b/docs/tutorials/04_vqd.ipynb index 2443800e..254f7493 100644 --- a/docs/tutorials/04_vqd.ipynb +++ b/docs/tutorials/04_vqd.ipynb @@ -88,7 +88,7 @@ "ansatz = TwoLocal(2, rotation_blocks=[\"ry\", \"rz\"], entanglement_blocks=\"cz\", reps=1)\n", "\n", "optimizer = SLSQP()\n", - "ansatz.decompose().draw('mpl')" + "ansatz.decompose().draw(\"mpl\")" ] }, { @@ -148,6 +148,7 @@ "values = []\n", "steps = []\n", "\n", + "\n", "def callback(eval_count, params, value, meta, step):\n", " counts.append(eval_count)\n", " values.append(value)\n", @@ -170,8 +171,8 @@ "from qiskit_algorithms import VQD\n", "\n", "vqd = VQD(estimator, fidelity, ansatz, optimizer, k=k, betas=betas, callback=callback)\n", - "result = vqd.compute_eigenvalues(operator = H2_op)\n", - "vqd_values = result.eigenvalues\n" + "result = vqd.compute_eigenvalues(operator=H2_op)\n", + "vqd_values = result.eigenvalues" ] }, { @@ -237,7 +238,7 @@ "counts = np.asarray(counts)\n", "values = np.asarray(values)\n", "\n", - "for i in range(1,4):\n", + "for i in range(1, 4):\n", " _counts = counts[np.where(steps == i)]\n", " _values = values[np.where(steps == i)]\n", " pylab.plot(_counts, _values, label=f\"State {i-1}\")\n", @@ -338,8 +339,9 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/05_qaoa.ipynb b/docs/tutorials/05_qaoa.ipynb index 7a00b6fb..448c56f9 100644 --- a/docs/tutorials/05_qaoa.ipynb +++ b/docs/tutorials/05_qaoa.ipynb @@ -26,10 +26,9 @@ "import networkx as nx\n", "\n", "num_nodes = 4\n", - "w = np.array([[0., 1., 1., 0.],\n", - " [1., 0., 1., 1.],\n", - " [1., 1., 0., 1.],\n", - " [0., 1., 1., 0.]])\n", + "w = np.array(\n", + " [[0.0, 1.0, 1.0, 0.0], [1.0, 0.0, 1.0, 1.0], [1.0, 1.0, 0.0, 1.0], [0.0, 1.0, 1.0, 0.0]]\n", + ")\n", "G = nx.from_numpy_array(w)" ] }, @@ -56,9 +55,9 @@ ], "source": [ "layout = nx.random_layout(G, seed=10)\n", - "colors = ['r', 'g', 'b', 'y']\n", + "colors = [\"r\", \"g\", \"b\", \"y\"]\n", "nx.draw(G, layout, node_color=colors)\n", - "labels = nx.get_edge_attributes(G, 'weight')\n", + "labels = nx.get_edge_attributes(G, \"weight\")\n", "nx.draw_networkx_edge_labels(G, pos=layout, edge_labels=labels);" ] }, @@ -95,10 +94,12 @@ " w_01 = np.where(w != 0, 1, 0)\n", " return np.sum(w_01 * X)\n", "\n", + "\n", "def bitfield(n, L):\n", " result = np.binary_repr(n, L)\n", " return [int(digit) for digit in result] # [2:] to chop off the \"0b\" part\n", "\n", + "\n", "# use the brute-force way to generate the oracle\n", "L = num_nodes\n", "max = 2**L\n", @@ -114,7 +115,7 @@ " if cur_v < sol:\n", " sol = cur_v\n", "\n", - "print(f'Objective value computed by the brute-force method is {sol}')" + "print(f\"Objective value computed by the brute-force method is {sol}\")" ] }, { @@ -132,6 +133,7 @@ "source": [ "from qiskit.quantum_info import Pauli, SparsePauliOp\n", "\n", + "\n", "def get_operator(weight_matrix):\n", " r\"\"\"Generate Hamiltonian for the graph partitioning\n", " Notes:\n", @@ -179,6 +181,7 @@ "\n", " return SparsePauliOp(pauli_list, coeffs=coeffs), shift\n", "\n", + "\n", "qubit_op, offset = get_operator(w)" ] }, @@ -215,6 +218,7 @@ "\n", "sampler = Sampler()\n", "\n", + "\n", "def sample_most_likely(state_vector):\n", " \"\"\"Compute the most likely binary string from state vector.\n", " Args:\n", @@ -233,6 +237,7 @@ " x.reverse()\n", " return np.asarray(x)\n", "\n", + "\n", "algorithm_globals.random_seed = 10598\n", "\n", "optimizer = COBYLA()\n", @@ -243,7 +248,7 @@ "x = sample_most_likely(result.eigenstate)\n", "\n", "print(x)\n", - "print(f'Objective value computed by QAOA is {objective_value(x, w)}')" + "print(f\"Objective value computed by QAOA is {objective_value(x, w)}\")" ] }, { @@ -277,7 +282,7 @@ "x = sample_most_likely(result.eigenstate)\n", "\n", "print(x)\n", - "print(f'Objective value computed by the NumPyMinimumEigensolver is {objective_value(x, w)}')" + "print(f\"Objective value computed by the NumPyMinimumEigensolver is {objective_value(x, w)}\")" ] }, { @@ -318,7 +323,7 @@ "x = sample_most_likely(result.eigenstate)\n", "\n", "print(x)\n", - "print(f\"Objective value computed by SamplingVQE is {objective_value(x, w)}\")\n" + "print(f\"Objective value computed by SamplingVQE is {objective_value(x, w)}\")" ] }, { @@ -357,8 +362,9 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/06_grover.ipynb b/docs/tutorials/06_grover.ipynb index 5bafbdb3..dfd3259c 100644 --- a/docs/tutorials/06_grover.ipynb +++ b/docs/tutorials/06_grover.ipynb @@ -78,7 +78,7 @@ "from qiskit_algorithms import AmplificationProblem\n", "\n", "# the state we desire to find is '11'\n", - "good_state = ['11']\n", + "good_state = [\"11\"]\n", "\n", "# specify the oracle that marks the state '11' as a good solution\n", "oracle = QuantumCircuit(2)\n", @@ -90,7 +90,7 @@ "# now we can have a look at the Grover operator that is used in running the algorithm\n", "# (Algorithm circuits are wrapped in a gate to appear in composition as a block\n", "# so we have to decompose() the op to see it expanded into its component gates.)\n", - "problem.grover_operator.decompose().draw(output='mpl')" + "problem.grover_operator.decompose().draw(output=\"mpl\")" ] }, { @@ -125,10 +125,10 @@ "\n", "grover = Grover(sampler=Sampler())\n", "result = grover.amplify(problem)\n", - "print('Result type:', type(result))\n", + "print(\"Result type:\", type(result))\n", "print()\n", - "print('Success!' if result.oracle_evaluation else 'Failure!')\n", - "print('Top measurement:', result.top_measurement)" + "print(\"Success!\" if result.oracle_evaluation else \"Failure!\")\n", + "print(\"Top measurement:\", result.top_measurement)" ] }, { @@ -167,15 +167,15 @@ "source": [ "from qiskit.quantum_info import Statevector\n", "\n", - "oracle = Statevector.from_label('11')\n", - "problem = AmplificationProblem(oracle, is_good_state=['11'])\n", + "oracle = Statevector.from_label(\"11\")\n", + "problem = AmplificationProblem(oracle, is_good_state=[\"11\"])\n", "\n", "grover = Grover(sampler=Sampler())\n", "result = grover.amplify(problem)\n", - "print('Result type:', type(result))\n", + "print(\"Result type:\", type(result))\n", "print()\n", - "print('Success!' if result.oracle_evaluation else 'Failure!')\n", - "print('Top measurement:', result.top_measurement)" + "print(\"Success!\" if result.oracle_evaluation else \"Failure!\")\n", + "print(\"Top measurement:\", result.top_measurement)" ] }, { @@ -203,7 +203,7 @@ } ], "source": [ - "problem.grover_operator.oracle.decompose().draw(output='mpl')" + "problem.grover_operator.oracle.decompose().draw(output=\"mpl\")" ] }, { @@ -236,11 +236,11 @@ "from qiskit.exceptions import MissingOptionalLibraryError\n", "\n", "# `Oracle` (`PhaseOracle`) as the `oracle` argument\n", - "expression = '(a & b)'\n", + "expression = \"(a & b)\"\n", "try:\n", " oracle = PhaseOracle(expression)\n", " problem = AmplificationProblem(oracle)\n", - " display(problem.grover_operator.oracle.decompose().draw(output='mpl'))\n", + " display(problem.grover_operator.oracle.decompose().draw(output=\"mpl\"))\n", "except MissingOptionalLibraryError as ex:\n", " print(ex)" ] @@ -310,16 +310,18 @@ "theta = 2 * np.arccos(1 / np.sqrt(3))\n", "state_preparation = QuantumCircuit(3)\n", "state_preparation.ry(theta, 0)\n", - "state_preparation.ch(0,1)\n", + "state_preparation.ch(0, 1)\n", "state_preparation.x(1)\n", "state_preparation.h(2)\n", "\n", "# we only care about the first two bits being in state 1, thus add both possibilities for the last qubit\n", - "problem = AmplificationProblem(oracle, state_preparation=state_preparation, is_good_state=['110', '111'])\n", + "problem = AmplificationProblem(\n", + " oracle, state_preparation=state_preparation, is_good_state=[\"110\", \"111\"]\n", + ")\n", "\n", "# state_preparation\n", - "print('state preparation circuit:')\n", - "problem.grover_operator.state_preparation.draw(output='mpl')" + "print(\"state preparation circuit:\")\n", + "problem.grover_operator.state_preparation.draw(output=\"mpl\")" ] }, { @@ -339,8 +341,8 @@ "source": [ "grover = Grover(sampler=Sampler())\n", "result = grover.amplify(problem)\n", - "print('Success!' if result.oracle_evaluation else 'Failure!')\n", - "print('Top measurement:', result.top_measurement)" + "print(\"Success!\" if result.oracle_evaluation else \"Failure!\")\n", + "print(\"Top measurement:\", result.top_measurement)" ] }, { @@ -386,7 +388,7 @@ "source": [ "oracle = QuantumCircuit(5)\n", "oracle.ccz(0, 1, 2)\n", - "oracle.draw(output='mpl')" + "oracle.draw(output=\"mpl\")" ] }, { @@ -421,7 +423,7 @@ "from qiskit.circuit.library import GroverOperator\n", "\n", "grover_op = GroverOperator(oracle, insert_barriers=True)\n", - "grover_op.decompose().draw(output='mpl')" + "grover_op.decompose().draw(output=\"mpl\")" ] }, { @@ -450,7 +452,7 @@ ], "source": [ "grover_op = GroverOperator(oracle, reflection_qubits=[0, 1, 2], insert_barriers=True)\n", - "grover_op.decompose().draw(output='mpl')" + "grover_op.decompose().draw(output=\"mpl\")" ] }, { @@ -483,9 +485,9 @@ "# a list of binary strings good state\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", - "good_state = ['11', '00']\n", + "good_state = [\"11\", \"00\"]\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", - "print(problem.is_good_state('11'))" + "print(problem.is_good_state(\"11\"))" ] }, { @@ -507,7 +509,7 @@ "oracle.cz(0, 1)\n", "good_state = [0, 1]\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", - "print(problem.is_good_state('11'))" + "print(problem.is_good_state(\"11\"))" ] }, { @@ -531,9 +533,9 @@ "# `Statevector` good state\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", - "good_state = Statevector.from_label('11')\n", + "good_state = Statevector.from_label(\"11\")\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", - "print(problem.is_good_state('11'))" + "print(problem.is_good_state(\"11\"))" ] }, { @@ -558,10 +560,11 @@ " return True\n", " return False\n", "\n", + "\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", - "print(problem.is_good_state('11'))" + "print(problem.is_good_state(\"11\"))" ] }, { @@ -592,7 +595,7 @@ "# integer iteration\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", - "problem = AmplificationProblem(oracle, is_good_state=['11'])\n", + "problem = AmplificationProblem(oracle, is_good_state=[\"11\"])\n", "grover = Grover(iterations=1)" ] }, @@ -605,7 +608,7 @@ "# list iteration\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", - "problem = AmplificationProblem(oracle, is_good_state=['11'])\n", + "problem = AmplificationProblem(oracle, is_good_state=[\"11\"])\n", "grover = Grover(iterations=[1, 2, 3])" ] }, @@ -618,7 +621,7 @@ "# using sample_from_iterations\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", - "problem = AmplificationProblem(oracle, is_good_state=['11'])\n", + "problem = AmplificationProblem(oracle, is_good_state=[\"11\"])\n", "grover = Grover(iterations=[1, 2, 3], sample_from_iterations=True)" ] }, @@ -676,11 +679,12 @@ ], "source": [ "def to_DIAMACS_CNF_format(bit_rep):\n", - " return [index+1 if val==1 else -1 * (index + 1) for index, val in enumerate(bit_rep)]\n", + " return [index + 1 if val == 1 else -1 * (index + 1) for index, val in enumerate(bit_rep)]\n", + "\n", "\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", - "problem = AmplificationProblem(oracle, is_good_state=['11'], post_processing=to_DIAMACS_CNF_format)\n", + "problem = AmplificationProblem(oracle, is_good_state=[\"11\"], post_processing=to_DIAMACS_CNF_format)\n", "problem.post_processing([1, 0, 1])" ] }, @@ -716,8 +720,9 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/07_grover_examples.ipynb b/docs/tutorials/07_grover_examples.ipynb index 0262a04e..99c6e663 100644 --- a/docs/tutorials/07_grover_examples.ipynb +++ b/docs/tutorials/07_grover_examples.ipynb @@ -24,7 +24,7 @@ "metadata": {}, "outputs": [], "source": [ - "input_3sat_instance = '''\n", + "input_3sat_instance = \"\"\"\n", "c example DIMACS-CNF 3-SAT\n", "p cnf 3 5\n", "-1 -2 -3 0\n", @@ -32,7 +32,7 @@ "1 2 -3 0\n", "1 -2 -3 0\n", "-1 2 3 0\n", - "'''" + "\"\"\"" ] }, { @@ -65,7 +65,7 @@ "from qiskit.exceptions import MissingOptionalLibraryError\n", "from qiskit.circuit.library.phase_oracle import PhaseOracle\n", "\n", - "fp = tempfile.NamedTemporaryFile(mode='w+t', delete=False)\n", + "fp = tempfile.NamedTemporaryFile(mode=\"w+t\", delete=False)\n", "fp.write(input_3sat_instance)\n", "file_name = fp.name\n", "fp.close()\n", @@ -187,7 +187,7 @@ } ], "source": [ - "expression = '(w ^ x) & ~(y ^ z) & (x & y & z)'\n", + "expression = \"(w ^ x) & ~(y ^ z) & (x & y & z)\"\n", "try:\n", " oracle = PhaseOracle(expression)\n", " problem = AmplificationProblem(oracle, is_good_state=oracle.evaluate_bitstring)\n", @@ -237,8 +237,9 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/10_pvqd.ipynb b/docs/tutorials/10_pvqd.ipynb index 464cd841..747dd7d8 100644 --- a/docs/tutorials/10_pvqd.ipynb +++ b/docs/tutorials/10_pvqd.ipynb @@ -41,9 +41,14 @@ "from qiskit.quantum_info import SparsePauliOp\n", "\n", "final_time = 1\n", - "hamiltonian = SparsePauliOp.from_sparse_list([\n", - " (\"ZZ\", [0, 1], 0.1), (\"X\", [0], 1), (\"X\", [1], 1),\n", - "], num_qubits=2)\n", + "hamiltonian = SparsePauliOp.from_sparse_list(\n", + " [\n", + " (\"ZZ\", [0, 1], 0.1),\n", + " (\"X\", [0], 1),\n", + " (\"X\", [1], 1),\n", + " ],\n", + " num_qubits=2,\n", + ")\n", "observable = SparsePauliOp([\"ZI\", \"IZ\"])" ] }, @@ -165,12 +170,7 @@ "from qiskit_algorithms import PVQD\n", "\n", "pvqd = PVQD(\n", - " fidelity,\n", - " ansatz,\n", - " initial_parameters,\n", - " estimator=estimator,\n", - " num_timesteps=100,\n", - " optimizer=bfgs\n", + " fidelity, ansatz, initial_parameters, estimator=estimator, num_timesteps=100, optimizer=bfgs\n", ")" ] }, @@ -189,7 +189,9 @@ "source": [ "from qiskit_algorithms import TimeEvolutionProblem\n", "\n", - "problem = TimeEvolutionProblem(hamiltonian, time=final_time, aux_operators=[hamiltonian, observable])" + "problem = TimeEvolutionProblem(\n", + " hamiltonian, time=final_time, aux_operators=[hamiltonian, observable]\n", + ")" ] }, { @@ -698,6 +700,7 @@ "source": [ "import scipy as sc\n", "\n", + "\n", "def exact(final_time, timestep, hamiltonian, initial_state):\n", " \"\"\"Get the exact values for energy and the observable.\"\"\"\n", " O = observable.to_matrix()\n", @@ -729,7 +732,9 @@ "from qiskit.quantum_info import Statevector\n", "\n", "initial_state = Statevector(ansatz.bind_parameters(initial_parameters))\n", - "exact_times, exact_energies, exact_magnetizations = exact(final_time, 0.01, hamiltonian, initial_state)" + "exact_times, exact_energies, exact_magnetizations = exact(\n", + " final_time, 0.01, hamiltonian, initial_state\n", + ")" ] }, { @@ -880,9 +885,9 @@ "source": [ "energies_gd = np.real(result_gd.observables)[:, 0]\n", "\n", - "plt.plot(result.times[:n + 1], energies[:n + 1], \"-\", color=\"royalblue\", label=\"BFGS\")\n", + "plt.plot(result.times[: n + 1], energies[: n + 1], \"-\", color=\"royalblue\", label=\"BFGS\")\n", "plt.plot(result_gd.times, energies_gd, \"--\", color=\"royalblue\", label=\"Gradient descent\")\n", - "plt.plot(exact_times[:n + 1], exact_energies[:n + 1], \":\", color=\"k\", label=\"Exact\")\n", + "plt.plot(exact_times[: n + 1], exact_energies[: n + 1], \":\", color=\"k\", label=\"Exact\")\n", "plt.legend(loc=\"best\")\n", "plt.xlabel(\"time $t$\")\n", "plt.ylabel(\"energy $E$\")\n", @@ -931,9 +936,9 @@ "source": [ "magnetizations_gd = np.real(result_gd.observables)[:, 1]\n", "\n", - "plt.plot(result.times[:n + 1], magnetizations[:n + 1], \"-\", color=\"crimson\", label=\"BFGS\")\n", + "plt.plot(result.times[: n + 1], magnetizations[: n + 1], \"-\", color=\"crimson\", label=\"BFGS\")\n", "plt.plot(result_gd.times, magnetizations_gd, \"--\", color=\"crimson\", label=\"Gradient descent\")\n", - "plt.plot(exact_times[:n + 1], exact_magnetizations[:n + 1], \":\", color=\"k\", label=\"Exact\")\n", + "plt.plot(exact_times[: n + 1], exact_magnetizations[: n + 1], \":\", color=\"k\", label=\"Exact\")\n", "plt.legend(loc=\"best\")\n", "plt.xlabel(\"time $t$\")\n", "plt.ylabel(r\"magnetization $\\langle Z_1 + Z_2 \\rangle$\")\n", @@ -979,8 +984,9 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/11_VarQTE.ipynb b/docs/tutorials/11_VarQTE.ipynb index 2dc2eb9a..78632154 100644 --- a/docs/tutorials/11_VarQTE.ipynb +++ b/docs/tutorials/11_VarQTE.ipynb @@ -85,10 +85,9 @@ "source": [ "from qiskit.quantum_info import SparsePauliOp\n", "\n", - "hamiltonian = SparsePauliOp(['ZZ', 'IX', 'XI'],\n", - " coeffs=[-0.2 , -1, -1])\n", + "hamiltonian = SparsePauliOp([\"ZZ\", \"IX\", \"XI\"], coeffs=[-0.2, -1, -1])\n", "\n", - "magnetization = SparsePauliOp([ 'IZ', 'ZI'], coeffs=[1, 1])" + "magnetization = SparsePauliOp([\"IZ\", \"ZI\"], coeffs=[1, 1])" ] }, { @@ -130,7 +129,7 @@ "from qiskit.circuit.library import EfficientSU2\n", "\n", "ansatz = EfficientSU2(hamiltonian.num_qubits, reps=1)\n", - "ansatz.decompose().draw('mpl')" + "ansatz.decompose().draw(\"mpl\")" ] }, { @@ -152,9 +151,9 @@ "source": [ "import numpy as np\n", "\n", - "init_param_values={}\n", + "init_param_values = {}\n", "for i in range(len(ansatz.parameters)):\n", - " init_param_values[ansatz.parameters[i]]=np.pi/2" + " init_param_values[ansatz.parameters[i]] = np.pi / 2" ] }, { @@ -274,7 +273,9 @@ "source": [ "from qiskit_algorithms import SciPyImaginaryEvolver\n", "\n", - "evolution_problem = TimeEvolutionProblem(hamiltonian, time, initial_state=init_state, aux_operators=aux_ops)\n", + "evolution_problem = TimeEvolutionProblem(\n", + " hamiltonian, time, initial_state=init_state, aux_operators=aux_ops\n", + ")\n", "exact_evol = SciPyImaginaryEvolver(num_timesteps=501)\n", "sol = exact_evol.evolve(evolution_problem)" ] @@ -323,8 +324,8 @@ "exact_h_exp_val = sol.observables[0][0].real\n", "\n", "times = evolution_result.times\n", - "pylab.plot(times, h_exp_val, label= \"VarQITE\")\n", - "pylab.plot(times, exact_h_exp_val , label= \"Exact\", linestyle='--')\n", + "pylab.plot(times, h_exp_val, label=\"VarQITE\")\n", + "pylab.plot(times, exact_h_exp_val, label=\"Exact\", linestyle=\"--\")\n", "pylab.xlabel(\"Time\")\n", "pylab.ylabel(r\"$\\langle H \\rangle$ (energy)\")\n", "pylab.legend(loc=\"upper right\");" @@ -383,7 +384,7 @@ "source": [ "from qiskit_algorithms.gradients import ReverseEstimatorGradient, ReverseQGT\n", "\n", - "var_principle = ImaginaryMcLachlanPrinciple(qgt=ReverseQGT() , gradient=ReverseEstimatorGradient())\n", + "var_principle = ImaginaryMcLachlanPrinciple(qgt=ReverseQGT(), gradient=ReverseEstimatorGradient())\n", "evolution_problem = TimeEvolutionProblem(hamiltonian, time, aux_operators=aux_ops)\n", "var_qite = VarQITE(ansatz, init_param_values, var_principle, Estimator())\n", "evolution_result_eff = var_qite.evolve(evolution_problem)" @@ -429,8 +430,8 @@ "exact_h_exp_val_eff = sol.observables[0][0].real\n", "\n", "times = evolution_result_eff.times\n", - "pylab.plot(times, h_exp_val_eff, label= r\"VarQITE$_{eff}$\")\n", - "pylab.plot(times, exact_h_exp_val_eff , label= \"Exact\", linestyle='--')\n", + "pylab.plot(times, h_exp_val_eff, label=r\"VarQITE$_{eff}$\")\n", + "pylab.plot(times, exact_h_exp_val_eff, label=\"Exact\", linestyle=\"--\")\n", "pylab.xlabel(\"Time\")\n", "pylab.ylabel(r\"$\\langle H \\rangle$ (energy)\")\n", "pylab.legend(loc=\"upper right\");" @@ -505,8 +506,8 @@ } ], "source": [ - "pylab.plot(times, (h_exp_val-exact_h_exp_val), label=\"VarQITE\")\n", - "pylab.plot(times, (h_exp_val_eff-exact_h_exp_val_eff), label=r\"VarQITE$_{eff}$\", linestyle='--')\n", + "pylab.plot(times, (h_exp_val - exact_h_exp_val), label=\"VarQITE\")\n", + "pylab.plot(times, (h_exp_val_eff - exact_h_exp_val_eff), label=r\"VarQITE$_{eff}$\", linestyle=\"--\")\n", "pylab.xlabel(\"Time\")\n", "pylab.ylabel(r\"$\\Delta \\langle H \\rangle$\")\n", "pylab.legend(loc=\"upper right\");" @@ -569,7 +570,7 @@ ], "source": [ "ansatz = EfficientSU2(hamiltonian.num_qubits, reps=1)\n", - "ansatz.decompose().draw('mpl')" + "ansatz.decompose().draw(\"mpl\")" ] }, { @@ -592,7 +593,9 @@ "init_param_values = {}\n", "\n", "for i in range(len(ansatz.parameters)):\n", - " init_param_values[ansatz.parameters[i]] = np.pi/2 # initialize the parameters which also decide the initial state" + " init_param_values[ansatz.parameters[i]] = (\n", + " np.pi / 2\n", + " ) # initialize the parameters which also decide the initial state" ] }, { @@ -686,7 +689,7 @@ "\n", "time = 10.0\n", "evolution_problem = TimeEvolutionProblem(hamiltonian, time, aux_operators=aux_ops)\n", - "var_qrte = VarQRTE(ansatz, init_param_values,var_principle, Estimator())\n", + "var_qrte = VarQRTE(ansatz, init_param_values, var_principle, Estimator())\n", "evolution_result_re = var_qrte.evolve(evolution_problem)" ] }, @@ -729,7 +732,9 @@ "source": [ "from qiskit_algorithms import SciPyRealEvolver\n", "\n", - "evolution_problem = TimeEvolutionProblem(hamiltonian, time, initial_state = init_circ, aux_operators=aux_ops)\n", + "evolution_problem = TimeEvolutionProblem(\n", + " hamiltonian, time, initial_state=init_circ, aux_operators=aux_ops\n", + ")\n", "rtev = SciPyRealEvolver(1001)\n", "sol = rtev.evolve(evolution_problem)" ] @@ -772,8 +777,8 @@ "mz_exp_val_re = np.array([ele[0][0] for ele in evolution_result_re.observables])\n", "exact_mz_exp_val_re = sol.observables[0][0].real\n", "times = evolution_result_re.times\n", - "pylab.plot(times, mz_exp_val_re, label= \"VarQRTE\")\n", - "pylab.plot(times, exact_mz_exp_val_re , label= \"Exact\", linestyle='--')\n", + "pylab.plot(times, mz_exp_val_re, label=\"VarQRTE\")\n", + "pylab.plot(times, exact_mz_exp_val_re, label=\"Exact\", linestyle=\"--\")\n", "pylab.xlabel(\"Time\")\n", "pylab.ylabel(r\"$\\langle m_z \\rangle$\")\n", "pylab.legend(loc=\"upper right\");" @@ -800,10 +805,12 @@ "source": [ "from qiskit_algorithms.gradients import DerivativeType\n", "\n", - "var_principle = RealMcLachlanPrinciple(qgt=ReverseQGT() , gradient=ReverseEstimatorGradient(derivative_type=DerivativeType.IMAG))\n", + "var_principle = RealMcLachlanPrinciple(\n", + " qgt=ReverseQGT(), gradient=ReverseEstimatorGradient(derivative_type=DerivativeType.IMAG)\n", + ")\n", "time = 10.0\n", "evolution_problem = TimeEvolutionProblem(hamiltonian, time, aux_operators=aux_ops)\n", - "var_qrte = VarQRTE(ansatz, init_param_values,var_principle, Estimator())\n", + "var_qrte = VarQRTE(ansatz, init_param_values, var_principle, Estimator())\n", "evolution_result_re_eff = var_qrte.evolve(evolution_problem)" ] }, @@ -837,8 +844,8 @@ ], "source": [ "mz_exp_val_re_eff = np.array([ele[0][0] for ele in evolution_result_re_eff.observables])\n", - "pylab.plot(times, mz_exp_val_re_eff, label= r\"VarQRTE$_{eff}$\")\n", - "pylab.plot(times, exact_mz_exp_val_re , label= \"Exact\", linestyle='--')\n", + "pylab.plot(times, mz_exp_val_re_eff, label=r\"VarQRTE$_{eff}$\")\n", + "pylab.plot(times, exact_mz_exp_val_re, label=\"Exact\", linestyle=\"--\")\n", "pylab.xlabel(\"Time\")\n", "pylab.ylabel(r\"$\\langle m_z \\rangle$\")\n", "pylab.legend(loc=\"upper right\");" @@ -879,8 +886,10 @@ } ], "source": [ - "pylab.plot(times, (mz_exp_val_re-exact_mz_exp_val_re), label= \"VarQRTE\")\n", - "pylab.plot(times, (mz_exp_val_re_eff-exact_mz_exp_val_re), label= r\"VarQRTE$_{eff}$\", linestyle='--')\n", + "pylab.plot(times, (mz_exp_val_re - exact_mz_exp_val_re), label=\"VarQRTE\")\n", + "pylab.plot(\n", + " times, (mz_exp_val_re_eff - exact_mz_exp_val_re), label=r\"VarQRTE$_{eff}$\", linestyle=\"--\"\n", + ")\n", "pylab.xlabel(\"Time\")\n", "pylab.ylabel(r\"$\\Delta \\langle m_z \\rangle$\")\n", "pylab.legend(loc=\"upper right\");" @@ -925,8 +934,9 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/12_gradients_framework.ipynb b/docs/tutorials/12_gradients_framework.ipynb index 71e9863d..24b693d8 100644 --- a/docs/tutorials/12_gradients_framework.ipynb +++ b/docs/tutorials/12_gradients_framework.ipynb @@ -144,21 +144,21 @@ "from qiskit.quantum_info import SparsePauliOp\n", "import numpy as np\n", "\n", - "#Instantiate the quantum circuit\n", - "a = Parameter('a')\n", - "b = Parameter('b')\n", + "# Instantiate the quantum circuit\n", + "a = Parameter(\"a\")\n", + "b = Parameter(\"b\")\n", "q = QuantumRegister(1)\n", "qc = QuantumCircuit(q)\n", "qc.h(q)\n", "qc.rz(a, q[0])\n", "qc.rx(b, q[0])\n", "\n", - "display(qc.draw('mpl'))\n", + "display(qc.draw(\"mpl\"))\n", "\n", - "#Instantiate the Hamiltonian observable 2X+Z\n", - "H = SparsePauliOp.from_list([('X', 2), ('Z',1)])\n", + "# Instantiate the Hamiltonian observable 2X+Z\n", + "H = SparsePauliOp.from_list([(\"X\", 2), (\"Z\", 1)])\n", "\n", - "#Parameter list\n", + "# Parameter list\n", "params = [[np.pi / 4, 0]]" ] }, @@ -200,15 +200,15 @@ "from qiskit.primitives import Estimator\n", "from qiskit_algorithms.gradients import ParamShiftEstimatorGradient\n", "\n", - "#Define the estimator\n", + "# Define the estimator\n", "estimator = Estimator()\n", - "#Define the gradient\n", + "# Define the gradient\n", "gradient = ParamShiftEstimatorGradient(estimator)\n", "\n", "# Evaluate the gradient of the circuits using parameter shift gradients\n", - "pse_grad_result = gradient.run(qc, H, params).result().gradients\n", + "pse_grad_result = gradient.run(qc, H, params).result().gradients\n", "\n", - "print('State estimator gradient computed with parameter shift', pse_grad_result)" + "print(\"State estimator gradient computed with parameter shift\", pse_grad_result)" ] }, { @@ -239,17 +239,17 @@ ], "source": [ "# Instantiate the quantum state with two parameters\n", - "a = Parameter('a')\n", - "b = Parameter('b')\n", + "a = Parameter(\"a\")\n", + "b = Parameter(\"b\")\n", "\n", "q = QuantumRegister(1)\n", "qc_sample = QuantumCircuit(q)\n", "qc_sample.h(q)\n", "qc_sample.rz(a, q[0])\n", "qc_sample.rx(b, q[0])\n", - "qc_sample.measure_all() #important for sampler\n", + "qc_sample.measure_all() # important for sampler\n", "\n", - "qc_sample.draw('mpl')" + "qc_sample.draw(\"mpl\")" ] }, { @@ -269,11 +269,11 @@ "from qiskit.primitives import Sampler\n", "from qiskit_algorithms.gradients import ParamShiftSamplerGradient\n", "\n", - "param_vals = [[np.pi/4, np.pi/2]]\n", + "param_vals = [[np.pi / 4, np.pi / 2]]\n", "sampler = Sampler()\n", "gradient = ParamShiftSamplerGradient(sampler)\n", "pss_grad_result = gradient.run(qc_sample, param_vals).result().gradients\n", - "print('State sampler gradient computed with parameter shift', pss_grad_result)" + "print(\"State sampler gradient computed with parameter shift\", pss_grad_result)" ] }, { @@ -322,7 +322,7 @@ "\n", "# Evaluate the gradient\n", "lce_grad_result = state_grad.run(qc, H, params).result().gradients\n", - "print('State estimator gradient computed with the linear combination method', lce_grad_result)" + "print(\"State estimator gradient computed with the linear combination method\", lce_grad_result)" ] }, { @@ -357,11 +357,11 @@ "source": [ "from qiskit_algorithms.gradients import FiniteDiffEstimatorGradient\n", "\n", - "state_grad = FiniteDiffEstimatorGradient(estimator, epsilon = 0.001)\n", + "state_grad = FiniteDiffEstimatorGradient(estimator, epsilon=0.001)\n", "\n", "# Evaluate the gradient\n", "fde_grad_result = state_grad.run(qc, H, params).result().gradients\n", - "print('State estimator gradient computed with finite difference', fde_grad_result)" + "print(\"State estimator gradient computed with finite difference\", fde_grad_result)" ] }, { @@ -389,11 +389,11 @@ "source": [ "from qiskit_algorithms.gradients import SPSAEstimatorGradient\n", "\n", - "state_grad = SPSAEstimatorGradient(estimator, epsilon = 0.001, batch_size=10, seed=50)\n", + "state_grad = SPSAEstimatorGradient(estimator, epsilon=0.001, batch_size=10, seed=50)\n", "\n", "# Evaluate the gradient\n", "spsae_grad_result = state_grad.run(qc, H, params).result().gradients\n", - "print('State estimator gradient computed with SPSA:', spsae_grad_result)" + "print(\"State estimator gradient computed with SPSA:\", spsae_grad_result)" ] }, { @@ -435,11 +435,11 @@ "\n", "qgt = LinCombQGT(estimator, derivative_type=DerivativeType.COMPLEX)\n", "\n", - "param_vals = [[np.pi/4, 0.1]]\n", + "param_vals = [[np.pi / 4, 0.1]]\n", "\n", - "#Evaluate the QGTs\n", + "# Evaluate the QGTs\n", "qgt_result = qgt.run(qc, param_vals).result().qgts\n", - "print('QGT:')\n", + "print(\"QGT:\")\n", "print(qgt_result)" ] }, @@ -479,12 +479,12 @@ "source": [ "from qiskit_algorithms.gradients import QFI\n", "\n", - "#Define the QFI metric for the QGT\n", + "# Define the QFI metric for the QGT\n", "qfi = QFI(qgt)\n", "\n", "# Evaluate the QFI\n", "qfi_result = qfi.run(qc, param_vals).result().qfis\n", - "print('QFI:')\n", + "print(\"QFI:\")\n", "print(qfi_result)" ] }, @@ -545,17 +545,16 @@ "from qiskit.circuit import ParameterVector\n", "\n", "# Instantiate the system Hamiltonian\n", - "h2_hamiltonian = SparsePauliOp.from_list([('II', -1.05),\n", - " ('IZ', 0.39),\n", - " ('ZI', -0.39),\n", - " ('ZZ', -0.01)])\n", + "h2_hamiltonian = SparsePauliOp.from_list(\n", + " [(\"II\", -1.05), (\"IZ\", 0.39), (\"ZI\", -0.39), (\"ZZ\", -0.01)]\n", + ")\n", "\n", "# This is the target energy\n", "h2_energy = -1.85727503\n", "\n", "# Define the Ansatz\n", "wavefunction = QuantumCircuit(2)\n", - "params = ParameterVector('theta', length=8)\n", + "params = ParameterVector(\"theta\", length=8)\n", "it = iter(params)\n", "wavefunction.ry(next(it), 0)\n", "wavefunction.ry(next(it), 1)\n", @@ -567,7 +566,7 @@ "wavefunction.rz(next(it), 0)\n", "wavefunction.rz(next(it), 1)\n", "\n", - "wavefunction.draw('mpl')" + "wavefunction.draw(\"mpl\")" ] }, { @@ -576,7 +575,7 @@ "metadata": {}, "outputs": [], "source": [ - "#Make circuit copies for different VQEs\n", + "# Make circuit copies for different VQEs\n", "wavefunction_1 = wavefunction.copy()\n", "wavefunction_2 = wavefunction.copy()" ] @@ -610,16 +609,16 @@ "from qiskit_algorithms.optimizers import CG\n", "from qiskit_algorithms import VQE, SamplingVQE\n", "\n", - "#Conjugate Gradient algorithm\n", + "# Conjugate Gradient algorithm\n", "optimizer = CG(maxiter=50)\n", "\n", "# Gradient callable\n", "estimator = Estimator()\n", - "grad = LinCombEstimatorGradient(estimator) # optional estimator gradient\n", + "grad = LinCombEstimatorGradient(estimator) # optional estimator gradient\n", "vqe = VQE(estimator=estimator, ansatz=wavefunction, optimizer=optimizer, gradient=grad)\n", "\n", "result = vqe.compute_minimum_eigenvalue(h2_hamiltonian)\n", - "print('Result of Estimator VQE:', result.optimal_value, '\\nReference:', h2_energy)" + "print(\"Result of Estimator VQE:\", result.optimal_value, \"\\nReference:\", h2_energy)" ] }, { @@ -653,11 +652,11 @@ "source": [ "from scipy.optimize import minimize\n", "\n", - "#Classical optimizer\n", + "# Classical optimizer\n", "vqe_classical = VQE(estimator=estimator, ansatz=wavefunction_2, optimizer=minimize, gradient=grad)\n", "\n", "result_classical = vqe_classical.compute_minimum_eigenvalue(h2_hamiltonian)\n", - "print('Result of classical optimizer:', result_classical.optimal_value, '\\nReference:', h2_energy)" + "print(\"Result of classical optimizer:\", result_classical.optimal_value, \"\\nReference:\", h2_energy)" ] }, { @@ -696,8 +695,9 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", - "%qiskit_copyright\n" + "%qiskit_copyright" ] } ], diff --git a/docs/tutorials/13_trotterQRTE.ipynb b/docs/tutorials/13_trotterQRTE.ipynb index 2fc61b1e..738e46e5 100644 --- a/docs/tutorials/13_trotterQRTE.ipynb +++ b/docs/tutorials/13_trotterQRTE.ipynb @@ -62,15 +62,16 @@ "from qiskit.quantum_info import SparsePauliOp\n", "from math import sin, cos\n", "\n", + "\n", "def get_hamiltonian(L, J, h, alpha=0):\n", - " \n", + "\n", " # List of Hamiltonian terms as 3-tuples containing\n", " # (1) the Pauli string,\n", " # (2) the qubit indices corresponding to the Pauli string,\n", " # (3) the coefficient.\n", - " ZZ_tuples = [('ZZ', [i, i + 1], -J) for i in range(0, L-1)]\n", - " Z_tuples = [('Z', [i], -h * sin(alpha)) for i in range(0, L)]\n", - " X_tuples = [('X', [i], -h * cos(alpha)) for i in range(0, L)]\n", + " ZZ_tuples = [(\"ZZ\", [i, i + 1], -J) for i in range(0, L - 1)]\n", + " Z_tuples = [(\"Z\", [i], -h * sin(alpha)) for i in range(0, L)]\n", + " X_tuples = [(\"X\", [i], -h * cos(alpha)) for i in range(0, L)]\n", "\n", " # We create the Hamiltonian as a SparsePauliOp, via the method\n", " # `from_sparse_list`, and multiply by the interaction term.\n", @@ -108,7 +109,7 @@ "source": [ "from math import pi\n", "\n", - "H = get_hamiltonian(L=2, J=.2, h=1., alpha=pi/8)\n", + "H = get_hamiltonian(L=2, J=0.2, h=1.0, alpha=pi / 8)\n", "H" ] }, @@ -135,7 +136,7 @@ "\n", "# First spin up, second spin down\n", "# (remember that the labels are interpreted from right to left)\n", - "initial_state = Statevector.from_label('10')\n", + "initial_state = Statevector.from_label(\"10\")\n", "\n", "problem = TimeEvolutionProblem(H, initial_state=initial_state, time=final_time)" ] @@ -189,7 +190,7 @@ } ], "source": [ - "result.evolved_state.draw('mpl')" + "result.evolved_state.draw(\"mpl\")" ] }, { @@ -219,7 +220,9 @@ } ], "source": [ - "result.evolved_state.decompose(reps=2).decompose('disentangler_dg').decompose('multiplex1_reverse_dg').draw('mpl')" + "result.evolved_state.decompose(reps=2).decompose(\"disentangler_dg\").decompose(\n", + " \"multiplex1_reverse_dg\"\n", + ").draw(\"mpl\")" ] }, { @@ -290,7 +293,7 @@ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", - "bar_width = .1\n", + "bar_width = 0.1\n", "# We prepare an initial state ↑↓ (01).\n", "# Note that Statevector and SparsePauliOp interpret the qubits from right to left\n", "initial_state = Statevector.from_label(\"10\")\n", @@ -300,10 +303,10 @@ "\n", "# We create the list of angles in radians, with a small epsilon\n", "# the exactly longitudinal field, which would present no dynamics at all\n", - "alphas = np.linspace(-np.pi/2 + eps, np.pi/2 - eps, 5)\n", + "alphas = np.linspace(-np.pi / 2 + eps, np.pi / 2 - eps, 5)\n", "\n", "for i, alpha in enumerate(alphas):\n", - " H_alpha = get_hamiltonian(L=2, J=.2, h=1., alpha=alpha)\n", + " H_alpha = get_hamiltonian(L=2, J=0.2, h=1.0, alpha=alpha)\n", " problem = TimeEvolutionProblem(H_alpha, initial_state=initial_state, time=1.6)\n", " result = trotter.evolve(problem)\n", " evolved_state = Statevector(result.evolved_state)\n", @@ -313,7 +316,7 @@ " values = list(amplitudes_dict.values())\n", " # Convert angle to degrees\n", " alpha_str = f\"$\\\\alpha={int(np.round(alpha * 180 / pi))}^\\\\circ$\"\n", - " plt.bar(np.arange(4) + i * bar_width, values, bar_width, label=alpha_str, alpha=.7)\n", + " plt.bar(np.arange(4) + i * bar_width, values, bar_width, label=alpha_str, alpha=0.7)\n", "\n", "plt.xticks(np.arange(4) + 2 * bar_width, labels)\n", "plt.xlabel(\"Measurement\")\n", @@ -359,7 +362,7 @@ "from math import pi\n", "\n", "L = 6\n", - "H = get_hamiltonian(L=L, J=.2, h=1.2, alpha=pi/8)" + "H = get_hamiltonian(L=L, J=0.2, h=1.2, alpha=pi / 8)" ] }, { @@ -399,8 +402,12 @@ "metadata": {}, "outputs": [], "source": [ - "magnetization_op = SparsePauliOp.from_sparse_list([('Z', [i], 1.) for i in range(0, L)], num_qubits=L)\n", - "correlation_op = SparsePauliOp.from_sparse_list([('ZZ', [i, i+1], 1.) for i in range(0, L-1)], num_qubits=L) / (L - 1)" + "magnetization_op = SparsePauliOp.from_sparse_list(\n", + " [(\"Z\", [i], 1.0) for i in range(0, L)], num_qubits=L\n", + ")\n", + "correlation_op = SparsePauliOp.from_sparse_list(\n", + " [(\"ZZ\", [i, i + 1], 1.0) for i in range(0, L - 1)], num_qubits=L\n", + ") / (L - 1)" ] }, { @@ -421,9 +428,14 @@ "metadata": {}, "outputs": [], "source": [ - "final_time = 30.\n", - "initial_state = Statevector.from_label('001100')\n", - "problem = TimeEvolutionProblem(H, initial_state=initial_state, time=final_time, aux_operators=[H, magnetization_op, correlation_op])" + "final_time = 30.0\n", + "initial_state = Statevector.from_label(\"001100\")\n", + "problem = TimeEvolutionProblem(\n", + " H,\n", + " initial_state=initial_state,\n", + " time=final_time,\n", + " aux_operators=[H, magnetization_op, correlation_op],\n", + ")" ] }, { @@ -507,10 +519,16 @@ "import matplotlib.pyplot as plt\n", "\n", "fig, axes = plt.subplots(3, sharex=True)\n", - "times = np.linspace(0, final_time, num_timesteps + 1) # includes initial state\n", - "axes[0].plot(times, observables[:, 0], label='First order', marker='x', c='darkmagenta', ls='-', lw=.8)\n", - "axes[1].plot(times, observables[:, 1], label='First order', marker='x', c='darkmagenta', ls='-', lw=.8)\n", - "axes[2].plot(times, observables[:, 2], label='First order', marker='x', c='darkmagenta', ls='-', lw=.8)\n", + "times = np.linspace(0, final_time, num_timesteps + 1) # includes initial state\n", + "axes[0].plot(\n", + " times, observables[:, 0], label=\"First order\", marker=\"x\", c=\"darkmagenta\", ls=\"-\", lw=0.8\n", + ")\n", + "axes[1].plot(\n", + " times, observables[:, 1], label=\"First order\", marker=\"x\", c=\"darkmagenta\", ls=\"-\", lw=0.8\n", + ")\n", + "axes[2].plot(\n", + " times, observables[:, 2], label=\"First order\", marker=\"x\", c=\"darkmagenta\", ls=\"-\", lw=0.8\n", + ")\n", "axes[0].set_ylabel(\"Energy\")\n", "axes[1].set_ylabel(\"Magnetization\")\n", "axes[2].set_ylabel(\"Mean spin correlation\")\n", @@ -547,7 +565,9 @@ "exact_times = np.linspace(0, final_time, 101)\n", "\n", "# We compute the exact evolution using the exp\n", - "exact_evolution = [initial_state.evolve(sc.linalg.expm(-1j * time * H_array)) for time in exact_times]" + "exact_evolution = [\n", + " initial_state.evolve(sc.linalg.expm(-1j * time * H_array)) for time in exact_times\n", + "]" ] }, { @@ -597,11 +617,16 @@ } ], "source": [ - "axes[0].plot(exact_times, exact_energy, c='k', ls=':', label='Exact')\n", - "axes[1].plot(exact_times, exact_magnetization, c='k', ls=':', label='Exact')\n", - "axes[2].plot(exact_times, exact_correlation, c='k', ls=':', label='Exact')\n", + "axes[0].plot(exact_times, exact_energy, c=\"k\", ls=\":\", label=\"Exact\")\n", + "axes[1].plot(exact_times, exact_magnetization, c=\"k\", ls=\":\", label=\"Exact\")\n", + "axes[2].plot(exact_times, exact_correlation, c=\"k\", ls=\":\", label=\"Exact\")\n", "# Select the labels of only the first axis\n", - "legend = fig.legend(*axes[0].get_legend_handles_labels(), bbox_to_anchor=(1., .5), loc='center left', framealpha=.5)\n", + "legend = fig.legend(\n", + " *axes[0].get_legend_handles_labels(),\n", + " bbox_to_anchor=(1.0, 0.5),\n", + " loc=\"center left\",\n", + " framealpha=0.5,\n", + ")\n", "fig.tight_layout()\n", "fig" ] @@ -683,7 +708,8 @@ "circuit = circuit.decompose(reps=2)\n", "\n", "# Let us print some stats\n", - "print(f\"\"\"\n", + "print(\n", + " f\"\"\"\n", "Trotter step with Lie-Trotter\n", "-----------------------------\n", "\n", @@ -691,10 +717,11 @@ " Gate count: {len(circuit)}\n", " Nonlocal gate count: {circuit.num_nonlocal_gates()}\n", " Gate breakdown: {\", \".join([f\"{k.upper()}: {v}\" for k, v in circuit.count_ops().items()])}\n", - "\"\"\")\n", + "\"\"\"\n", + ")\n", "\n", "# And finally draw the circuit\n", - "circuit.draw('mpl')" + "circuit.draw(\"mpl\")" ] }, { @@ -748,14 +775,15 @@ "source": [ "from qiskit.synthesis import SuzukiTrotter\n", "\n", - "second_order_formula = SuzukiTrotter() # if not passed, order defaults to 2\n", + "second_order_formula = SuzukiTrotter() # if not passed, order defaults to 2\n", "trotter_step_second_order = PauliEvolutionGate(H, dt, synthesis=second_order_formula)\n", "circuit = QuantumCircuit(H.num_qubits)\n", "circuit.append(trotter_step_second_order, range(H.num_qubits))\n", "circuit = circuit.decompose(reps=2)\n", "\n", "# Let us print some stats\n", - "print(f\"\"\"\n", + "print(\n", + " f\"\"\"\n", "Trotter step with Suzuki Trotter (2nd order)\n", "--------------------------------------------\n", "\n", @@ -764,10 +792,11 @@ " Nonlocal gate count: {circuit.num_nonlocal_gates()}\n", " Gate breakdown: {\", \".join([f\"{k.upper()}: {v}\" for k, v in circuit.count_ops().items()])}\n", "\n", - "\"\"\")\n", + "\"\"\"\n", + ")\n", "\n", "# And finall\n", - "circuit.draw('mpl')" + "circuit.draw(\"mpl\")" ] }, { @@ -803,7 +832,8 @@ "circuit = circuit.decompose(reps=2)\n", "\n", "# Let us print some stats\n", - "print(f\"\"\"\n", + "print(\n", + " f\"\"\"\n", "Trotter step with Suzuki Trotter (4th order)\n", "--------------------------------------------\n", "\n", @@ -812,7 +842,8 @@ " Nonlocal gate count: {circuit.num_nonlocal_gates()}\n", " Gate breakdown: {\", \".join([f\"{k.upper()}: {v}\" for k, v in circuit.count_ops().items()])}\n", "\n", - "\"\"\")" + "\"\"\"\n", + ")" ] }, { @@ -833,7 +864,12 @@ "from qiskit.synthesis import SuzukiTrotter\n", "\n", "trotter = TrotterQRTE(SuzukiTrotter(order=4), num_timesteps=num_timesteps, estimator=Estimator())\n", - "problem = TimeEvolutionProblem(H, initial_state=initial_state, time=final_time, aux_operators=[H, magnetization_op, correlation_op])\n", + "problem = TimeEvolutionProblem(\n", + " H,\n", + " initial_state=initial_state,\n", + " time=final_time,\n", + " aux_operators=[H, magnetization_op, correlation_op],\n", + ")\n", "result = trotter.evolve(problem)\n", "observables_order4 = np.array(np.array(result.observables)[:, :, 0], dtype=np.float64)" ] @@ -865,13 +901,24 @@ } ], "source": [ - "axes[0].plot(times, observables_order4[:, 0], label='Fourth Order', marker='x', c='limegreen', ls='-', lw=.8)\n", - "axes[1].plot(times, observables_order4[:, 1], label='Fourth Order', marker='x', c='limegreen', ls='-', lw=.8)\n", - "axes[2].plot(times, observables_order4[:, 2], label='Fourth Order', marker='x', c='limegreen', ls='-', lw=.8)\n", + "axes[0].plot(\n", + " times, observables_order4[:, 0], label=\"Fourth Order\", marker=\"x\", c=\"limegreen\", ls=\"-\", lw=0.8\n", + ")\n", + "axes[1].plot(\n", + " times, observables_order4[:, 1], label=\"Fourth Order\", marker=\"x\", c=\"limegreen\", ls=\"-\", lw=0.8\n", + ")\n", + "axes[2].plot(\n", + " times, observables_order4[:, 2], label=\"Fourth Order\", marker=\"x\", c=\"limegreen\", ls=\"-\", lw=0.8\n", + ")\n", "\n", "# Replace the legend\n", "legend.remove()\n", - "legend = fig.legend(*axes[0].get_legend_handles_labels(), bbox_to_anchor=(1., .5), loc='center left', framealpha=.5)\n", + "legend = fig.legend(\n", + " *axes[0].get_legend_handles_labels(),\n", + " bbox_to_anchor=(1.0, 0.5),\n", + " loc=\"center left\",\n", + " framealpha=0.5,\n", + ")\n", "fig" ] }, @@ -925,17 +972,19 @@ "\n", "# An inner list comprehension loops over the terms of the SparsePauliOp magnetization_op,\n", "# which corresponds to the magnetization of each one of the sites\n", - "magnetizations = np.real([[sv.expectation_value(term) for term in magnetization_op] for sv in exact_evolution])\n", + "magnetizations = np.real(\n", + " [[sv.expectation_value(term) for term in magnetization_op] for sv in exact_evolution]\n", + ")\n", "# The shape of magnetizations is (101, 6), containing (t) for each site 0, 1, ..., 5\n", "plt.figure(figsize=(14, 2))\n", "# Create the 2-dim xx and yy arrays tiling the grid with the x and y values\n", "xx, yy = np.meshgrid(exact_times, np.arange(L))\n", - "plt.pcolor(xx, yy, magnetizations.T, vmin=-1, vmax=+1, cmap='RdBu')\n", + "plt.pcolor(xx, yy, magnetizations.T, vmin=-1, vmax=+1, cmap=\"RdBu\")\n", "# Force the figure to have all y ticks from 0 to 5\n", "plt.yticks(np.arange(L))\n", - "plt.ylabel('Site $i$')\n", - "plt.xlabel('Time')\n", - "plt.colorbar(label='$\\\\langle Z_i \\\\rangle$', aspect=1.8)" + "plt.ylabel(\"Site $i$\")\n", + "plt.xlabel(\"Time\")\n", + "plt.colorbar(label=\"$\\\\langle Z_i \\\\rangle$\", aspect=1.8)" ] }, { @@ -985,6 +1034,7 @@ ], "source": [ "import qiskit.tools.jupyter\n", + "\n", "%qiskit_version_table\n", "%qiskit_copyright" ] diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 00000000..7d5b2f6f --- /dev/null +++ b/mypy.ini @@ -0,0 +1,11 @@ +[mypy] +warn_unused_configs = True +ignore_missing_imports = True +strict_optional = False +no_implicit_optional = True +warn_redundant_casts = True +warn_unused_ignores = True + +### Output +show_error_codes = True +show_error_context = True diff --git a/requirements-dev.txt b/requirements-dev.txt index 366b3d7d..b3b60507 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -17,6 +17,8 @@ discover rustworkx>=0.13 qiskit-aer>=0.12 networkx>=2.2 +mypy>=0.991 +mypy-extensions>=0.4.3 # Tweedledum is unmaintained and its existing Mac wheels are unreliable. If you # manage to get a working install on a Mac the functionality should still work,