Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .coverage
Binary file not shown.
20 changes: 19 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# File: MANIFEST.in
# File: alphatriangle/MANIFEST.in
# File: MANIFEST.in
include README.md
include LICENSE
include requirements.txt
Expand All @@ -7,4 +9,20 @@ graft tests
include .python-version
include pyproject.toml
global-exclude __pycache__
global-exclude *.py[co]
global-exclude *.py[co]
# Remove pruned directories
prune alphatriangle/visualization
prune alphatriangle/interaction
# REMOVE environment and structs pruning (they are part of trianglengin now)
# prune alphatriangle/environment
# prune alphatriangle/structs
# Remove pruned files
global-exclude alphatriangle/app.py
# Remove pruned test directories
prune tests/visualization
prune tests/interaction
# REMOVE environment and structs test pruning
# prune tests/environment
# prune tests/structs
# Remove pruned core files
global-exclude alphatriangle/rl/core/visual_state_actor.py
308 changes: 218 additions & 90 deletions README.md

Large diffs are not rendered by default.

113 changes: 0 additions & 113 deletions alphatriangle/app.py

This file was deleted.

97 changes: 21 additions & 76 deletions alphatriangle/cli.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@
# File: alphatriangle/cli.py
import logging
import sys
from typing import Annotated

import typer

from alphatriangle import config, utils
from alphatriangle.app import Application
# Import EnvConfig from trianglengin
# Import alphatriangle specific configs and runner
from alphatriangle.config import (
MCTSConfig,
PersistenceConfig,
TrainConfig,
)

# --- REVERTED: Import from the re-exporting runners.py ---
from alphatriangle.training.runners import (
run_training_headless_mode,
run_training_visual_mode,
)

# --- END REVERTED ---
# Import the single runner function
from alphatriangle.training.runners import run_training

app = typer.Typer(
name="alphatriangle",
help="AlphaZero implementation for a triangle puzzle game.",
help="AlphaZero training pipeline for a triangle puzzle game (uses trianglengin).",
add_completion=False,
)

Expand Down Expand Up @@ -64,87 +57,39 @@ def setup_logging(log_level_str: str):
handlers=[logging.StreamHandler(sys.stdout)],
force=True, # Override existing config
)
logging.getLogger("ray").setLevel(logging.WARNING) # Keep Ray less verbose
logging.getLogger("matplotlib").setLevel(
logging.WARNING
) # Keep Matplotlib less verbose
logging.getLogger("ray").setLevel(logging.WARNING)
# Add trianglengin logger control if needed
logging.getLogger("trianglengin").setLevel(
logging.INFO
) # Example: Set engine log level
logging.info(f"Root logger level set to {logging.getLevelName(log_level)}")


def run_interactive_mode(mode: str, seed: int, log_level: str):
"""Runs the interactive application."""
setup_logging(log_level)
logger = logging.getLogger(__name__) # Get logger after setup
logger.info(f"Running in {mode.capitalize()} mode...")
utils.set_random_seeds(seed)

mcts_config = MCTSConfig()
config.print_config_info_and_validate(mcts_config)

try:
app_instance = Application(mode=mode)
app_instance.run()
except ImportError as e:
logger.error(f"Runtime ImportError: {e}")
logger.error("Please ensure all dependencies are installed.")
sys.exit(1)
except Exception as e:
logger.critical(f"An unhandled error occurred: {e}", exc_info=True)
sys.exit(1)

logger.info("Exiting.")
sys.exit(0)


@app.command()
def play(
log_level: LogLevelOption = "INFO",
seed: SeedOption = 42,
):
"""Run the game in interactive Play mode."""
run_interactive_mode(mode="play", seed=seed, log_level=log_level)


@app.command()
def debug(
log_level: LogLevelOption = "INFO",
seed: SeedOption = 42,
):
"""Run the game in interactive Debug mode."""
run_interactive_mode(mode="debug", seed=seed, log_level=log_level)
# --- REMOVED run_interactive_mode, play, debug commands ---


@app.command()
def train(
headless: Annotated[
bool,
typer.Option("--headless", "-H", help="Run training without visualization."),
] = False,
# REMOVE headless option - it's always headless now
log_level: LogLevelOption = "INFO",
seed: SeedOption = 42,
):
"""Run the AlphaTriangle training pipeline."""
"""Run the AlphaTriangle training pipeline (headless)."""
setup_logging(log_level)
logger = logging.getLogger(__name__)

# Use alphatriangle configs here
train_config_override = TrainConfig()
persist_config_override = PersistenceConfig()
train_config_override.RANDOM_SEED = seed

if headless:
logger.info("Starting training in Headless mode...")
exit_code = run_training_headless_mode(
log_level_str=log_level,
train_config_override=train_config_override,
persist_config_override=persist_config_override,
)
else:
logger.info("Starting training in Visual mode...")
exit_code = run_training_visual_mode(
log_level_str=log_level,
train_config_override=train_config_override,
persist_config_override=persist_config_override,
)
logger.info("Starting training...")
# Call the single runner function directly
exit_code = run_training(
log_level_str=log_level,
train_config_override=train_config_override,
persist_config_override=persist_config_override,
)

logger.info(f"Training finished with exit code {exit_code}.")
sys.exit(exit_code)
Expand Down
8 changes: 4 additions & 4 deletions alphatriangle/config/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# File: alphatriangle/config/README.md

# Configuration Module (`alphatriangle.config`)

## Purpose and Architecture

