sorts.benchmark_sorts ===================== .. py:module:: sorts.benchmark_sorts .. autoapi-nested-parse:: Benchmark several sorting algorithms on the same random datasets. This is a *reference* benchmark, not a rigorous one: it times each algorithm on a few shared, randomly generated integer datasets and prints a small comparison table. It exists so that visitors can see the practical cost of the different strategies in this directory side by side, without embedding timing code inside the individual algorithm modules (which keeps those files clean, import-cheap, and focused on being readable reference implementations). Run it from the repository root: python -m sorts.benchmark_sorts The individual algorithms are imported from their own modules, so this file never re-implements a sort. Attributes ---------- .. autoapisummary:: sorts.benchmark_sorts.SORTS Classes ------- .. autoapisummary:: sorts.benchmark_sorts.Comparable Functions --------- .. autoapisummary:: sorts.benchmark_sorts.all_sorts_agree sorts.benchmark_sorts.benchmark sorts.benchmark_sorts.is_sorted sorts.benchmark_sorts.main Module Contents --------------- .. py:class:: Comparable Bases: :py:obj:`Protocol` Base class for protocol classes. Protocol classes are defined as:: class Proto(Protocol): def meth(self) -> int: ... Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing). For example:: class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check See PEP 544 for details. Protocol classes decorated with @typing.runtime_checkable act as simple-minded runtime protocols that check only the presence of given attributes, ignoring their type signatures. Protocol classes can be generic, they are defined as:: class GenProto[T](Protocol): def meth(self) -> T: ... .. py:method:: __lt__(other: object, /) -> bool .. py:function:: all_sorts_agree(data: list[int]) -> bool Return True if every algorithm in ``SORTS`` sorts ``data`` correctly. Each algorithm is given a fresh copy of the data (some sort in place), and its result is checked against Python's built-in ``sorted`` as the ground truth. >>> all_sorts_agree([5, 1, 4.2, 2, 8.5, 0, 2]) True >>> all_sorts_agree([]) True >>> all_sorts_agree([42]) True >>> all_sorts_agree(list(range(5, -6, -1))) True >>> all_sorts_agree(list("Python")) True .. py:function:: benchmark[T: Comparable](data: list[T], number: int = 1) -> dict[str, float] Time every algorithm in ``SORTS`` on a copy of ``data``. Returns a mapping of algorithm name to the elapsed seconds for ``number`` repetitions. Each timed call receives its own fresh copy so in-place sorts do not hand an already-sorted list to the next repetition. >>> benchmark([]) Traceback (most recent call last): ... ValueError: Please provide a non-empty dataset >>> benchmark([1], number=0) Traceback (most recent call last): ... ValueError: Number of repetitions must be positive .. py:function:: is_sorted(collection: collections.abc.Sequence[int]) -> bool Return True if every element is less than or equal to the next one. >>> is_sorted([1, 2, 2, 3]) True >>> is_sorted([1, 3, 2]) False >>> is_sorted([]) True .. py:function:: main() -> None .. py:data:: SORTS :type: dict[str, collections.abc.Callable[[list[int]], collections.abc.Sequence[int]]]