Skip to main content

Highโ€‘performance C++ MCTS (AlphaZero & MuZero) with Tree Reuse for triangular games

Project description

CI PyPI Coverage Status License: MIT Python Version

TriMCTS

TriMCTS Logo

TriMCTS is an installable Python package providing C++ bindings for Monte Carlo Tree Search, supporting both AlphaZero and MuZero paradigms, optimized for triangular grid games like the one in trianglengin.

๐Ÿ”‘ Key Features

  • High-performance C++ core implementation.
  • Seamless Python integration via Pybind11.
  • Supports AlphaZero-style evaluation (policy/value from state).
  • Batched Network Evaluations: Efficiently calls the Python network's evaluate_batch method during search for improved performance, especially with GPUs.
  • MCTS Tree Reuse: Significantly speeds up sequential MCTS calls (e.g., during self-play) by reusing the relevant subtree from the previous search step. The C++ core manages the tree lifetime via opaque handles (py::capsule) passed between Python calls.
  • (Planned) Supports MuZero-style evaluation (initial inference + recurrent inference).
  • Configurable search parameters (simulation count, PUCT, discount factor, Dirichlet noise, batch size).
  • Designed for use with external Python game state objects and network evaluators.
  • Type-hinted Python API (py.typed compliant).

๐Ÿš€ Installation

# From PyPI (once published)
pip install trimcts

# For development (from cloned repo root)
# Ensure you clean previous builds if you encounter issues:
# rm -rf build/ src/trimcts.egg-info/ dist/ src/trimcts/trimcts_cpp.*.so
pip install -e .[dev]

๐Ÿ’ก Usage Example (AlphaZero Style with Tree Reuse)

import time
import numpy as np
import torch # Added import
# Use the actual GameState if trianglengin is installed
try:
    from trianglengin import GameState, EnvConfig
    HAS_TRIANGLENGIN = True
except ImportError:
    # Define minimal mocks if trianglengin is not available
    class GameState: # type: ignore
        def __init__(self, *args, **kwargs): self.current_step = 0
        def is_over(self): return False
        def copy(self): return self
        def step(self, action): return 0.0, False
        def get_outcome(self): return 0.0
        def valid_actions(self): return [0, 1]
    class EnvConfig: pass # type: ignore
    HAS_TRIANGLENGIN = False

# Assuming alphatriangle is installed and provides these:
# from alphatriangle.nn import NeuralNetwork # Example network wrapper
# from alphatriangle.config import ModelConfig, TrainConfig

from trimcts import run_mcts, SearchConfiguration, AlphaZeroNetworkInterface

# --- Mock Neural Network (same as before) ---
class MockNeuralNetwork:
    def __init__(self, *args, **kwargs):
        self.model = torch.nn.Module() # Dummy model
        print("MockNeuralNetwork initialized.")

    def evaluate_state(self, state: GameState) -> tuple[dict[int, float], float]:
        valid_actions = state.valid_actions()
        if not valid_actions: return {}, 0.0
        policy = {action: 1.0 / len(valid_actions) for action in valid_actions}
        value = 0.5
        return policy, value

    def evaluate_batch(self, states: list[GameState]) -> list[tuple[dict[int, float], float]]:
        print(f"  Mock evaluate_batch called with {len(states)} states.")
        return [self.evaluate_state(s) for s in states]

    def load_weights(self, path): print(f"Mock: Pretending to load weights from {path}")
    def to(self, device): print(f"Mock: Pretending to move model to {device}"); return self
# --- End Mock Neural Network ---

# --- AlphaZero Wrapper (same as before) ---
class MyAlphaZeroWrapper(AlphaZeroNetworkInterface):
    def __init__(self, model_path: str | None = None):
        self.network = MockNeuralNetwork()
        if model_path: self.network.load_weights(model_path)
        self.network.model.eval()
        print("MyAlphaZeroWrapper initialized.")

    def evaluate_state(self, state: GameState) -> tuple[dict[int, float], float]:
        print(f"Python: Evaluating SINGLE state step {state.current_step}")
        policy_map, value = self.network.evaluate_state(state)
        print(f"Python: Single evaluation result - Policy keys: {len(policy_map)}, Value: {value:.4f}")
        return policy_map, value

    def evaluate_batch(self, states: list[GameState]) -> list[tuple[dict[int, float], float]]:
        print(f"Python: Evaluating BATCH of {len(states)} states.")
        results = self.network.evaluate_batch(states)
        print(f"Python: Batch evaluation returned {len(results)} results.")
        return results

