Beispiel #1
0
        private static int[][] GenerateOneStepFurtherExactly(IEnumerable <int[]> multipleTransitionFunctions, int newPosition, long targetCount, int precomputedIntegrityLevel, GeneratorHelper generatorHelper)
        {
            var automataToReturn = new int[targetCount][];
            int pasteCounter     = 0;
            var hashSet          = new ConcurrentDictionary <long, object>();

            foreach (var oldTransitionFunction in multipleTransitionFunctions)
            {
                var verticesIncludingNew = newPosition + 1;
                var temporary            = new long[verticesIncludingNew];
                var hashes  = new long[verticesIncludingNew];
                var mailbox = new List <long> [verticesIncludingNew];
                for (int i = 0; i < mailbox.Length; i++)
                {
                    mailbox[i] = new List <long>();
                }

                foreach (var newTransitionFunction in GenerateNewMutableLightweightFromSmart(oldTransitionFunction, newPosition))
                {
                    generatorHelper.InitializeIteration(newTransitionFunction, hashes, mailbox);
                    var automatonHash = generatorHelper.IterateAndSquashMultiple(newTransitionFunction, hashes, temporary, mailbox, precomputedIntegrityLevel);
                    if (!hashSet.ContainsKey(automatonHash))
                    {
                        if (hashSet.TryAdd(automatonHash, null))
                        {
                            var index = Interlocked.Increment(ref pasteCounter);
                            automataToReturn[index - 1] = (int[])newTransitionFunction.Clone();
                        }
                    }
                }
            }

#if diagnostics
            if (pasteCounter != automataToReturn.Length)
            {
                throw new Exception("Not enough automata produced!");
            }
#endif
            return(automataToReturn);
        }
Beispiel #2
0
        private static int[][] GenerateOneStepFurther(IEnumerable <int[]> multipleTransitionFunctions, int newPosition, long targetCount, ref int maximumEstimatedIntegrityLevel, GeneratorHelper generatorHelper)
        {
            var automataCandidates = multipleTransitionFunctions
                                     .Select(transitionFunctions => GenerateNewMutableClonesFromSmart(transitionFunctions, newPosition))
                                     .SelectMany(id => id)
                                     .ToArray();

            var individualVerticesHashes = new long[automataCandidates.Length][];

            var verticesIncludingNew = newPosition + 1;

            for (int automatonID = 0; automatonID < automataCandidates.Length; automatonID += 1)
            {
                individualVerticesHashes[automatonID] = new long[verticesIncludingNew];
            }

#if diagnostics
            Console.WriteLine($"Total number of automata: {automataCandidates.Length}");
#endif

            var hashToGroup = new Dictionary <long, SameHashCollisionGroup>();

            int estimatedIntegrityLevel = maximumEstimatedIntegrityLevel;

            void insertIdIntoHashbag(Dictionary <long, SameHashCollisionGroup> map, long hash, int id)
            {
                if (!map.ContainsKey(hash))
                {
                    map.TryAdd(hash, new SameHashCollisionGroup()
                    {
                        automatonIDs     = new ConcurrentBag <int>(),
                        agreedIterations = estimatedIntegrityLevel
                    });
                }

                map[hash].automatonIDs.Add(id);
            }

            List <long>[] SetupNewMailbox(int size)
            {
                var mailbox = new List <long> [size];

                for (int i = 0; i < mailbox.Length; i++)
                {
                    mailbox[i] = new List <long>();
                }
                return(mailbox);
            }

#if diagnostics
            int       progress           = 0;
            const int progressReportSize = 262143;
            var       last = (automataCandidates.Length / progressReportSize) * progressReportSize;
            Console.WriteLine("Please wait...");
#endif

            for (int automatonID = 0; automatonID < automataCandidates.Length; automatonID++)
            {
                var temporary = new long[verticesIncludingNew];
                var mailbox   = SetupNewMailbox(verticesIncludingNew);
#if diagnostics
                if ((automatonID & progressReportSize) == 0 && automatonID > 0)
                {
                    Interlocked.Add(ref progress, progressReportSize);
                    Console.WriteLine($"Preparing... {(progress) * 100d / automataCandidates.Length}%");
                }
#endif
                generatorHelper.InitializeIteration(automataCandidates[automatonID], individualVerticesHashes[automatonID], mailbox);
                var initialHash = generatorHelper.IterateAndSquashMultiple(automataCandidates[automatonID], individualVerticesHashes[automatonID], temporary, mailbox, estimatedIntegrityLevel);
                insertIdIntoHashbag(hashToGroup, initialHash, automatonID);
            }

            Dictionary <long, SameHashCollisionGroup> integrityLevelConformant = hashToGroup;
            int requiredIntegrityLevel = maximumEstimatedIntegrityLevel;
            while (targetCount > hashToGroup.Count)
            {
#if diagnostics
                Console.WriteLine($"Integrity level is too low: {requiredIntegrityLevel}");
#endif
                requiredIntegrityLevel  += 1;
                integrityLevelConformant = new Dictionary <long, SameHashCollisionGroup>();

                while (hashToGroup.Count > 0 && targetCount > hashToGroup.Count)
                {
                    // pass groups that fulfil integrity level requirement
#if diagnostics
                    Console.WriteLine($"LEFTOVER to recompute: {hashToGroup.Count}");
#endif
                    var stack = new Stack <long>(hashToGroup.Keys);
                    while (stack.Count > 0)
                    {
                        var key = stack.Pop();

                        if (targetCount == hashToGroup.Count)
                        {
                            break;
                        }
                        var temporary = new long[verticesIncludingNew];
                        var mailbox   = SetupNewMailbox(verticesIncludingNew);

                        var collisionGroup = hashToGroup[key];

                        var queuedHashes    = new Queue <long>();
                        var differentHashes = new HashSet <long>();
                        // recompute hashes
                        foreach (var automatonID in collisionGroup.automatonIDs)
                        {
                            var nextHash = generatorHelper.IterateAndSquashMultiple(automataCandidates[automatonID], individualVerticesHashes[automatonID], temporary, mailbox, requiredIntegrityLevel - collisionGroup.agreedIterations);
                            differentHashes.Add(nextHash);
                            queuedHashes.Enqueue(nextHash);
                        }

                        if (differentHashes.Count == 1)
                        {
                            collisionGroup.agreedIterations = requiredIntegrityLevel;
                            hashToGroup.Remove(key, out collisionGroup);
                            integrityLevelConformant.TryAdd(key, collisionGroup);
                        }
                        else
                        {
                            hashToGroup.Remove(key, out collisionGroup);

                            foreach (var automatonID in collisionGroup.automatonIDs)
                            {
                                insertIdIntoHashbag(hashToGroup, queuedHashes.Dequeue(), automatonID);
                            }

                            foreach (var item in differentHashes)
                            {
                                stack.Push(item);
                            }
                        }
                    }
                    ;
                }

                foreach (var kvp in hashToGroup)
                {
                    integrityLevelConformant.TryAdd(kvp.Key, kvp.Value);
                }

                hashToGroup = integrityLevelConformant;
            }

#if diagnostics
            Console.WriteLine($"Integrity level is enough: {requiredIntegrityLevel}");
#endif

            maximumEstimatedIntegrityLevel = requiredIntegrityLevel;

            // return all unique automata
            return(integrityLevelConformant.Select(kvp =>
            {
                kvp.Value.automatonIDs.TryPeek(out int representativeAutomatonID);
                return automataCandidates[representativeAutomatonID];
            }).ToArray());
        }