mirror of
https://github.com/kristoferssolo/grovers-visualizer.git
synced 2025-10-21 20:10:35 +00:00
feat(args): add args functionality
This commit is contained in:
parent
70c8d50ec9
commit
083f60ffa2
@ -1,10 +1,11 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "grovers-visualizer"
|
name = "grovers-visualizer"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
description = "Add your description here"
|
description = "Add your description here"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"argparse>=1.4.0",
|
||||||
"numpy>=2.2.4",
|
"numpy>=2.2.4",
|
||||||
"qiskit-aer>=0.17.0",
|
"qiskit-aer>=0.17.0",
|
||||||
"qiskit[visualization]>=2.0.0",
|
"qiskit[visualization]>=2.0.0",
|
||||||
|
|||||||
@ -10,36 +10,23 @@ from math import asin, sqrt
|
|||||||
from typing import TYPE_CHECKING, Callable
|
from typing import TYPE_CHECKING, Callable
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from matplotlib.axes import Axes
|
|
||||||
from qiskit import QuantumCircuit
|
from qiskit import QuantumCircuit
|
||||||
from qiskit.quantum_info import Statevector
|
from qiskit.quantum_info import Statevector
|
||||||
|
|
||||||
from grovers_visualizer.circuit import diffusion, oracle
|
from grovers_visualizer.circuit import diffusion, oracle
|
||||||
|
from grovers_visualizer.parse import parse_args
|
||||||
from grovers_visualizer.plot import draw_grover_circle, plot_amplitudes_live
|
from grovers_visualizer.plot import draw_grover_circle, plot_amplitudes_live
|
||||||
from grovers_visualizer.state import QubitState
|
|
||||||
from grovers_visualizer.utils import all_states, optimal_grover_iterations
|
from grovers_visualizer.utils import all_states, optimal_grover_iterations
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from matplotlib.axes import Axes
|
||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
|
|
||||||
|
|
||||||
def plot_counts(ax: Axes, counts: dict[str, int], target_state: QubitState) -> None:
|
|
||||||
"""Display a bar chart for the measurement results."""
|
|
||||||
|
|
||||||
# Sort the states
|
|
||||||
states = list(counts.keys())
|
|
||||||
frequencies = [counts[s] for s in states]
|
|
||||||
|
|
||||||
ax.clear()
|
|
||||||
ax.bar(states, frequencies, color="skyblue")
|
|
||||||
ax.set_xlabel("Measured State")
|
|
||||||
ax.set_ylabel("Counts")
|
|
||||||
ax.set_title(f"Measurement Counts for Target: {target_state}")
|
|
||||||
ax.set_ylim(0, max(frequencies) * 1.2)
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
target_state = QubitState("1010")
|
args = parse_args()
|
||||||
|
|
||||||
|
target_state = args.target
|
||||||
n_qubits = len(target_state)
|
n_qubits = len(target_state)
|
||||||
basis_states = [str(bit) for bit in all_states(n_qubits)]
|
basis_states = [str(bit) for bit in all_states(n_qubits)]
|
||||||
optimal_iterations = optimal_grover_iterations(n_qubits)
|
optimal_iterations = optimal_grover_iterations(n_qubits)
|
||||||
@ -66,7 +53,7 @@ def main() -> None:
|
|||||||
plot_amplitudes_live(ax_bar, bars, sv, basis_states, step_label, iteration, target_state, optimal_iterations)
|
plot_amplitudes_live(ax_bar, bars, sv, basis_states, step_label, iteration, target_state, optimal_iterations)
|
||||||
draw_grover_circle(ax_circle, iteration, optimal_iterations, theta, state_angle)
|
draw_grover_circle(ax_circle, iteration, optimal_iterations, theta, state_angle)
|
||||||
|
|
||||||
plt.pause(0.5)
|
plt.pause(args.speed)
|
||||||
|
|
||||||
# Start with Hadamard
|
# Start with Hadamard
|
||||||
qc = QuantumCircuit(n_qubits)
|
qc = QuantumCircuit(n_qubits)
|
||||||
@ -74,14 +61,24 @@ def main() -> None:
|
|||||||
iterate_and_plot(None, "Hadamard (Initialization)", 0)
|
iterate_and_plot(None, "Hadamard (Initialization)", 0)
|
||||||
|
|
||||||
iteration = 1
|
iteration = 1
|
||||||
while plt.fignum_exists(fig.number):
|
running = True
|
||||||
|
|
||||||
|
def on_key(event) -> None:
|
||||||
|
nonlocal running
|
||||||
|
if event.key == "q":
|
||||||
|
running = False
|
||||||
|
|
||||||
|
cid = fig.canvas.mpl_connect("key_press_event", on_key)
|
||||||
|
while plt.fignum_exists(fig.number) and running:
|
||||||
iterate_and_plot(lambda qc: oracle(qc, target_state), "Oracle (Query Phase)", iteration)
|
iterate_and_plot(lambda qc: oracle(qc, target_state), "Oracle (Query Phase)", iteration)
|
||||||
iterate_and_plot(lambda qc: diffusion(qc, n_qubits), "Diffusion (Inversion Phase)", iteration)
|
iterate_and_plot(lambda qc: diffusion(qc, n_qubits), "Diffusion (Inversion Phase)", iteration)
|
||||||
|
|
||||||
iteration += 1
|
iteration += 1
|
||||||
|
if args.iterations > 0 and iteration > args.iterations:
|
||||||
|
break
|
||||||
|
|
||||||
|
fig.canvas.mpl_disconnect(cid)
|
||||||
plt.ioff()
|
plt.ioff()
|
||||||
plt.show()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
40
src/grovers_visualizer/parse.py
Normal file
40
src/grovers_visualizer/parse.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from argparse import ArgumentParser
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from grovers_visualizer.state import QubitState
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Args:
|
||||||
|
target: QubitState
|
||||||
|
iterations: int
|
||||||
|
speed: float
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> Args:
|
||||||
|
parser = ArgumentParser(description="Grover's Algorithm Visualizer")
|
||||||
|
parser.add_argument(
|
||||||
|
"target",
|
||||||
|
type=str,
|
||||||
|
help="Target bitstring (e.g., 1010)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-i",
|
||||||
|
"--iterations",
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
help="Number of Grover iterations (default: 0 (infinite))",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--speed",
|
||||||
|
type=float,
|
||||||
|
default=0.5,
|
||||||
|
help="Pause duration (seconds) between steps (deafult: 0.5)",
|
||||||
|
)
|
||||||
|
ns = parser.parse_args()
|
||||||
|
return Args(
|
||||||
|
target=QubitState(ns.target),
|
||||||
|
iterations=ns.iterations,
|
||||||
|
speed=ns.speed,
|
||||||
|
)
|
||||||
13
uv.lock
13
uv.lock
@ -2,6 +2,15 @@ version = 1
|
|||||||
revision = 1
|
revision = 1
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "argparse"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/18/dd/e617cfc3f6210ae183374cd9f6a26b20514bbb5a792af97949c5aacddf0f/argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4", size = 70508 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f2/94/3af39d34be01a24a6e65433d19e107099374224905f1e0cc6bbe1fd22a2f/argparse-1.4.0-py2.py3-none-any.whl", hash = "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314", size = 23000 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "contourpy"
|
name = "contourpy"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
@ -70,9 +79,10 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grovers-visualizer"
|
name = "grovers-visualizer"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
{ name = "argparse" },
|
||||||
{ name = "numpy" },
|
{ name = "numpy" },
|
||||||
{ name = "qiskit", extra = ["visualization"] },
|
{ name = "qiskit", extra = ["visualization"] },
|
||||||
{ name = "qiskit-aer" },
|
{ name = "qiskit-aer" },
|
||||||
@ -91,6 +101,7 @@ dev = [
|
|||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
|
{ name = "argparse", specifier = ">=1.4.0" },
|
||||||
{ name = "numpy", specifier = ">=2.2.4" },
|
{ name = "numpy", specifier = ">=2.2.4" },
|
||||||
{ name = "pyqt6", marker = "extra == 'mpl'", specifier = ">=6.9.0" },
|
{ name = "pyqt6", marker = "extra == 'mpl'", specifier = ">=6.9.0" },
|
||||||
{ name = "qiskit", extras = ["visualization"], specifier = ">=2.0.0" },
|
{ name = "qiskit", extras = ["visualization"], specifier = ">=2.0.0" },
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user