# --- Simulation Loop Example ---
env_config = EnvConfig()
if HAS_TRIANGLENGIN:
    env_config.ROWS = 3
    env_config.COLS = 3
    env_config.NUM_SHAPE_SLOTS = 1
    env_config.PLAYABLE_RANGE_PER_ROW = [(0,3), (0,3), (0,3)]

game_state = GameState(config=env_config, initial_seed=42)
network_wrapper = MyAlphaZeroWrapper()

mcts_config = SearchConfiguration()
mcts_config.max_simulations = 50
mcts_config.mcts_batch_size = 8

# --- Tree Reuse Variables ---
mcts_tree_handle = None # Start with no tree
last_action = -1        # No previous action initially

print("--- Running Self-Play Loop with Tree Reuse ---")
max_episode_steps = 10
for step in range(max_episode_steps):
    if game_state.is_over():
        print(f"\nGame over at step {step}. Final Score: {game_state.game_score()}")
        break

    print(f"\n--- Step {step} ---")
    print(f"Current State Step: {game_state.current_step}")
    print(f"Passing tree handle: {'Yes' if mcts_tree_handle else 'No'}")
    print(f"Passing last action: {last_action}")

    # Run MCTS, passing the handle and last action
    # It returns visit counts AND the new handle
    start_time = time.time()
    visit_counts, mcts_tree_handle = run_mcts(
        root_state=game_state,
        network_interface=network_wrapper,
        config=mcts_config,
        previous_tree_handle=mcts_tree_handle, # Pass handle from previous step
        last_action=last_action               # Pass action that led to current state
    )
    end_time = time.time()
    print(f"MCTS Result (Visit Counts) after {end_time - start_time:.3f} seconds:")
    print(visit_counts)
    print(f"Received new tree handle: {'Present' if mcts_tree_handle else 'None'}")

    # Select best action based on visits
    if not visit_counts:
        print("MCTS returned no visits. Ending episode.")
        break
    best_action = max(visit_counts, key=visit_counts.get)
    print(f"Selected Action: {best_action}")

    # Store the selected action for the *next* MCTS call
    last_action = best_action

    # Apply the action to the game state
    reward, done = game_state.step(best_action)
    print(f"Step Reward: {reward:.3f}, Done: {done}")

else:
     print(f"\nEpisode finished after {max_episode_steps} steps.")

# The mcts_tree_handle (a py::capsule) will be automatically garbage collected
# by Python when it goes out of scope, triggering the C++ destructor.
print("\n--- End of Simulation ---")

(MuZero example will be added later)

๐Ÿ“‚ Project Structure

trimcts/
โ”œโ”€โ”€ .github/workflows/      # CI configuration (e.g., ci_cd.yml)
โ”œโ”€โ”€ src/trimcts/            # Python package source ([src/trimcts/README.md](src/trimcts/README.md))
โ”‚   โ”œโ”€โ”€ cpp/                # C++ source code ([src/trimcts/cpp/README.md](src/trimcts/cpp/README.md))
โ”‚   โ”‚   โ”œโ”€โ”€ CMakeLists.txt  # CMake build script for C++ part
โ”‚   โ”‚   โ”œโ”€โ”€ bindings.cpp    # Pybind11 bindings
โ”‚   โ”‚   โ”œโ”€โ”€ config.h        # C++ configuration struct
โ”‚   โ”‚   โ”œโ”€โ”€ mcts.cpp        # C++ MCTS implementation (Node, simulation loop)
โ”‚   โ”‚   โ”œโ”€โ”€ mcts.h          # C++ MCTS header
โ”‚   โ”‚   โ”œโ”€โ”€ mcts_manager.cpp # C++ MCTS Tree Manager implementation
โ”‚   โ”‚   โ”œโ”€โ”€ mcts_manager.h  # C++ MCTS Tree Manager header (handles lifetime)
โ”‚   โ”‚   โ”œโ”€โ”€ python_interface.h # C++ helpers for Python interaction
โ”‚   โ”‚   โ””โ”€โ”€ structs.h       # Common C++ structs (NetworkOutput, etc.)
โ”‚   โ”œโ”€โ”€ __init__.py         # Exposes public API (run_mcts, configs, etc.)
โ”‚   โ”œโ”€โ”€ config.py           # Python SearchConfiguration (Pydantic)
โ”‚   โ”œโ”€โ”€ mcts_wrapper.py     # Python network interface definition & run_mcts wrapper
โ”‚   โ””โ”€โ”€ py.typed            # Marker file for type checkers (PEP 561)
โ”œโ”€โ”€ tests/                  # Python tests ([tests/README.md](tests/README.md))
โ”‚   โ”œโ”€โ”€ conftest.py
โ”‚   โ””โ”€โ”€ test_alpha_wrapper.py # Tests for AlphaZero functionality
โ”œโ”€โ”€ .gitignore
โ”œโ”€โ”€ LICENSE
โ”œโ”€โ”€ MANIFEST.in             # Specifies files for source distribution
โ”œโ”€โ”€ pyproject.toml          # Build system & package configuration
โ”œโ”€โ”€ README.md               # This file
โ””โ”€โ”€ setup.py                # Setup script for C++ extension building

