Proportioni & Regola dela Cosa (1494)

Verifies Severinus Boethius’s and Pacioli’s five genera of rational inequality (Summa Part I, Distinctio VI, fols. 70r–83r), the six Euclidean modi arguendi (fol. 74r), the exact geometor.model semicircle construction of the arithmetic, geometric, and harmonic means, the Euclidean golden cut of 10 into \(\sqrt{125}-5\) and \(15-\sqrt{125}\), and Pacioli’s six canonical Cossic quadratic equations (Distinctio VIII, fols. 145r–146r).

"""Runnable CLI demonstration of Pacioli's *Summa* (1494) proportions and Cossic algebra.

        Displays Rich tables verifying:
        1. Severinus Boethius's and Pacioli's five genera of rational inequality (*Summa* fols. 70r–83r),
        2. The six Euclidean *modi arguendi* (*Summa* fol. 74r),
        3. Exact ``geometor.model`` semicircle construction of the three classical means and the
           division of ``10`` in extreme and mean ratio,
        4. Pacioli's six canonical Cossic quadratic equations (*Summa* fols. 145r–146r).
        """

        from __future__ import annotations

        import sys
        from pathlib import Path

        _SRC = Path(__file__).resolve().parents[1] / "src"
        if str(_SRC) not in sys.path:
            sys.path.insert(0, str(_SRC))

        import sympy as sp  # noqa: E402
        from rich.console import Console  # noqa: E402
        from rich.table import Table  # noqa: E402

        from geometor.pacioli.proportions import (  # noqa: E402
            apply_six_euclidean_modes,
            classify_boethian_ratio,
            compound_ratios,
            construct_extreme_and_mean_ratio,
            construct_three_means,
            solve_cossic_quadratic,
        )


        def run_demo() -> None:
            """Execute and print the *Summa* (1494) proportions and Cossic algebra showcase."""
            console = Console()
            console.rule("[bold gold1]Fra Luca Pacioli • Summa (1494) — Proportioni & Regola dela Cosa")

            boethian_table = Table(title="Part I, Dist. VI (fols. 70r–83r): Five Boethian Genera of Ratio")
            boethian_table.add_column("Terms (p : q)", style="cyan")
            boethian_table.add_column("Reduced", style="white")
            boethian_table.add_column("Inequality", style="magenta")
            boethian_table.add_column("Genus", style="green")
            boethian_table.add_column("Latin Species", style="bold yellow")

            sample_pairs = [(6, 6), (12, 4), (9, 6), (5, 3), (5, 2), (11, 4), (3, 4)]
            for p_val, q_val in sample_pairs:
                rec = classify_boethian_ratio(p_val, q_val)
                boethian_table.add_row(
                    f"{p_val} : {q_val}",
                    f"{rec.antecedent}:{rec.consequent}",
                    rec.inequality,
                    rec.genus,
                    rec.latin_species,
                )
            console.print(boethian_table)

            octave = compound_ratios([(3, 2), (4, 3)])
            console.print(
                f"[bold]Compounded Musical Octave (fol. 83r):[/bold] "
                f"(3:2 sesquialtera) ⊗ (4:3 sesquitertia) = "
                f"[yellow]{octave.antecedent}:{octave.consequent} ({octave.latin_species})[/yellow]\n"
            )

            modes = apply_six_euclidean_modes(12, 8, 9, 6, e=4, f=3)
            console.print(
                f"[bold]Six Euclidean Modes on 12:8 = 9:6 (fol. 74r):[/bold] "
                f"conversa={modes.conversa[0]}, permutata={modes.permutata[0]}, "
                f"congionta={modes.congionta[0]}, disgiunta={modes.disgiunta[0] if modes.disgiunta else 'N/A'}, "
                f"eversa={modes.eversa[0] if modes.eversa else 'N/A'}, "
                f"equa={modes.equa[0] if modes.equa else 'N/A'}\n"
            )

            means = construct_three_means(9, 4)
            div10 = construct_extreme_and_mean_ratio(10)
            console.print(
                f"[bold]Semicircle Three Means for (9, 4) (fol. 73v):[/bold] "
                f"A = {means.arithmetic_mean}, G = {means.geometric_mean}, H = {means.harmonic_mean} "
                f"(G² = A·H = {means.geometric_mean**2}; Proof steps = {len(means.model.steps)})"
            )
            console.print(
                f"[bold]Divine Proportion of 10 (Dist. VI & Compendio Cap. VIII):[/bold] "
                f"Major = {div10.major_part}, Minor = {div10.minor_part}, "
                f"φ = {div10.phi_ratio} (Proof steps = {len(div10.model.steps)})\n"
            )

            cossic_table = Table(title="Part I, Dist. VIII (fols. 145r–146r): Six Canonical Cossic Equations")
            cossic_table.add_column("Canon", justify="right", style="cyan")
            cossic_table.add_column("Kind", style="magenta")
            cossic_table.add_column("1494 Cossic Statement", style="white")
            cossic_table.add_column("Positive Root(s)", style="bold green")
            cossic_table.add_column("Completed Square", style="yellow")

            cases = [
                (1, 2, 10, 0),
                (2, 3, 0, 27),
                (3, 0, 4, 20),
                (4, 1, 10, 39),
                (5, 1, 10, 21),
                (6, 1, 3, 4),
                (4, sp.Rational(23, 4), 16, 48),
            ]
            for canon_no, a_val, b_val, c_val in cases:
                sol = solve_cossic_quadratic(canon_no, a_val, b_val, c_val)
                roots_str = ", ".join(str(r) for r in sol.positive_roots)
                cossic_table.add_row(
                    str(sol.canon_number),
                    sol.canon_kind,
                    sol.cossic_statement,
                    roots_str,
                    str(sol.completed_square_area),
                )
            console.print(cossic_table)


        if __name__ == "__main__":
            run_demo()