This module centralizes all configuration parameters for the AlphaTriangle project. It uses separate **Pydantic models** for different aspects of the application (environment, model, training, visualization, persistence) to promote modularity, clarity, and automatic validation.
This module centralizes all configuration parameters for the AlphaTriangle project. It uses separate **Pydantic models** for different aspects of the application (environment, model, training, persistence, MCTS) to promote modularity, clarity, and automatic validation.

- **Modularity:** Separating configurations makes it easier to manage parameters for different components.
- **Type Safety & Validation:** Using Pydantic models (`BaseModel`) provides strong type hinting, automatic parsing, and validation of configuration values based on defined types and constraints (e.g., `Field(gt=0)`).
Expand All @@ -15,10 +15,9 @@ This module centralizes all configuration parameters for the AlphaTriangle proje
## Exposed Interfaces

- **Pydantic Models:**
- [`EnvConfig`](env_config.py): Environment parameters (grid size, shapes).
- [`EnvConfig`](env_config.py): Environment parameters (grid size, shapes) - **Imported from `trianglengin`**.
- [`ModelConfig`](model_config.py): Neural network architecture parameters. **Defaults tuned for larger capacity.**
- [`TrainConfig`](train_config.py): Training loop hyperparameters (batch size, learning rate, workers, **PER settings**, etc.). **Defaults tuned for longer runs.**
- [`VisConfig`](vis_config.py): Visualization parameters (screen size, FPS, layout).
- [`PersistenceConfig`](persistence_config.py): Data saving/loading parameters (directories, filenames).
- [`MCTSConfig`](mcts_config.py): MCTS parameters (simulations, exploration constants, temperature).
- **Constants:**
Expand All @@ -31,6 +30,7 @@ This module centralizes all configuration parameters for the AlphaTriangle proje
This module primarily defines configurations and relies heavily on **Pydantic**.

- **`pydantic`**: The core library used for defining models and validation.
- **`trianglengin.config`**: Imports `EnvConfig`.
- **Standard Libraries:** `typing`, `time`, `os`, `logging`, `pathlib`.

---
Expand Down
10 changes: 6 additions & 4 deletions alphatriangle/config/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
from trianglengin.config import EnvConfig

from .app_config import APP_NAME
from .env_config import EnvConfig
from .mcts_config import MCTSConfig
from .model_config import ModelConfig
from .persistence_config import PersistenceConfig
from .train_config import TrainConfig
from .validation import print_config_info_and_validate
from .vis_config import VisConfig

# REMOVE DisplayConfig import

__all__ = [
"APP_NAME",
"EnvConfig",
"EnvConfig", # Now imported from trianglengin
"ModelConfig",
"PersistenceConfig",
"TrainConfig",
"VisConfig",
# "DisplayConfig", # REMOVED
"MCTSConfig",
"print_config_info_and_validate",
]
16 changes: 12 additions & 4 deletions alphatriangle/config/persistence_config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# File: alphatriangle/config/persistence_config.py
from pathlib import Path

from pydantic import BaseModel, Field, computed_field
Expand All @@ -12,8 +13,9 @@ class PersistenceConfig(BaseModel):

CHECKPOINT_SAVE_DIR_NAME: str = Field(default="checkpoints")
BUFFER_SAVE_DIR_NAME: str = Field(default="buffers")
GAME_STATE_SAVE_DIR_NAME: str = Field(default="game_states")
# REMOVED GAME_STATE_SAVE_DIR_NAME (handled externally now)
LOG_DIR_NAME: str = Field(default="logs")
TENSORBOARD_DIR_NAME: str = Field(default="tensorboard") # ADDED

LATEST_CHECKPOINT_FILENAME: str = Field(default="latest.pkl")
BEST_CHECKPOINT_FILENAME: str = Field(default="best.pkl")
Expand All @@ -22,11 +24,10 @@ class PersistenceConfig(BaseModel):

RUN_NAME: str = Field(default="default_run")

SAVE_GAME_STATES: bool = Field(default=False)
GAME_STATE_SAVE_FREQ_EPISODES: int = Field(default=5, ge=1)
# REMOVED SAVE_GAME_STATES and related freq

SAVE_BUFFER: bool = Field(default=True)
BUFFER_SAVE_FREQ_STEPS: int = Field(default=10, ge=1)
BUFFER_SAVE_FREQ_STEPS: int = Field(default=1000, ge=1) # Increased default freq

@computed_field # type: ignore[misc] # Decorator requires Pydantic v2
@property
Expand Down Expand Up @@ -54,6 +55,13 @@ def get_mlflow_abs_path(self) -> str:
abs_path = Path(self.ROOT_DATA_DIR).joinpath(self.MLFLOW_DIR_NAME).resolve()
return str(abs_path)

def get_tensorboard_log_dir(self, run_name: str | None = None) -> str:
"""Gets the directory for TensorBoard logs for a specific run."""
run_base = self.get_run_base_dir(run_name)
if not run_base or not hasattr(self, "TENSORBOARD_DIR_NAME"):
return "" # Fallback
return str(Path(run_base) / self.TENSORBOARD_DIR_NAME)


# Ensure model is rebuilt after changes
PersistenceConfig.model_rebuild(force=True)
1 change: 1 addition & 0 deletions alphatriangle/config/train_config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# File: alphatriangle/config/train_config.py
# File: alphatriangle/config/train_config.py
import logging
import time
from typing import Literal
Expand Down
Loading