| """ | |
| High-level utilities for Collatz operations. | |
| This module provides glue functions used by the web interface (app.py), | |
| combining steps such as: | |
| - generating an inverse Collatz tree, | |
| - generating the minimal subtree up to N, | |
| - computing basic statistics, | |
| - rendering graphs to Graphviz PNG images. | |
| """ | |
| from __future__ import annotations | |
| from typing import Optional, Tuple | |
| from pathlib import Path | |
| import pandas as pd | |
| from src.collatz.inverse_tree import generate_collatz_tree | |
| from src.collatz.minimal_subtree import generate_minimal_collatz_subtree_edges | |
| from src.visual.render import render_collatz_tree_graphviz | |
| from src.collatz.metrics import compute_basic_graph_stats | |
| def build_and_render_collatz_tree( | |
| backbone_length: int, | |
| branch_length: int, | |
| max_depth: int, | |
| *, | |
| filename: str = "collatz_tree", | |
| output_dir: Optional[str] = "outputs", | |
| return_edges: bool = False, | |
| ) -> Tuple[str, Optional[pd.DataFrame]]: | |
| """ | |
| Generate an inverse Collatz tree, render it as a PNG image, and optionally | |
| return the underlying edge DataFrame. | |
| """ | |
| output_path = Path(output_dir) | |
| output_path.mkdir(parents=True, exist_ok=True) | |
| df_edges: pd.DataFrame = generate_collatz_tree( | |
| backbone_length=backbone_length, | |
| branch_length=branch_length, | |
| max_depth=max_depth, | |
| ) | |
| image_path = render_collatz_tree_graphviz( | |
| df_edges=df_edges, | |
| filename=filename, | |
| directory=output_path, | |
| image_format="png", | |
| ) | |
| if return_edges: | |
| return image_path, df_edges | |
| return image_path, None | |
| def build_and_render_minimal_subtree( | |
| N: int, | |
| *, | |
| filename: str = "collatz_minimal_subtree", | |
| output_dir: Optional[str] = "outputs", | |
| return_edges: bool = False, | |
| ) -> Tuple[str, Optional[pd.DataFrame]]: | |
| """ | |
| Generate the minimal Collatz subtree containing all integers 1..N, | |
| render it as a PNG image, and optionally return the underlying | |
| edge DataFrame. | |
| This uses the structural branch construction (Algorithms 5 and 6) | |
| implemented in `generate_minimal_collatz_subtree_edges`. | |
| """ | |
| output_path = Path(output_dir) | |
| output_path.mkdir(parents=True, exist_ok=True) | |
| df_edges: pd.DataFrame = generate_minimal_collatz_subtree_edges(N) | |
| image_path = render_collatz_tree_graphviz( | |
| df_edges=df_edges, | |
| filename=filename, | |
| directory=output_path, | |
| image_format="png", | |
| ) | |
| if return_edges: | |
| return image_path, df_edges | |
| return image_path, None | |
| def compute_collatz_tree_stats( | |
| backbone_length: int, | |
| branch_length: int, | |
| max_depth: int, | |
| ) -> dict: | |
| """ | |
| Convenience helper: generate the inverse Collatz tree and return | |
| basic graph stats (number of nodes, edges, parity counts, etc.). | |
| """ | |
| df_edges = generate_collatz_tree( | |
| backbone_length=backbone_length, | |
| branch_length=branch_length, | |
| max_depth=max_depth, | |
| ) | |
| return compute_basic_graph_stats(df_edges) | |
| def safe_int(x, default: int = 1) -> int: | |
| """ | |
| Convert a value to int safely. | |
| This protects the Gradio app from crashing when users type invalid input. | |
| """ | |
| try: | |
| return int(x) | |
| except Exception: | |
| return default |