<commit_before>﻿namespace Foat.Puzzles.RubiksCube.Solution
{
    using Foat.Hashing;
    using Foat.Puzzles.RubiksCube;
    using Foat.Puzzles.Solutions;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    
    /// <summary>
    /// This class generates a PatternSet that contains every cube that can possibly be reached by twisting a cube defined by an initial Pattern.
    /// </summary>
    public static class PatternSetGenerator
    {
        #region Static Methods

        /// <summary>
        /// Generates the entire PatternSet using the given Pattern as a starting point.
        /// </summary>
        /// <param name="pattern">The initial pattern in the set.</param>
        /// <param name="numberOfThreads">The number of threads to use while generating the pattern set.</param>
        public static PatternSet Generate(Pattern pattern, int numberOfThreads)
        {
            RubiksCubeDepthDatabase patternSetDictionary = GeneratePatternSetDictionary(pattern, numberOfThreads);
            MinimalPerfectHash<FnvHash> mph = GetMinimalPerfectHashForPatternSet(patternSetDictionary.Keys);

            return new PatternSet(patternSetDictionary, mph, pattern);
        }

        /// <summary>
        /// Generates a minimal perfect hash for every cube in the PatternSet. This is a hash that can map any cube in the set
        /// to an index in the range of 0 ... N - 1 where N is the number of cubes in the entire set. Useful for constant time
        /// lookups of any cube in the set.
        /// </summary>
        /// <param name="database"></param>
        /// <returns></returns>
        private static MinimalPerfectHash<FnvHash> GetMinimalPerfectHashForPatternSet(IEnumerable<RubiksCube> cubes)
        {
            MinimalPerfectHash<FnvHash> mph = new MinimalPerfectHash<FnvHash>();
            mph.Generate(cubes.Select(cube=>cube.GetBytes()));
                       
            return mph;
        }

        /// <summary>
        /// Generates a dictionary that maps RubiksCubes to the minimum number of moves it will take to solve that cube.
        /// </summary>
        /// <param name="pattern">The initial pattern that will be used to generate every other RubiksCube in the PatternSet.</param>
        /// <param name="numberOfThreads">The number of threads to use while generating the pattern set dictionary.</param>
        /// <returns></returns>
        private static RubiksCubeDepthDatabase GeneratePatternSetDictionary(Pattern pattern, int numberOfThreads)
        {
            RubiksCubeDepthDatabase patternDatabase = new RubiksCubeDepthDatabase(pattern.GroupSize, numberOfThreads);

            RubiksCube newMaskedCube = new RubiksCube().ApplyMask(pattern.Mask);
            PuzzleState<RubiksCube> puzzleState = new PuzzleState<RubiksCube>(0, newMaskedCube);
            using (PuzzleStateQueue cubesToExamine = new PuzzleStateQueue(puzzleState.GetNumBytes(), 48000000, 1000))
            {
                SetInitalState(puzzleState, patternDatabase, cubesToExamine);

                PatternSetGeneratorWorker[] workers = new PatternSetGeneratorWorker[numberOfThreads];
                Task[] tasks = new Task[numberOfThreads];


                for (int i = 0; i < numberOfThreads; ++i)
                {
                    tasks[i] = Task.Factory.StartNew(() =>
                    {
                        new PatternSetGeneratorWorker(
                            patternDatabase,<commit_msg>The capacity of the ConcurrentMMFQueue is now based on the size of the pattern set rather than hard coded. This new value will be an overestimate of what is actually needed.<commit_after>﻿namespace Foat.Puzzles.RubiksCube.Solution
{
    using Foat.Hashing;
    using Foat.Puzzles.RubiksCube;
    using Foat.Puzzles.Solutions;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    
    /// <summary>
    /// This class generates a PatternSet that contains every cube that can possibly be reached by twisting a cube defined by an initial Pattern.
    /// </summary>
    public static class PatternSetGenerator
    {
        #region Static Methods

        /// <summary>
        /// Generates the entire PatternSet using the given Pattern as a starting point.
        /// </summary>
        /// <param name="pattern">The initial pattern in the set.</param>
        /// <param name="numberOfThreads">The number of threads to use while generating the pattern set.</param>
        public static PatternSet Generate(Pattern pattern, int numberOfThreads)
        {
            RubiksCubeDepthDatabase patternSetDictionary = GeneratePatternSetDictionary(pattern, numberOfThreads);
            MinimalPerfectHash<FnvHash> mph = GetMinimalPerfectHashForPatternSet(patternSetDictionary.Keys);

            return new PatternSet(patternSetDictionary, mph, pattern);
        }

        /// <summary>
        /// Generates a minimal perfect hash for every cube in the PatternSet. This is a hash that can map any cube in the set
        /// to an index in the range of 0 ... N - 1 where N is the number of cubes in the entire set. Useful for constant time
        /// lookups of any cube in the set.
        /// </summary>
        /// <param name="database"></param>
        /// <returns></returns>
        private static MinimalPerfectHash<FnvHash> GetMinimalPerfectHashForPatternSet(IEnumerable<RubiksCube> cubes)
        {
            MinimalPerfectHash<FnvHash> mph = new MinimalPerfectHash<FnvHash>();
            mph.Generate(cubes.Select(cube=>cube.GetBytes()));
                       
            return mph;
        }

        /// <summary>
        /// Generates a dictionary that maps RubiksCubes to the minimum number of moves it will take to solve that cube.
        /// </summary>
        /// <param name="pattern">The initial pattern that will be used to generate every other RubiksCube in the PatternSet.</param>
        /// <param name="numberOfThreads">The number of threads to use while generating the pattern set dictionary.</param>
        /// <returns></returns>
        private static RubiksCubeDepthDatabase GeneratePatternSetDictionary(Pattern pattern, int numberOfThreads)
        {
            RubiksCubeDepthDatabase patternDatabase = new RubiksCubeDepthDatabase(pattern.GroupSize, numberOfThreads);

            RubiksCube newMaskedCube = new RubiksCube().ApplyMask(pattern.Mask);
            PuzzleState<RubiksCube> puzzleState = new PuzzleState<RubiksCube>(0, newMaskedCube);
            using (PuzzleStateQueue cubesToExamine = new PuzzleStateQueue(puzzleState.GetNumBytes(), pattern.GroupSize, 1000))
            {
                SetInitalState(puzzleState, patternDatabase, cubesToExamine);

                PatternSetGeneratorWorker[] workers = new PatternSetGeneratorWorker[numberOfThreads];
                Task[] tasks = new Task[numberOfThreads];


                for (int i = 0; i < numberOfThreads; ++i)
                {
                    tasks[i] = Task.Factory.StartNew(() =>
                    {
                        new PatternSetGeneratorWorker(
                            patternDatabase,
{'fraction_non_alphanumeric': 0.08417415342087077, 'fraction_numerical': 0.00331720801658604, 'mean_word_length': 2.4358974358974357, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4044046', 'n_tokens_mistral': 1936, 'n_tokens_neox': 1802, 'n_words': 577}