Esempio n. 1
0
        public ParticleSwarms(string PgnFilename, int ParticleSwarms, int ParticlesPerSwarm, int WinPercentScale, Delegates.DisplayStats DisplayStats, Delegates.WriteMessageLine WriteMessageLine)
        {
            _displayStats     = DisplayStats;
            _writeMessageLine = WriteMessageLine;
            // Load games.
            WriteMessageLine("Loading games.");
            var stopwatch = new Stopwatch();

            stopwatch.Start();
            var board    = new Board(WriteMessageLine);
            var pgnGames = new PgnGames();

            pgnGames.Load(board, PgnFilename);
            stopwatch.Stop();
            // Count positions.
            long positions = 0;

            for (var gameIndex = 0; gameIndex < pgnGames.Count; gameIndex++)
            {
                var pgnGame = pgnGames[gameIndex];
                positions += pgnGame.Moves.Count;
            }
            var positionsPerSecond = (int)(positions / stopwatch.Elapsed.TotalSeconds);

            WriteMessageLine($"Loaded {pgnGames.Count:n0} games with {positions:n0} positions in {stopwatch.Elapsed.TotalSeconds:0.000} seconds ({positionsPerSecond:n0} positions per second).");
            stopwatch.Restart();
            WriteMessageLine("Creating data structures.");
            // Create parameters and particle swarms.
            var parameters = CreateParameters();

            for (var index = 0; index < ParticleSwarms; index++)
            {
                var particleSwarm = new ParticleSwarm(pgnGames, parameters, ParticlesPerSwarm, WinPercentScale);
                Add(particleSwarm);
                // Set parameter values of all particles in swarm to known best.
                foreach (var particle in particleSwarm.Particles)
                {
                    SetDefaultParameters(particle.Parameters);
                }
            }
            var stats       = new Stats();
            var cache       = new Cache(1, stats, board.ValidateMove);
            var killerMoves = new KillerMoves(Search.MaxHorizon);
            var moveHistory = new MoveHistory();
            var evaluation  = new Evaluation(stats, board.IsRepeatPosition, () => false, WriteMessageLine);
            var search      = new Search(stats, cache, killerMoves, moveHistory, evaluation, () => false, DisplayStats, WriteMessageLine);
            var firstParticleInFirstSwarm = this[0].Particles[0];

            firstParticleInFirstSwarm.CalculateEvaluationError(board, search, WinPercentScale);
            _originalEvaluationError = firstParticleInFirstSwarm.EvaluationError;
            stopwatch.Stop();
            WriteMessageLine($"Created data structures in {stopwatch.Elapsed.TotalSeconds:0.000} seconds.");
        }
Esempio n. 2
0
 public void Load(Board board, string filename, Delegates.WriteMessageLine writeMessageLine)
 {
     using (var pgnReader = File.OpenText(filename))
     {
         var     gameNumber = 1;
         PgnGame pgnGame;
         do
         {
             pgnGame = GetNextGame(board, pgnReader, gameNumber);
             if ((pgnGame != null) && (pgnGame.Result != GameResult.Unknown))
             {
                 Add(pgnGame);
             }
             gameNumber++;
             if ((gameNumber % 1000) == 0)
             {
                 writeMessageLine($"Loaded {gameNumber:n0} games.");
             }
         } while (pgnGame != null);
     }
     GC.Collect();
 }
Esempio n. 3
0
    public void FindMagicMultipliers(ColorlessPiece colorlessPiece, Delegates.WriteMessageLine writeMessageLine = null)
    {
        Direction[] directions;
        ulong[]     unoccupiedMoveMasks;
        ulong[]     relevantOccupancyMasks;
        ulong[]     magicMultipliers;
        int[]       shifts;
        ulong[][]   moveMasks;
        // ReSharper disable SwitchStatementHandlesSomeKnownEnumValuesWithDefault
        switch (colorlessPiece)
        {
        case ColorlessPiece.Bishop:
            directions             = new[] { Direction.NorthEast, Direction.SouthEast, Direction.SouthWest, Direction.NorthWest };
            unoccupiedMoveMasks    = Board.BishopMoveMasks;
            relevantOccupancyMasks = _bishopRelevantOccupancyMasks;
            magicMultipliers       = _bishopMagicMultipliers;
            shifts    = _bishopShifts;
            moveMasks = _bishopMoveMasks;
            break;

        case ColorlessPiece.Rook:
            directions             = new[] { Direction.North, Direction.East, Direction.South, Direction.West };
            unoccupiedMoveMasks    = Board.RookMoveMasks;
            relevantOccupancyMasks = _rookRelevantOccupancyMasks;
            magicMultipliers       = _rookMagicMultipliers;
            shifts    = _rookShifts;
            moveMasks = _rookMoveMasks;
            break;

        default:
            throw new ArgumentException($"{colorlessPiece} piece not supported.");
        }
        // ReSharper restore SwitchStatementHandlesSomeKnownEnumValuesWithDefault
        // Generate moves mask on each square.
        var occupancyToMovesMask = new Dictionary <ulong, ulong>();
        var uniqueMovesMasks     = new HashSet <ulong>();

        for (var square = Square.A8; square < Square.Illegal; square++)
        {
            occupancyToMovesMask.Clear();
            uniqueMovesMasks.Clear();
            var moveDestinations         = unoccupiedMoveMasks[(int)square];
            var relevantMoveDestinations = moveDestinations & relevantOccupancyMasks[(int)square];
            var uniqueOccupancies        = (int)Math.Pow(2, Bitwise.CountSetBits(relevantMoveDestinations));
            occupancyToMovesMask.EnsureCapacity(uniqueOccupancies);
            // Generate moves mask for every permutation of occupancy of the relevant destination squares.
            var occupancyPermutations = Bitwise.GetAllPermutations(relevantMoveDestinations);
            for (var occupancyIndex = 0; occupancyIndex < occupancyPermutations.Count; occupancyIndex++)
            {
                var occupancy = occupancyPermutations[occupancyIndex];
                var movesMask = Board.CreateMoveDestinationsMask(square, occupancy, directions);
                occupancyToMovesMask.Add(occupancy, movesMask);
                if (!uniqueMovesMasks.Contains(movesMask))
                {
                    uniqueMovesMasks.Add(movesMask);
                }
            }
            Debug.Assert(occupancyToMovesMask.Count == uniqueOccupancies);
            // Determine bit shift that produces number >= unique occupancies.
            // A stricter condition is number >= unique moves but this requires more computing time to find magic multipliers.
            var shift = 64 - (int)Math.Ceiling(Math.Log(uniqueOccupancies, 2d));
            shifts[(int)square] = shift;
            var magicMultiplier      = magicMultipliers[(int)square];
            var knownMagicMultiplier = magicMultiplier == 0 ? null : (ulong?)magicMultiplier;
            (magicMultipliers[(int)square], moveMasks[(int)square]) = FindMagicMultiplier(occupancyToMovesMask, shift, knownMagicMultiplier);
            writeMessageLine?.Invoke($"{Board.SquareLocations[(int)square],6}  {PieceHelper.GetName(colorlessPiece),6}  {shift,5}  {occupancyToMovesMask.Count,18}  {uniqueMovesMasks.Count,12}  {magicMultipliers[(int)square],16:X16}");
        }
    }
