/// <summary> /// Проверяет на элементарность матрицу в матрице передачи /// </summary> /// <param name="Theta">Матрица передачи</param> /// <param name="k">Номер матрицы, которую необходимо проверить</param> /// <param name="F">Массив номеров дивайдеров</param> /// <returns></returns> public static bool IsTrivialMatrix(RoutingMatrix Theta, int k, int[] F) { for (int i = 0; i < Theta.Dimention; i++) { for (int j = 0; j < F.Length; j++) { if (Theta[k][i, F[j]] > 0) { return(false); } } } return(true); }
/// <summary> /// Находит элементраную подсеть и возвращает номер соотвествующей элементарной матрицы /// </summary> /// <param name="F">Множество номеров дивайдеров</param> /// <param name="Theta">Матрица передачи</param> /// <returns></returns> public static int FindTrivialNetwork(int[] F, RoutingMatrix Theta) { //Найти элементарную подсеть int trivial_ind = 0; bool success = false; for (; trivial_ind < Theta.CountForker; trivial_ind++) { if (IsTrivialMatrix(Theta, trivial_ind, F)) { success = true; break; } } if (success == false) { return(-1); } return(trivial_ind); }
/// <summary> /// Выполние редукции относительно элементарной подсети k /// </summary> /// <param name="Network"></param> /// <param name="k">Номер элементарной подсети</param> /// <returns></returns> public static DescriptionOFJQN ReduceTrivialSubNetwork(DescriptionOFJQN Description, int k) { //Генерация фазового распределения для элементраной сети #if (DEBUG) Console.WriteLine("Выполнение редукции"); #endif PhaseTypeVarible TrivialPH = ResponseTimeDistributionForTrivialSubNetwork(Description.S, Description.F, Description.J, Description.Theta, Description.mu, k); int Y = TrivialPH.NumberOfPhases; var A = TrivialPH.SubGenerator; var alpha = TrivialPH.InitialDistribution; //Число всех систем в сети int L = Description.Theta.Dimention - 1; //2) Множества номеров базовых систем, дивайдеров, интеграторов для новой сети List <int> S = new List <int>(); //Вектор интенсивностей осблуживания для новой сети List <double> mu = new List <Double>(); for (int i = 0; i < Description.S.Length; i++) { mu.Add(Description.mu[i]); S.Add(Description.S[i]); } for (int i = 0; i < Y; i++) { mu.Add(-A[i, i]); S.Add(L + i + 1); } //Дивайдеры и интеграторы для новой сети List <int> F = new List <int>(); List <int> J = new List <int>(); for (int i = 0; i < Description.F.Length; i++) { F.Add(Description.F[i]); J.Add(Description.J[i]); } //3) Создаем новую матрицу передачи RoutingMatrix ReducedTheta = new RoutingMatrix(Y + Description.Theta.Dimention, Description.Theta.CountForker); //Копирование исходной матрицы в матрицу для новой сети for (int l = 0; l < Description.Theta.CountForker; l++) { for (int i = 0; i < Description.Theta.Dimention; i++) { for (int j = 0; j < Description.Theta.Dimention; j++) { ReducedTheta[l][i, j] = Description.Theta[l][i, j]; } } } //Переходы между новыми базовыми системами for (int l = 0; l < ReducedTheta.CountForker; l++) { //Возможность перехода для l-фрагмента в элементарную подсеть H_k (т.е. в дивайдер F_k) bool transition = false; for (int i = 0; i < Description.Theta.Dimention; i++) { if (Description.Theta[l][i, Description.F[k - 1]] > 0) { transition = true; break; } } if (transition == false) { continue; } for (int i = 1; i <= Y; i++) { for (int j = 1; j <= Y; j++) { if (i != j) { ReducedTheta[l][i + L, j + L] = -A[i - 1, j - 1] / A[i - 1, i - 1]; } } } } //вероятности перехода в подсеть и выхода из подсети for (int l = 0; l < ReducedTheta.CountForker; l++) { for (int i = 0; i <= L; i++) { for (int j = 1; j <= Y; j++) { ReducedTheta[l][i, L + j] = alpha[j - 1] * Description.Theta[l][i, Description.F[k - 1]]; } } } for (int l = 0; l < ReducedTheta.CountForker; l++) { for (int i = 1; i <= Y; i++) { for (int j = 0; j <= L; j++) { double a_star = -A.Row(i - 1).Sum(); ReducedTheta[l][L + i, j] = -a_star / A[i - 1, i - 1] * Description.Theta[l][Description.J[k - 1], j]; } } } //Удаление строк и столбцов ReducedTheta.DeleteMatrix(k, F[k - 1], J[k - 1]); int xF = F[k - 1]; F.RemoveAt(k - 1); //Удаление дивайдера Reorder(F, xF); Reorder(S, xF); Reorder(J, xF); int xJ = J[k - 1]; J.RemoveAt(k - 1);//Удаление интегратора Reorder(F, xJ); Reorder(S, xJ); Reorder(J, xJ); //Здесь нужно убрать все недостижимые базовые системы return(new DescriptionOFJQN(S.ToArray(), F.ToArray(), J.ToArray(), mu.ToArray(), null, ReducedTheta, Description.Lambda0)); }
/// <summary> /// Получает интенсивности потоков для каждой из систем в сети /// </summary> /// <param name="S">Массив номеров базовых систем </param> /// <param name="F">Массив номеров дивайдеров</param> /// <param name="J">Массив номеров интеграторов</param> /// <param name="Lambda0">ИНтенсивность входящего потока</param> /// <param name="Theta">Матрица передачи</param> /// <returns>Словарь, в котором ключ - вектор перемещений, а значение - вектор интенсвиностей для входящего потока /// в базовые системы и дивайдеры (S_1, S_2, ...S_LS, F_1, F_2, ..., F_LF) </returns> public static Dictionary <string, double[]> InputRates(int[] S, int[] F, int[] J, double Lambda0, RoutingMatrix Theta) { //Словарь с элементами (вектор перемещений; вектор интенсивостей) Dictionary <string, double[]> rates = new Dictionary <string, double[]>(); //Первый этап - Решение уравнения потока для требований //Размерность СЛАУ int n = F.Length + S.Length; int k = 0; //0-фрагменты //Перенумерация интенсивностей происходит по порядку //сначала для БС, а затем для дивайдеров: //lambda(S1) = lambda(1), ..., lambda(SL_S) = lambda(L_S) //lambda (F1) = lambda(L_S), ... lambdA(FL_F) = lambda(L_F+L_S) Matrix A = new Matrix(n, n); double[] b = new double[n]; //Нумерация базовых систем и интеграторов //базовых систем и дивайдеров int[] SF = new int[S.Length + F.Length]; int[] SJ = new int[S.Length + F.Length]; for (int i = 0; i < S.Length; i++) { SF[i] = S[i]; SJ[i] = S[i]; } for (int i = 0; i < F.Length; i++) { SF[i + S.Length] = F[i]; SJ[i + S.Length] = J[i]; } for (int j = 0; j < A.CountRow; j++) { for (int i = 0; i < A.CountColumn; i++) { A[j, i] = Theta[k, SJ[i], SF[j]]; if (i == j) { A[i, j]--; } } //Поток требований из источника b[j] = -Lambda0 * Theta[k, 0, SF[j]]; } rates.Add("0", Computation.Gauss(A, b)); HashSet <string> UnknownRates = new HashSet <string>(); UnknownRates.Add("0"); //Пока множество не пусто while (UnknownRates.Count != 0) { string v = UnknownRates.ElementAt(0); UnknownRates.Remove(v); //Проверяю поток в дивайдер for (k = 0; k < F.Length; k++) { //Если есть поток в k-ый дивайдер, то определяю итенсивности для //вектора перемещений (v,k) int indexFk = Array.IndexOf(SF, F[k]); if (rates[v][indexFk] > 0) { A.Initialize(); b.Initialize(); for (int j = 0; j < A.CountRow; j++) { for (int i = 0; i < SF.Length; i++) { A[j, i] = Theta[k + 1, SJ[i], SF[j]]; if (i == j) { A[i, j]--; } } //Поток требований в БС и дивайдер (в интегратор поток требований идти не может) b[j] = -rates[v][indexFk] * Theta[k + 1, F[k], SF[j]]; } string new_v = v + "," + (k + 1).ToString(); rates.Add(new_v, Computation.Gauss(A, b)); UnknownRates.Add(new_v); } } } return(rates); }
/// <summary> /// /// </summary> /// <param name="S"></param> /// <param name="F"></param> /// <param name="J"></param> /// <param name="Theta"></param> /// <param name="mu"></param> /// <param name="TrivialIndex">Индекс элеметарной подсети (k>0) </param> /// <returns></returns> public static PhaseTypeVarible ResponseTimeDistributionForTrivialSubNetwork(int[] S, int[] F, int[] J, RoutingMatrix Theta, double[] mu, int TrivialIndex) { #if (DEBUG) Console.WriteLine("Получение длительности реациии для элементарной подсети соглано теореме"); #endif //Счет всех собственных номеров идет с нуля! //Множество собственных номеров базовых систем, в которые переходят фрагменты непосредственно после деления // в дивайдере F_k List <int> R = new List <int>(); int k = TrivialIndex; for (int j = 0; j < S.Length; j++) { if (Theta[k][F[k - 1], S[j]] > 0) { R.Add(j); } } int cR = R.Count; List <int>[] B = new List <int> [cR]; for (int i = 0; i < B.Length; i++) { //B[i] - последовательность, состоящая из собственных номеров базовых систем в которые //возможно поступление k-фрагмента из базовой системы S_R[i], i = 0, ..., cR-1 B[i] = new List <int>(); //Начинаем обход в ширину из вершины S_R[i] Queue <int> queue = new Queue <int>(); queue.Enqueue(R[i]); //Первый элемент - сосбственный номер базовой системы S_R[i] while (queue.Count != 0) { //Достать из очереди собственный номер базовой системы int j = queue.Dequeue(); //Положить в список просмотренных вершин B[i].Add(j); //Для всех смежных вершин выполнить for (int l = 0; l < S.Length; l++) { //Если возможен переход //вершина не посещена //и не нарпавлена в очередь для посещения if ((Theta[k][S[j], S[l]] > 0) && (queue.Contains(l) == false) && (B[i].Contains(l) == false)) { //Запланировал посетить эту вершину queue.Enqueue(l); } } } //Упорядочиваем, но на первом месте должен стоять элемент R[i] B[i].Sort(); B[i][B[i].IndexOf(R[i])] = B[i][0]; B[i][0] = R[i]; } List <PhaseTypeVarible> ph = new List <PhaseTypeVarible>(); //Вычисления по формуле for (int i = 0; i < R.Count; i++) { int j = R[i]; //Число систем достижимых из Sj (включая Sj) var b = B[i]; int cb = b.Count; //Начальное распределение double[] alpha = new double[cb]; alpha[0] = 1; //Генератор Matrix A = new Matrix(cb, cb); for (int n = 0; n < cb; n++) { for (int m = 0; m < cb; m++) { //n* m* номера базовых систем во множестве всех систем int n_ = b[n] + 1; int m_ = b[m] + 1; A[n, m] = mu[b[n]] * Theta[k][n_, m_]; if (n == m) { A[n, m] = -mu[b[n]]; } } } //Получили генератор и начальное распределение для одной из начальных систем for (int l = 1; l <= Theta[k][F[k - 1], S[j]]; l++) { ph.Add(new PhaseTypeVarible(A, alpha)); #if (DEBUG) Console.WriteLine("Вывод параметров фазового распределения"); Console.WriteLine(new PhaseTypeVarible(A, alpha)); #endif } } #if (DEBUG) Console.WriteLine("Распределение для всей подсети"); Console.WriteLine(PHOperations.Max(ph)); Console.ReadKey(); #endif return(PHOperations.Max(ph)); }