Skip to content
This repository was archived by the owner on Aug 3, 2023. It is now read-only.
/ mcts Public archive

Package mcts provides parallel monte-carlo tree search for your Go applications.

License

Notifications You must be signed in to change notification settings

go-mcts/mcts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

217bbb4 · Apr 27, 2022

History

24 Commits
Apr 27, 2022
Oct 31, 2021
Oct 31, 2021
Oct 13, 2021
Oct 13, 2021
Oct 13, 2021
Oct 16, 2021
Oct 16, 2021
Oct 31, 2021
Oct 28, 2021
Apr 24, 2022
Apr 24, 2022
Oct 16, 2021
Oct 31, 2021
Oct 16, 2021
Oct 31, 2021
Oct 31, 2021

Repository files navigation

mcts

GitHub Workflow Status codecov Go Report Card PkgGoDev Release

Package mcts provides parallel monte-carlo tree search for your Go applications.

Installation

Go latest is recommended.

go get -u github.com/go-mcts/mcts

Getting started

See examples directory.

Implements mcts.Move and mcts.State:

// examples/nim/nim.go
type Move int

type State struct {
	playerToMove int
	chips        int
}

func (s *State) PlayerToMove() int {
	return s.playerToMove
}

func (s *State) HasMoves() bool {
	s.checkInvariant()
	return s.chips > 0
}

func (s *State) GetMoves() []mcts.Move {
	s.checkInvariant()

	var moves []mcts.Move
	for i := 1; i <= min(3, s.chips); i++ {
		moves = append(moves, i)
	}
	return moves
}

func (s *State) DoMove(move mcts.Move) {
	m := move.(int)
	if m < 1 || m > 3 {
		panic("illegal move")
	}
	s.checkInvariant()

	s.chips -= m
	s.playerToMove = 3 - s.playerToMove

	s.checkInvariant()
}

func (s *State) DoRandomMove(rd *rand.Rand) {
	if s.chips <= 0 {
		panic("invalid chips")
	}
	s.checkInvariant()

	max := min(3, s.chips)
	s.DoMove(rd.Intn(max) + 1)

	s.checkInvariant()
}

func (s *State) GetResult(currentPlayerToMove int) float64 {
	if s.chips != 0 {
		panic("game not over")
	}
	s.checkInvariant()

	if s.playerToMove == currentPlayerToMove {
		return 1.0
	}
	return 0.0
}

func (s *State) Clone() mcts.State {
	return &State{
		playerToMove: s.playerToMove,
		chips:        s.chips,
	}
}

Run mcts.ComputeMove:

state := &State{
	playerToMove: 1,
	chips:        chips,
}
move := mcts.ComputeMove(state, mcts.MaxIterations(100000), mcts.Verbose(true))

By default, runtime.NumCPU() goroutines are started for compute:

2021-10-16T16:13:33+08:00       DEBUG   100000 games played (493618.37 / second).
2021-10-16T16:13:33+08:00       DEBUG   100000 games played (487598.00 / second).
2021-10-16T16:13:33+08:00       DEBUG   100000 games played (474579.62 / second).
2021-10-16T16:13:33+08:00       DEBUG   100000 games played (470514.17 / second).
2021-10-16T16:13:33+08:00       DEBUG   Move: 2 (16% visits) (48% wins)
2021-10-16T16:13:33+08:00       DEBUG   Move: 1 (72% visits) (67% wins)
2021-10-16T16:13:33+08:00       DEBUG   Move: 3 (13% visits) (48% wins)
2021-10-16T16:13:33+08:00       DEBUG   Best: 1 (72% visits) (67% wins)
2021-10-16T16:13:33+08:00       DEBUG   400000 games played in 0.21 s. (1881366.23 / second, 4 parallel jobs).

License

This project is under the MIT License. See the LICENSE file for the full license text.