Esempio n. 4
0
        public void FindMagicMultipliers(int Piece, Delegates.WriteMessageLine WriteMessageLine = null)
        {
            Direction[] directions;
            ulong[]     unoccupiedMoveMasks;
            ulong[]     relevantOccupancyMasks;
            ulong[]     magicMultipliers;
            int[]       shifts;
            ulong[][]   moveMasks;
            switch (Piece)
            {
            case Engine.Piece.WhiteBishop:
            case Engine.Piece.BlackBishop:
                directions             = new[] { Direction.NorthEast, Direction.SouthEast, Direction.SouthWest, Direction.NorthWest };
                unoccupiedMoveMasks    = Board.BishopMoveMasks;
                relevantOccupancyMasks = _bishopRelevantOccupancyMasks;
                magicMultipliers       = _bishopMagicMultipliers;
                shifts    = _bishopShifts;
                moveMasks = _bishopMoveMasks;
                break;

            case Engine.Piece.WhiteRook:
            case Engine.Piece.BlackRook:
                directions             = new[] { Direction.North, Direction.East, Direction.South, Direction.West };
                unoccupiedMoveMasks    = Board.RookMoveMasks;
                relevantOccupancyMasks = _rookRelevantOccupancyMasks;
                magicMultipliers       = _rookMagicMultipliers;
                shifts    = _rookShifts;
                moveMasks = _rookMoveMasks;
                break;

            default:
                throw new ArgumentException($"{Piece} piece not supported.");
            }
            // Generate moves mask on each square.
            var occupancyToMovesMask = new Dictionary <ulong, ulong>();
            var uniqueMovesMasks     = new HashSet <ulong>();

            for (var square = 0; square < 64; square++)
            {
                occupancyToMovesMask.Clear();
                uniqueMovesMasks.Clear();
                var moveDestinations         = unoccupiedMoveMasks[square];
                var relevantMoveDestinations = moveDestinations & relevantOccupancyMasks[square];
                var uniqueOccupancies        = (int)Math.Pow(2, Bitwise.CountSetBits(relevantMoveDestinations));
                occupancyToMovesMask.EnsureCapacity(uniqueOccupancies);
                // Generate moves mask for every permutation of relevant occupancy bits.
                using (var occupancyPermutations = Bitwise.GetAllPermutations(relevantMoveDestinations).GetEnumerator())
                {
                    while (occupancyPermutations.MoveNext())
                    {
                        var occupancy = occupancyPermutations.Current;
                        if (!occupancyToMovesMask.ContainsKey(occupancy))
                        {
                            // Have not yet generated moves for this occupancy mask.
                            var movesMask = Board.CreateMoveDestinationsMask(square, occupancy, directions);
                            occupancyToMovesMask.Add(occupancy, movesMask);
                            if (!uniqueMovesMasks.Contains(movesMask))
                            {
                                uniqueMovesMasks.Add(movesMask);
                            }
                        }
                    }
                }
                // Validate enumerator found all permutations of relevant occupancy bits.
                Debug.Assert(occupancyToMovesMask.Count == uniqueOccupancies);
                // Determine bit shift that produces number >= unique occupancies.
                // A stricter condition is number >= unique moves but this requires more computing time to find magic multipliers.
                var shift = 64 - (int)Math.Ceiling(Math.Log(uniqueOccupancies, 2d));
                shifts[square] = shift;
                var magicMultiplier = magicMultipliers[square];
                if (magicMultiplier == 0)
                {
                    (magicMultipliers[square], moveMasks[square]) = FindMagicMultiplier(occupancyToMovesMask, shift, null);
                }
                else
                {
                    (magicMultipliers[square], moveMasks[square]) = FindMagicMultiplier(occupancyToMovesMask, shift, magicMultiplier);
                }
                WriteMessageLine?.Invoke($"{Board.SquareLocations[square],6}  {Engine.Piece.GetName(Piece),6}  {shift,5}  {occupancyToMovesMask.Count,18}  {uniqueMovesMasks.Count,12}  {magicMultipliers[square],16:X16}");
            }
        }