Пример #1
0
        public TimeDiagram CreateDiagram <T>(IGraphicsFactory <T, IGraph> factory, out InteractiveDiagram interactiveDiagram) where T : InteractiveDiagram
        {
            List <string> labels = new List <string>(Parameters.ChannelCount + Parameters.QueueCapacity + 3);

            labels.Add("Заявки");

            for (int i = 0; i < Parameters.ChannelCount; i++)
            {
                labels.Add($"Канал { Parameters.ChannelCount - i }");
            }

            for (int i = 0; i < Parameters.QueueCapacity; i++)
            {
                labels.Add($"Место { Parameters.QueueCapacity - i }");
            }

            labels.Add("Обслужено");
            labels.Add("Отказ");

            T idg = factory.CreateEmptyDiagram(labels);

            TimeDiagram diagram = new TimeDiagram(Parameters.ChannelCount, Parameters.QueueCapacity, idg);

            FillDiagram(diagram);

            interactiveDiagram = idg;

            return(diagram);
        }
Пример #2
0
        void FillDiagram(TimeDiagram timeDiagram)
        {
            double step = 0.5 / Parameters.ThreadIntencity;


            RandomGenerator rnd = new RandomGenerator(Parameters.MinRandomValue);

            double realTime  = 0;
            double fixedTime = 0;

            for (int i = 0; !Parameters.HasClientLimit || i < Parameters.ClientLimit; i++)
            {
                double realRndValue;
                double rndValue = rnd.Next(Parameters.ThreadIntencity, out realRndValue);
                realTime += rndValue;

                while (fixedTime < realTime)
                {
                    timeDiagram.CheckClientCountAtTime(fixedTime);
                    fixedTime += step;
                }

                if (Parameters.HasTimeLimit && realTime > Parameters.TimeLimit)
                {
                    break;
                }

                PushClient(realTime, rnd, realRndValue, rndValue, timeDiagram);
            }

            timeDiagram.FinishDiagram();
        }
Пример #3
0
 // Добавляет новое событие на диаграмму
 private void SaveEvent(TimeDiagram diagram, DestroyableElement e, ElementState state, double t)
 {
     diagram[e.Data].Add(new StatePoint()
     {
         Time = t, State = state
     });
 }
Пример #4
0
        public TimeDiagram CreateDiagram()
        {
            var diagram = new TimeDiagram(Parameters.ChannelCount, Parameters.QueueCapacity);

            FillDiagram(diagram);

            return(diagram);
        }
Пример #5
0
 static string MakeReport(ParametersContainer diagramParameters, TimeDiagram timeDiagram)
 {
     return(diagramParameters.ToString() + "\r\n" + ReportTool.MakeReport(timeDiagram, clientMetrics, GetMetrics(timeDiagram.ChannelCount, timeDiagram.QueueCapacity)));
 }
Пример #6
0
        /// <summary>
        /// Создает новую линию в пути заявки, обслуженной на указанном месте обслуживания.
        /// </summary>
        /// <param name="channelIndex">Индекс используемого места обслуживания.</param>
        /// <param name="arrivalTime">Время начала обслуживания.</param>
        /// <param name="rnd">Используемый ГСЧ</param>
        void CreateChannelLine(int channelIndex, double arrivalTime, RandomGenerator rnd, TimeDiagram timeDiagram)
        {
            double realRndValue;
            double clientSerivceTime = rnd.Next(Parameters.ChannelsIntencites[channelIndex], out realRndValue);

            double departureTime = arrivalTime + clientSerivceTime;

            channelIdleTimes[channelIndex] = departureTime;

            timeDiagram.PushChannelLine(channelIndex, clientSerivceTime, realRndValue);
            timeDiagram.PushServedPoint();
        }
