コード例 #1
0
        private static void DoWork(string[] args)
        {
            using (var solutionSemaphore = new Semaphore(0, int.MaxValue))
            {
                var makeSound = false;
                if (args.Length >= 2)
                {
                    if (int.TryParse(args[1], out var enabled2))
                    {
                        makeSound = enabled2 != 0;
                    }
                }
                var maximumAutomatonCollectionSize = int.MaxValue;

                var           minimalSynchronizingLength = 0;
                var           unaryResourcesQueue        = new ConcurrentQueue <int>();
                MicroSolution results = null;
                var           resultsMergedTotalAutomata = 0;

                #region address setup
                var address = $"http://localhost:62752/ua";
                if (args.Length >= 1)
                {
                    address = $"{args[0]}/ua";
                }
                Console.WriteLine($"Connecting to {address}");
                #endregion

                #region WebSocket connection
                var shouldReconnect = true;

                var connectionBuild = new HubConnectionBuilder().WithUrl(address).AddMessagePackProtocol();
                var connection      = connectionBuild.Build();

                connection.On("NoMoreAutomataThankYou", async() =>
                {
                    try
                    {
                        SayColoured(ConsoleColor.Magenta, "No more automata needed to compute");
                        shouldReconnect = false;
                        await connection.StopAsync();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception: " + e.Message);
                    }
                }
                              );

                connection.On("ComputeAutomata", async(ServerClientSentUnaryAutomataWithSettings parameters) =>
                {
                    try
                    {
                        maximumAutomatonCollectionSize = parameters.targetCollectionSize;

                        if (parameters.serverMinimalLength != minimalSynchronizingLength)
                        {
                            SayColoured(ConsoleColor.Red, $"New lower bound on synchronizing word length from server {parameters.serverMinimalLength}");
                        }

                        // no need for pedantic synchronization, the server will ultimately handle everything synchronously
                        if (minimalSynchronizingLength < parameters.serverMinimalLength)
                        {
                            minimalSynchronizingLength = parameters.serverMinimalLength;
                        }


                        var startTime            = DateTime.Now;
                        var list                 = new List <ISolvedOptionalAutomaton>();
                        var uniqueAutomaton      = UniqueUnaryAutomata.Generator.GetUniqueAutomatonFromCached(parameters.automatonSize, parameters.unaryAutomatonIndex);
                        var uniqueAutomatonBytes = new byte[uniqueAutomaton.Length];
                        for (int i = 0; i < uniqueAutomaton.Length; i++)
                        {
                            uniqueAutomatonBytes[i] = (byte)uniqueAutomaton[i];
                        }

                        var localLength = minimalSynchronizingLength;
                        SayColoured(ConsoleColor.DarkGray, $"Preparing to compute {parameters.unaryAutomatonIndex} unary automaton of size {parameters.automatonSize} with minimum length of {parameters.serverMinimalLength}");
                        foreach (var automaton in new BinaryAutomataIterator().GetAllSolved(parameters.automatonSize, parameters.unaryAutomatonIndex))
                        {
                            if (automaton.SynchronizingWordLength.HasValue && automaton.SynchronizingWordLength.Value >= localLength)
                            {
                                list.Add(automaton.DeepClone());
                            }
                        }

                        if (list.Count > 0)
                        {
                            SayColoured(ConsoleColor.Blue, $"Completed unary {parameters.unaryAutomatonIndex} (found {list.Count})");
                        }
                        else
                        {
                            SayColoured(ConsoleColor.DarkGray, $"Completed unary {parameters.unaryAutomatonIndex} (not found any)");
                        }

                        var finishedTime = DateTime.Now;
                        results          = new MicroSolution()
                        {
                            unaryIndex     = parameters.unaryAutomatonIndex,
                            unaryItself    = uniqueAutomatonBytes,
                            solvedAutomata = list,
                            startTime      = startTime,
                            finishTime     = finishedTime
                        };
                        SayColoured(ConsoleColor.Gray, $"Notifying client about new solution {parameters.unaryAutomatonIndex}");
                        Interlocked.Add(ref resultsMergedTotalAutomata, list.Count);
                        solutionSemaphore.Release();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception: " + e.Message);
                    }
                }
                              );

                #region Updating minimum synchronizing word length
                connection.On("UpdateLength", async(int serverMinimalLength) =>
                {
                    SayColoured(ConsoleColor.DarkRed, $"Dynamically updated length to {serverMinimalLength}!");
                    minimalSynchronizingLength = serverMinimalLength;
                });
                #endregion

                #region on connection close
                connection.Closed += async(error) =>
                {
                    if (shouldReconnect)
                    {
                        SayColoured(ConsoleColor.Red, "Closed connection. Reconnecting...");
                        try
                        {
                            await Task.Delay((int)(Math.Exp(new Random().NextDouble() * 2 + 7)));

                            await connection.StartAsync();
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("Exception: " + e.Message);
                        }
                    }
                    else
                    {
                        SayColoured(ConsoleColor.Magenta, "Connection ended");
                    }
                };
                #endregion
                #endregion
                var repeat = true;
                while (repeat)
                {
                    repeat = false;
                    try
                    {
                        connection.StartAsync().Wait();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception: " + e.Message);
                        Console.WriteLine("Could not connect. Retrying...");
                        repeat = true;
                    }
                }

                var solvedUnaryAutomata = 0;
                var solveBeginningTime  = DateTime.Now;
                var afterSentDate       = DateTime.Now;


                SayColoured(ConsoleColor.Gray, $"Initializing connection...");
                connection.InvokeAsync("InitializeConnection").Wait();
                SayColoured(ConsoleColor.Green, $"Registration sent!");
                while (connection.State == HubConnectionState.Connected && shouldReconnect)
                {
                    SayColoured(ConsoleColor.Gray, $"Waiting for a task to complete...");
                    solutionSemaphore.WaitOne();
                    SayColoured(ConsoleColor.Green, $"A task is completed! Preparing results...");

                    var previousMinimalSyncLength = minimalSynchronizingLength;
                    var preparedResult            = PrepareNextRound(results, ref resultsMergedTotalAutomata, ref maximumAutomatonCollectionSize, ref minimalSynchronizingLength, out var toSendAutomataCount);
                    SayColoured(ConsoleColor.Green, $"Results ready to send!");
                    if (minimalSynchronizingLength != previousMinimalSyncLength)
                    {
                        SayColoured(ConsoleColor.Red, $"Changed locally the minimal sync length from {previousMinimalSyncLength} to {minimalSynchronizingLength}");
                    }

                    // might still throw an exception, we allow that
                    if (connection.State == HubConnectionState.Connected && shouldReconnect)
                    {
                        solvedUnaryAutomata += 1;
                        var automataPerSecond = solvedUnaryAutomata / (DateTime.Now - solveBeginningTime).TotalSeconds;

                        SayColoured(ConsoleColor.Gray, $"Sending back a unary solution having {toSendAutomataCount.ToString()} total automata...");
                        var command = connection.InvokeAsync("ReceiveSolvedUnaryAutomatonAndAskForMore", new ClientServerRequestForMoreAutomata()
                        {
                            nextQuantity          = 1,
                            suggestedMinimumBound = minimalSynchronizingLength,
                            solution = preparedResult
                        });
                        if (makeSound)
                        {
                            Console.Beep();
                        }
                        command.Wait();

                        #region Sent back description
                        SayColoured(ConsoleColor.DarkGray, $"Sent back! Total speed including communication time gaps: {automataPerSecond:F2} unary automata per second");
                        #endregion

                        afterSentDate = DateTime.Now;
                    }
                    else
                    {
                        Console.WriteLine("Connection ended! Exiting loop.");
                        break;
                    }

                    if (!shouldReconnect)
                    {
                        break;
                    }
                }
                Console.WriteLine("Exited loop.");
            }
        }