๐Ÿ› ๏ธ Building from Source

  1. Clone the repository: git clone https://github.com/lguibr/trimcts.git
  2. Navigate to the directory: cd trimcts
  3. Recommended: Create and activate a virtual environment:
    python -m venv .venv
    source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
    
  4. Install build dependencies: pip install pybind11>=2.10 cmake wheel
  5. Clean previous builds (important if switching Python versions or encountering issues):
    rm -rf build/ src/trimcts.egg-info/ dist/ src/trimcts/trimcts_cpp.*.so
    
  6. Install the package in editable mode: pip install -e .

๐Ÿงช Running Tests

# Make sure you have installed dev dependencies
pip install -e .[dev]
pytest

๐Ÿค Contributing

Contributions are welcome! Please follow standard fork-and-pull-request workflow. Ensure tests pass and code adheres to formatting/linting standards (Ruff, MyPy).

๐Ÿ“œ License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

trimcts-1.2.0-cp312-cp312-win_amd64.whl (181.2 kB view details)

Uploaded CPython 3.12Windows x86-64

trimcts-1.2.0-cp312-cp312-musllinux_1_2_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

trimcts-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (216.0 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

trimcts-1.2.0-cp312-cp312-macosx_14_0_universal2.whl (89.2 kB view details)

Uploaded CPython 3.12macOS 14.0+ universal2 (ARM64, x86-64)

trimcts-1.2.0-cp311-cp311-win_amd64.whl (180.2 kB view details)

Uploaded CPython 3.11Windows x86-64

trimcts-1.2.0-cp311-cp311-musllinux_1_2_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

trimcts-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (216.0 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

trimcts-1.2.0-cp311-cp311-macosx_14_0_universal2.whl (89.5 kB view details)

Uploaded CPython 3.11macOS 14.0+ universal2 (ARM64, x86-64)

trimcts-1.2.0-cp310-cp310-win_amd64.whl (177.5 kB view details)

Uploaded CPython 3.10Windows x86-64

trimcts-1.2.0-cp310-cp310-musllinux_1_2_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ x86-64

trimcts-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (216.0 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

trimcts-1.2.0-cp310-cp310-macosx_14_0_universal2.whl (88.2 kB view details)

Uploaded CPython 3.10macOS 14.0+ universal2 (ARM64, x86-64)

File details

Details for the file trimcts-1.2.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: trimcts-1.2.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 181.2 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for trimcts-1.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b54c0e406070d7c107b8614367a5622794b03fe47118437d90d2431fbf6e112c
MD5 d6bf96c0120c6b0124cc74f39d9738f9
BLAKE2b-256 4feb07b02b66c4c834648ebf21a9001a6c6f7b14ba4ba2f90cabd1c502cdd3cd

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp312-cp312-win_amd64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 92570d0f58f90793bc46a324615747b2604035c1115d040a71d79b60d86d6ca7
MD5 c4a3c5e3a3d5e3e6f06ecbbe718d063a
BLAKE2b-256 568c6b4d563129b1a9351103dd4f431effe62f9bbc7099b2775797b91286bc7e

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp312-cp312-musllinux_1_2_x86_64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8e7473e32ad444069790e2e2350c1ad716dc7a471c87ab0808d8ac5caa6e20f4
MD5 cbfc38f43fe7fd3bd0825c257fc146f2
BLAKE2b-256 0ec64791281c996f9cc9a7befd59b5980bdd39785f3226e8fa52f659deff9cc3

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp312-cp312-macosx_14_0_universal2.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp312-cp312-macosx_14_0_universal2.whl
Algorithm Hash digest
SHA256 47b1c31a8cdfe2fa2176dfbc1a6a28d55ffa83f45c9649b2aaa58a3bb45f4da1
MD5 c71ef39681fdbbd109690f6a690eff69
BLAKE2b-256 0ac060336c3f0aaf5c001f1ce34b38e4c3f3b759d7c4bcfbf0deda3a1f0e5e53

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp312-cp312-macosx_14_0_universal2.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: trimcts-1.2.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 180.2 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for trimcts-1.2.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 c6a21937f24d1408bfa6e3a6cfebaca76c8ad6604f6920bc7204b8b7b329367e
MD5 90aec004e05d152deb29fcfe3f3f4991
BLAKE2b-256 4fba2d121083ea88fb22af0f2fc1aef611c984d9dc2199f179deb1d822164a66

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp311-cp311-win_amd64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e9895e9660654eab887a541fd837704dd27aabd23da44c18c5d62b249d1a5540
MD5 5d44986f358963dfc9eb8e6604cb9848
BLAKE2b-256 0315c677fcc1c4fae81cf32f3f039e53dca5ddee768b8350a514dacfb90383a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp311-cp311-musllinux_1_2_x86_64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 46ed3f74a27cd430a6850fb5a9ee49807c0772caafb4e128df65fc1d30ecb3ff
MD5 1b7f137aa097176e641914f51d5f4dbf
BLAKE2b-256 f0c8b018878cdb191008e5f8827f4a21fc9b355ee360702a3d2d15772bd9a3b5

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp311-cp311-macosx_14_0_universal2.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp311-cp311-macosx_14_0_universal2.whl
Algorithm Hash digest
SHA256 cba101b992a3b0a64a0b102eb5ac7c9c496520a15812641f3b4ae6f291e4c4fe
MD5 19be13a94c31c8cebf50ad1f7e7309e7
BLAKE2b-256 94f3f1000589967bd77f3af594c26bfedaf043eec234f43cc63d16fae726ea22

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp311-cp311-macosx_14_0_universal2.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: trimcts-1.2.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 177.5 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for trimcts-1.2.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 c842b190119cbbef55fb102730e457e348fe298f9ea56c3a73c67a1afba3dc98
MD5 fa4f09ea39f3f79b0e6b1b3b7a03deaa
BLAKE2b-256 35416215aab8b9a8b41691847952a5f879d56152b42e1000153b8e016548d8a7

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp310-cp310-win_amd64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8cfa21e3f8a014c0072ceaf989acfc429d02edfd5780d0c3b99b24ee7d5b7adc
MD5 a0dc8bab5068190f4918422bd24df725
BLAKE2b-256 fc2bc0ea229434324a4ea37d796df1b06c12104c28cbe6ffa7d162ae752fe8e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp310-cp310-musllinux_1_2_x86_64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3f1dedb5381c71676636edc6b5fa5f08405b168bc41240166a98284752ea5fce
MD5 6334c396b21777960668ab06d5c844af
BLAKE2b-256 0d1125cf351f6656b1d830fce4ca4d399dde5d19f1e9923a321e95cf7249c083

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file trimcts-1.2.0-cp310-cp310-macosx_14_0_universal2.whl.

File metadata

File hashes

Hashes for trimcts-1.2.0-cp310-cp310-macosx_14_0_universal2.whl
Algorithm Hash digest
SHA256 211cb721acd294016dfa7de83c10a5d7772e1fb168388f47bfb31ae23908c6ff
MD5 aeb5a178959bd015b16d159506f35603
BLAKE2b-256 6cdaa61d253d3f45e630e06420d6bb564b6597425a1143ec684243a23a7fd989

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.0-cp310-cp310-macosx_14_0_universal2.whl:

Publisher: ci_cd.yml on lguibr/trimcts

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page