refactor(args): add mutually exclusive

This commit is contained in:
Kristofers Solo 2025-05-07 10:31:46 +03:00
parent 553bf667e5
commit 750cccdcd5
Signed by: kristoferssolo
GPG Key ID: 74FF8144483D82C8
5 changed files with 50 additions and 14 deletions

View File

@ -2,6 +2,7 @@ from argparse import ArgumentParser
from dataclasses import dataclass from dataclasses import dataclass
from grovers_visualizer.state import QubitState from grovers_visualizer.state import QubitState
from grovers_visualizer.utils import get_app_version
@dataclass @dataclass
@ -14,9 +15,36 @@ class Args:
def parse_args() -> Args: def parse_args() -> Args:
parser = ArgumentParser(description="Grover's Algorithm Visualizer") parser = ArgumentParser(description="Grover's Algorithm Visualizer")
parse_opts(parser)
parse_cli(parser)
ns = parser.parse_args()
return Args(
target=ns.target,
iterations=ns.iterations,
speed=ns.speed,
ui=ns.ui,
)
def parse_opts(base_parser: ArgumentParser) -> None:
parser = base_parser
parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {get_app_version()}")
def parse_cli(base_parser: ArgumentParser) -> None:
parser = base_parser.add_argument_group("cli")
parser.register("type", "qubit state", QubitState.from_str)
parser.add_argument( parser.add_argument(
"target", "target",
type=str, type="qubit state",
default=QubitState.from_str("1111"),
nargs="?",
help="Target bitstring (e.g., 1010)", help="Target bitstring (e.g., 1010)",
) )
parser.add_argument( parser.add_argument(
@ -34,10 +62,3 @@ def parse_args() -> Args:
help="Pause duration (seconds) between steps (deafult: 0.5)", help="Pause duration (seconds) between steps (deafult: 0.5)",
) )
parser.add_argument("--ui", action="store_true", help="Run with DearPyGui UI") parser.add_argument("--ui", action="store_true", help="Run with DearPyGui UI")
ns = parser.parse_args()
return Args(
target=QubitState.from_str(ns.target),
iterations=ns.iterations,
speed=ns.speed,
ui=ns.ui,
)

View File

@ -7,8 +7,8 @@ from matplotlib.gridspec import GridSpec
from qiskit import QuantumCircuit from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector from qiskit.quantum_info import Statevector
from .args import Args
from .circuit import diffusion, oracle from .circuit import diffusion, oracle
from .parse import Args
from .plot import SinePlotData, plot_amplitudes, plot_circle, plot_sine from .plot import SinePlotData, plot_amplitudes, plot_circle, plot_sine
from .utils import all_states, optimal_grover_iterations from .utils import all_states, optimal_grover_iterations

View File

@ -6,8 +6,8 @@ simulation using Qiskit's Aer simulator, and visualizes the results
using matplotlib. using matplotlib.
""" """
from .args import parse_args
from .cli import run_cli from .cli import run_cli
from .parse import parse_args
from .ui import run_dpg_ui from .ui import run_dpg_ui

View File

@ -1,6 +1,6 @@
from importlib.util import find_spec from importlib.util import find_spec
from grovers_visualizer.parse import Args from grovers_visualizer.args import Args
def is_dearpygui_available() -> bool: def is_dearpygui_available() -> bool:
@ -10,11 +10,11 @@ def is_dearpygui_available() -> bool:
return False return False
def run_dpg_ui(_args: Args) -> None: def run_dpg_ui(args: Args) -> None:
if not is_dearpygui_available(): if not is_dearpygui_available():
print("DearPyGui is not installed. Install with: pip install .[ui]") print("DearPyGui is not installed. Install with: pip install 'grovers-visualizer[ui]'")
return return
from .dpg import run_dearpygui_ui from .dpg import run_dearpygui_ui
run_dearpygui_ui() run_dearpygui_ui(args)

View File

@ -1,6 +1,8 @@
import tomllib
from collections.abc import Iterator from collections.abc import Iterator
from itertools import product from itertools import product
from math import floor, pi, sqrt from math import floor, pi, sqrt
from pathlib import Path
from .state import QubitState from .state import QubitState
@ -27,3 +29,16 @@ def get_bar_color(state: str, target_state: QubitState | None, iteration: int, o
if optimal_iteration and is_optimal_iteration(iteration, optimal_iteration): if optimal_iteration and is_optimal_iteration(iteration, optimal_iteration):
return "green" return "green"
return "orange" return "orange"
def get_app_version(pyproject_path: str = "pyproject.toml") -> str:
"""Reads the version from the [project] section of pyproject.toml."""
path = Path(pyproject_path)
if not path.is_file():
raise FileNotFoundError(f"{pyproject_path} not found.")
with path.open("rb") as f:
data = tomllib.load(f)
try:
return str(data["project"]["version"])
except KeyError:
raise KeyError("Version not found in [project] section of pyproject.toml.")