コード例 #2
0
        private static SolvedAutomatonMessage PrepareNextRound(
            MicroSolution solution,
            ref int resultsMergedTotalAutomata,
            ref int maximumAutomatonCollectionSize,
            ref int minimalSynchronizingLength,
            out int toSendAutomataCount
            )
        {
            SolvedAutomatonMessage result  = null;
            var synchronizingLengthToCount = new SortedDictionary <int, int>();

            toSendAutomataCount = 0;
            Interlocked.Add(ref resultsMergedTotalAutomata, -solution.solvedAutomata.Count);

            var syncLengths           = new List <ushort>();
            var solvedBs              = new List <byte[]>();
            var ignoreLimitsThreshold = IgnoreThreshold(solution.unaryItself.Length);

            foreach (var automaton in solution.solvedAutomata)
            {
                syncLengths.Add(automaton.SynchronizingWordLength.Value);
                if (automaton.SynchronizingWordLength.Value < ignoreLimitsThreshold)
                {
                    toSendAutomataCount += 1;
                }
                solvedBs.Add(automaton.TransitionFunctionsB);

                if (!synchronizingLengthToCount.ContainsKey(automaton.SynchronizingWordLength.Value))
                {
                    synchronizingLengthToCount.Add(automaton.SynchronizingWordLength.Value, 0);
                }
                synchronizingLengthToCount[automaton.SynchronizingWordLength.Value] += 1;
            }

            result = new SolvedAutomatonMessage()
            {
                unaryIndex       = solution.unaryIndex,
                solvedB          = solvedBs,
                solvedSyncLength = syncLengths,
                unaryArray       = solution.unaryItself,
                startTime        = solution.startTime,
                finishTime       = solution.finishTime
            };

            if (toSendAutomataCount > maximumAutomatonCollectionSize)
            {
                var removeUpTo = -1;
                foreach (var item in synchronizingLengthToCount)
                {
                    if (toSendAutomataCount > maximumAutomatonCollectionSize)
                    {
                        toSendAutomataCount -= item.Value;
                        removeUpTo           = item.Key;
                    }
                    else
                    {
                        break;
                    }
                }

                if (removeUpTo + 1 > minimalSynchronizingLength)
                {
                    minimalSynchronizingLength = removeUpTo + 1;
                }

                var newSyncLengths = new List <ushort>();
                var newSolvedB     = new List <byte[]>();
                for (int i = 0; i < result.solvedB.Count; i++)
                {
                    if (result.solvedSyncLength[i] >= minimalSynchronizingLength)
                    {
                        newSyncLengths.Add(result.solvedSyncLength[i]);
                        newSolvedB.Add(result.solvedB[i]);
                    }
                }
                result.solvedB          = newSolvedB;
                result.solvedSyncLength = newSyncLengths;
            }

            return(result);
        }