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.1-cp312-cp312-win_amd64.whl (182.1 kB view details)

Uploaded CPython 3.12Windows x86-64

trimcts-1.2.1-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.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (217.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

trimcts-1.2.1-cp312-cp312-macosx_14_0_universal2.whl (89.7 kB view details)

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

trimcts-1.2.1-cp311-cp311-win_amd64.whl (181.0 kB view details)

Uploaded CPython 3.11Windows x86-64

trimcts-1.2.1-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.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (217.7 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

trimcts-1.2.1-cp311-cp311-macosx_14_0_universal2.whl (89.9 kB view details)

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

trimcts-1.2.1-cp310-cp310-win_amd64.whl (178.3 kB view details)

Uploaded CPython 3.10Windows x86-64

trimcts-1.2.1-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.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (217.7 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

trimcts-1.2.1-cp310-cp310-macosx_14_0_universal2.whl (88.5 kB view details)

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

File details

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

File metadata

  • Download URL: trimcts-1.2.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 182.1 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.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 07f62c9b9739c26af94f3f139a00e23c9a1048bc433e7b392fde64dd047922c6
MD5 8b74dbd24ca1fffbf16fd9b9c2d6f50f
BLAKE2b-256 e2bba343f20a782abec9765937baf31bd902ab5d94799d8a69b4926a340b52d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 fbf90a38d1817342946f5fe5bc6f8245128956690d83f67b2b175fa11a3f6995
MD5 89e76ed271ac3563bffcf0943954a989
BLAKE2b-256 a3cfe590dad17d75efe6f0b2a48270c132c02bfe8bd9e45fea87bca650b0cd45

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6e12633b4cb7d6878a45fb692b76336645a09e3e423442e07e2111251a9088ad
MD5 d3fb0d39785bc3c927c4287e7f69e96c
BLAKE2b-256 986a346a2f7daa6ce6a0e581c9792d13923ac8f95f9cad3ea4e2551f4121646e

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp312-cp312-macosx_14_0_universal2.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp312-cp312-macosx_14_0_universal2.whl
Algorithm Hash digest
SHA256 a42f729e3a743b3a09dee962568adab9049c5235b13a5b715e258fdfbd6c0ad4
MD5 0db22b35acf5e67d6495719ae1ae326a
BLAKE2b-256 c3c4ba08873cb558088adc185f286bb7bb8aef7e288f28e1f75cee2caffaf5cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: trimcts-1.2.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 181.0 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.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 34d50c8d7ad7e24b41edddfcb5aa96f8d7ca3d891997c370f95a83e5d4531af1
MD5 fa57862a355155c062124f352d40dd47
BLAKE2b-256 74ac25dabaf35f28c26c9e083606c1f9d2aad022a087e8451799da35ff2c9a49

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 08c4d5c875107b0b586c17a95ca58930b408f79299a8014df324fc3723d83d4b
MD5 082337b5437671ac3a31320404f4da94
BLAKE2b-256 6c224f9ee200cadbf76b9d0581d32961203d43f243099735423e6fd64b2daea2

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a8b7d162b74f03c5fdd74590a2d3288e092112e386674094a303c9d0875ac404
MD5 8670c8db0e4fc5f2aca424ce6372f937
BLAKE2b-256 d6aa699ea081a7648ca614a3302e69e21ffec6be4af9efc70cbcaf7f2abb69f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp311-cp311-macosx_14_0_universal2.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp311-cp311-macosx_14_0_universal2.whl
Algorithm Hash digest
SHA256 8387da08a06205cae1b23311753a54d4b7445b4f980196cdc5cf6bdc4bdc4e11
MD5 da49300f642316515924d9cd4c9f1672
BLAKE2b-256 219f29a1713e7e5436c12cd36e86f28cf3c0ed0d729b2b2163e156b46b1db618

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: trimcts-1.2.1-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 178.3 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.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 0bd92bebd93f1e0d86f1567f426c867a934ef6ffdf5a11466e63271ca9ced831
MD5 63c7d5a88dbf4128ef993a2a019f56a3
BLAKE2b-256 29e03bec1f0666f41c8377b25e28731e96bc96bab4bb55fc46d103ff1c19b6a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 3147b5f45371ff5d8ee705f8fe787460cdce47fe100a4a2941a536b92a4e20f5
MD5 eb705dfe4d7f175cffc5baf7f47c0e22
BLAKE2b-256 653c275ba94d2b8d90ae69d80aa24b34ccc92c19b0a39422c6022682b725cbed

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1706d916d4e0cf585e03d16d6fc9f4b34a0e4d19afa4163927fa906be9fab256
MD5 2118c0c11d6a8f9a3ed7ca0adafcf313
BLAKE2b-256 4b137ef664c39fe4a584e7d32f3d52420a4bef6b810ac5eaa191f2d4980cbfd1

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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.1-cp310-cp310-macosx_14_0_universal2.whl.

File metadata

File hashes

Hashes for trimcts-1.2.1-cp310-cp310-macosx_14_0_universal2.whl
Algorithm Hash digest
SHA256 a24a145b1cbb85d49791715b379698a33682aabeb146e7333c8249146b112f8f
MD5 6a34ec6f99fad766f4fcb0f9966c5539
BLAKE2b-256 45bcaf938a47cb3a9fb426d6b88d7c2038f0601c2fc7cf359b9a2866c0100d8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for trimcts-1.2.1-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