Пример #7
0
        /// <summary>
        /// Добавляет в систему новую заявку и строит ее путь.
        /// </summary>
        /// <param name="arrivalTime">Время прибытия заявки</param>
        /// <param name="rnd">Импользуемый ГСЧ</param>
        void PushClient(double arrivalTime, RandomGenerator rnd, double realRndValue, double interval, TimeDiagram timeDiagram)
        {
            timeDiagram.PushStartPoint(arrivalTime, realRndValue, interval);

            int usingChannel = GetNextPossibleChannel(arrivalTime);

            if (usingChannel == -1)
            {
                timeDiagram.PushRefusedPoint();
                return;
            }

            if (channelIdleTimes[usingChannel] < arrivalTime)
            {
                CreateChannelLine(usingChannel, arrivalTime, rnd, timeDiagram);
                return;
            }

            int queuePlaceIndex = GetQueuePlaceIndex(arrivalTime);

            if (queuePlaceIndex == -1)
            {
                timeDiagram.PushRefusedPoint();
                return;
            }

            double queuedStart = arrivalTime;

            for (int i = queuePlaceIndex; i >= 0; i--)
            {
                double queuedEndTime = i != 0 ? queueIdleTimes[i - 1] : channelIdleTimes[usingChannel];

                queueIdleTimes[i] = queuedEndTime;

                timeDiagram.PushQueueLine(i, queuedEndTime - queuedStart);
                queuedStart = queuedEndTime;
            }

            CreateChannelLine(usingChannel, queueIdleTimes[0], rnd, timeDiagram);
        }
Пример #8
0
        // Симлуляция одной итерации до отказа (или истечения времени)
        private IterationReport RunIteration(ComputationGraph cGraph, SimulationSettings settings, bool saveTimeline = false)
        {
            /* Идея алгоритма
             *  Есть события (отказ или восстанолвение), которые
             *  хранятся в куче. На вершине кучи всегда самое ближайшее событие
             *
             *  Есть заявки на восстановление, которые помещаются в очередь с
             *  какой-то политикой
             *
             *   - Генерируем событие отказа, помещаем его в кучу
             *   - Извлекаем из кучи очередное событие
             *      - Отказ:
             *          - Отказываем элемент
             *          - Помещаем заявку на восстановление в очередь
             *          - Генерируем новый отказ, помещаем в кучу
             *      - Восстановление
             *          - Восстанавливаем элемент
             *
             *    - Каждый раз мы берем свободных воркеров и раздаем
             *    им задачи из очереди. Каждая задача становится событием
             *    восстановления через некоторое время
             */

            var         repairTimeList = new List <double>();
            TimeDiagram diagram        = null;

            if (saveTimeline)
            {
                diagram = new TimeDiagram();
                foreach (var element in cGraph.Elements)
                {
                    var tl = new TimeLine();
                    tl.Add(new StatePoint()
                    {
                        State = ElementState.OK, Time = 0
                    });
                    diagram.Add(element.Value.Data, tl);
                }
            }

            var heap        = new Heap <SimulationEvent>(new MinPriorityComparer <SimulationEvent>());
            var repairQueue = settings.RepairFactory.CreateQueue();

            double t           = 0;
            int    freeWorkers = settings.RepairTeamsCount;

            // Генерируем первый отказ
            SimulationEvent ev = GenerateFailureEvent(cGraph, t);

            heap.Add(ev);

            while (cGraph.IsPathExists() && t < settings.MaxTime)
            {
                ev = heap.Pop();
                t  = ev.Time;

                if (ev.Type == EventType.FAILURE)
                {
                    ev.Element.IsDestroyed = true;

                    // Добавляем задачу в очередь на восстановление
                    if (settings.IsRepair)
                    {
                        CreateRepairTask(ev, t, settings.RepairIntensity, repairQueue);
                    }

                    // Сохраняем событие на диаграмме
                    if (saveTimeline)
                    {
                        SaveEvent(diagram, ev.Element, ElementState.FAILURE, t);
                    }

                    ev = GenerateFailureEvent(cGraph, t);
                    heap.Add(ev);
                }
                else
                {
                    ev.Element.IsDestroyed = false;
                    freeWorkers++;

                    // Сохраняем событие на диаграмме
                    if (saveTimeline)
                    {
                        SaveEvent(diagram, ev.Element, ElementState.OK, t);
                    }
                }

                // Начинаем восстанвливать
                while (freeWorkers > 0 && repairQueue.Count > 0 && settings.IsRepair)
                {
                    var task = repairQueue.Pop();
                    ev = new SimulationEvent()
                    {
                        Element = task.Element,
                        Time    = t + task.TimeToRepair,
                        Type    = EventType.REPAIR
                    };

                    heap.Add(ev);
                    freeWorkers--;

                    // Сохраняем статистику по восстановлению
                    repairTimeList.Add(task.TimeToRepair);

                    // Сохраняем событие на диаграмме
                    if (saveTimeline)
                    {
                        SaveEvent(diagram, ev.Element, ElementState.REPAIR, t);
                    }
                }
            }

            return(new IterationReport()
            {
                FailureTime = t,
                RepairTimes = repairTimeList,
                TimeDiagram = diagram
            });
        }