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); }
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(); }
// Добавляет новое событие на диаграмму private void SaveEvent(TimeDiagram diagram, DestroyableElement e, ElementState state, double t) { diagram[e.Data].Add(new StatePoint() { Time = t, State = state }); }
public TimeDiagram CreateDiagram() { var diagram = new TimeDiagram(Parameters.ChannelCount, Parameters.QueueCapacity); FillDiagram(diagram); return(diagram); }
static string MakeReport(ParametersContainer diagramParameters, TimeDiagram timeDiagram) { return(diagramParameters.ToString() + "\r\n" + ReportTool.MakeReport(timeDiagram, clientMetrics, GetMetrics(timeDiagram.ChannelCount, timeDiagram.QueueCapacity))); }
/// <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(); }
/// <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); }
// Симлуляция одной итерации до отказа (или истечения времени) 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 }); }