//изменение кол-ва ферромона после прохождения муравья public static void updateFerromon(List <Vertex> list, Muravey muravey, Duga[,] curves) { double delta = deltaTau(muravey, curves); int count = 0; for (int i = 0; i < list.Count; i++) { for (int j = 0; j < list.Count; j++) { if (curves[i, j] != null) { curves[i, j].T = (1 - EVAPORATION_COEF) * curves[i, j].T; //если по дуге прошел муравей if (vertexContains(muravey.Way, i, j)) { curves[i, j].T += delta; if (i == 0) { count++; } } } } } }
public static void antAlhoritm(List <Vertex> list, Muravey muravey, List <int> ListVirtual, Duga[,] curves, BRANCH branch) { int CurrentMashine = startNode(list, curves, branch); //перезапись в первоначальные значения эвристической ф-ии restartEvristic(list, curves); while (!muravey.Tabu.SequenceEqual(ListVirtual)) { //добавление текущей вершины к пути муравья muravey.Way.Add(CurrentMashine); //добавление текущей вершины в список табу для муравья muravey.Tabu.Add(CurrentMashine); //получение следующей физической вершины (вирт ->физ) int indVertex = roulettePath(list, CurrentMashine, branch, MACHINE.REAL, muravey, curves); if (indVertex != 0) { //добавление вершины к пути муравья muravey.Way.Add(indVertex); //присвоение вирт машины физической addTarget(list, CurrentMashine, indVertex, muravey, curves); //добавление вершины к пути муравья(возврат к вирт. машине) muravey.Way.Add(CurrentMashine); } //получение индекса вирт.машины, к которой переходит муравей (вирт ->вирт) CurrentMashine = roulettePath(list, CurrentMashine, branch, MACHINE.VIRTUAL, muravey, curves); //если все вирт.машины посещены,то возврат к исходному if (CurrentMashine == 0) { muravey.Way.Add(CurrentMashine); break; } } }
//добавление дуг в графе static void addCurves(List <Vertex> list, Duga[,] curves) { Muravey muravey = new Muravey(0); for (int i = 0; i < list.Count - 1; i++) { for (int j = i + 1; j < list.Count; j++) { if ( (list[i].Type == MACHINE.VIRTUAL && list[j].Type == MACHINE.VIRTUAL && list[i].Branch == BRANCH.CALCULATIVE && list[j].Branch == BRANCH.CALCULATIVE) || (list[i].Type == MACHINE.VIRTUAL && list[j].Type == MACHINE.REAL && list[i].Branch == BRANCH.CALCULATIVE && list[j].Branch == BRANCH.CALCULATIVE) || (list[i].Type == MACHINE.VIRTUAL && list[j].Type == MACHINE.VIRTUAL && list[i].Branch == BRANCH.STORAGE && list[j].Branch == BRANCH.STORAGE) || (list[i].Type == MACHINE.VIRTUAL && list[j].Type == MACHINE.REAL && list[i].Branch == BRANCH.STORAGE && list[j].Branch == BRANCH.STORAGE)) { curves[i, j] = new Duga(1, Evristic(i, j, muravey, list)); curves[j, i] = new Duga(1, Evristic(j, i, muravey, list)); } if (list[i].Type == MACHINE.ROOT && list[j].Type == MACHINE.VIRTUAL) { curves[i, j] = new Duga(1, 1); curves[j, i] = new Duga(1, 1); } } } }
public void setTheBestWay(Muravey muravey) { if (muravey.target.Count >= Target.Count) { Way = muravey.Way; Target = muravey.target; } }
//вычисление дельта-тау для муравья public static double deltaTau(Muravey muravey, Duga[,] curves) { double sum = 0; for (int k = 0; k < (muravey.Way.Count - 1); k++) { int i = muravey.Way[k]; int j = muravey.Way[k + 1]; if (vertexContains(muravey.Way, i, j) && curves[i, j] != null) { sum += curves[i, j].N * Q; } } return(sum); }
//назначение дугам первоначальных значений эвристической ф-ии после прохода каждого муравья private static void restartEvristic(List <Vertex> list, Duga[,] curves) { Muravey muravey = new Muravey(0); for (int i = 1; i < list.Count; i++) { for (int j = 1; j < list.Count; j++) { if (curves[i, j] != null) { curves[i, j].N = Evristic(i, j, muravey, list); } } } }
private static double Evristic(int i, int j, Muravey muravey, List <Vertex> list) { if (list[i].Type == MACHINE.VIRTUAL && list[j].Type == MACHINE.VIRTUAL) { int max = 0; for (int k = 0; k < list.Count; k++) { if (list[k].Core > max) { max = list[k].Core; } } double result = (double)list[j].Core / max; if (result > 1) { return(0); } else { return(result); } } if ((list[i].Type == MACHINE.VIRTUAL && list[j].Type == MACHINE.REAL) || (list[j].Type == MACHINE.VIRTUAL && list[i].Type == MACHINE.REAL)) { int sum = 0; if (muravey.target.ContainsValue(list[j].Num)) { var keys = muravey.target.Where(x => x.Value == list[j].Num).ToList(); foreach (var k in keys) { sum += list[(int)k.Key].Core; } } double result = (double)(sum + list[i].Core) / (double)list[j].Core; if (result > 1) { return(0); } else { return(result); } } throw new Exception("Машины имеют не допустимый тип: " + i.ToString() + ", " + j.ToString()); }
//назначение вирт.машины физической для муравья и пересчет эвристической ф-ии public static void addTarget(List <Vertex> list, int CurrentMashine, int RealMachine, Muravey muravey, Duga[,] curves) { muravey.target.Add(CurrentMashine, RealMachine); for (int i = 0; i < list.Count; i++) { if (list[i].Type == MACHINE.VIRTUAL && curves[i, RealMachine] != null) { curves[i, RealMachine].N = Evristic(i, RealMachine, muravey, list); } } }
public static int roulettePath(List <Vertex> list, int CurrentMashine, BRANCH branch, MACHINE machine, Muravey muravey, Duga[,] curves) { //Dictionary для хранения вероятностей перехода вирт--->физ Dictionary <int, double> P = new Dictionary <int, double>(); int indVertex = 0; double p; //находнеие вероятностей перехода for (int j = 0; j < list.Count; j++) { //существут дуга && соотв. тип (вирт./физ.) && соответствут ветка (вычислит./storage) if (curves[CurrentMashine, j] != null && (list[j].Type == machine && list[j].Branch == branch)) { if ((machine == MACHINE.VIRTUAL && !muravey.Tabu.Contains(j)) || machine == MACHINE.REAL) { //верроятность перехода p = Math.Pow(curves[CurrentMashine, j].T, ALPHA) * Math.Pow(curves[CurrentMashine, j].N, BETA) / ZnamenatelP(list, CurrentMashine, branch, machine, curves, muravey); } else { p = 0; } P.Add(j, p); } } return(indVertex = rouletteChouse(P)); }
//муравьиный алгорит public static void Algoritm(string file) { //список вершин (вирт. машин +физ. вычислительных узлов) List <Vertex> vertex = new List <Vertex>(); vertex.Add(new Vertex(0, BRANCH.ROOT, MACHINE.ROOT, 0)); //массив дуг Duga[,] dugi; theBestSolution solution; Muravey[] muravey = new Muravey[COUNT_MURAVEY]; //заполнение списков vertex и storage readInputfromFile(file, vertex); dugi = new Duga[vertex.Count, vertex.Count]; solution = new theBestSolution(vertex.Count); //добавление дуг в графе addCurves(vertex, dugi); int[] count = new int[4]; //список вирт машин List <int> ListVirtual_vertex = new List <int>(); for (int i = 0; i < vertex.Count; i++) { if (vertex[i].Type == MACHINE.VIRTUAL && vertex[i].Branch == BRANCH.CALCULATIVE) { ListVirtual_vertex.Add(vertex[i].Num); count[0]++; } if (vertex[i].Type == MACHINE.REAL && vertex[i].Branch == BRANCH.CALCULATIVE) { count[1]++; } if (vertex[i].Type == MACHINE.VIRTUAL && vertex[i].Branch == BRANCH.STORAGE) { count[2]++; } if (vertex[i].Type == MACHINE.REAL && vertex[i].Branch == BRANCH.STORAGE) { count[3]++; } } //список вирт.элементов во всем графе List <int> ListVirtual_storage = new List <int>(); for (int i = 0; i < vertex.Count; i++) { if (vertex[i].Type == MACHINE.VIRTUAL) { ListVirtual_storage.Add(vertex[i].Num); } } //проход муравьями графа for (int m = 0; m < COUNT_MURAVEY; m++) { muravey[m] = new Muravey(0); //обход левой части графа(вирт.машины+физич.узлы) antAlhoritm(vertex, muravey[m], ListVirtual_vertex, dugi, BRANCH.CALCULATIVE); //Console.WriteLine(); //обход правой части графа(storage-элементы +хранилища данных) antAlhoritm(vertex, muravey[m], ListVirtual_storage, dugi, BRANCH.STORAGE); //изменение кол-ва ферромона на дугах updateFerromon(vertex, muravey[m], dugi); // Console.WriteLine(); //сортировка списка соответствий по ключу muravey[m].target = muravey[m].target.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value); solution.setTheBestWay(muravey[m]); } //оценка сходимости алгоритма solution.estimateWay(muravey); solution.theAdjacencyMatrixOfAGraph(vertex, dugi); //Deigstra(vertex, solution.AdjacencyMatrix); int[] rezult = new int[2]; foreach (int i in solution.Target.Keys) { for (int k = 0; k < vertex.Count; k++) { if (i == k) { if (vertex[i].Type == MACHINE.VIRTUAL && vertex[i].Branch == BRANCH.CALCULATIVE) { rezult[0]++; } if (vertex[i].Type == MACHINE.VIRTUAL && vertex[i].Branch == BRANCH.STORAGE) { rezult[1]++; } } } } Console.WriteLine(String.Format("|{0,15}|{1,7}|{2,7}|{3,11}|{4,10}|{5,8}|{6,14}|", file, count[0], count[1], rezult[0], count[2], count[3], rezult[1])); Console.WriteLine(String.Format("+---------------+-------+-------+-----------+----------+--------+--------------+")); Console.ReadKey(); }
//вычисление знаменателя в формуле вероятности (для выбора пути муравьем) public static double ZnamenatelP(List <Vertex> list, int i, BRANCH branch, MACHINE type, Duga[,] curves, Muravey muravey) { double sum = 0; for (int j = 0; j < list.Count; j++) { if (curves[i, j] != null && list[j].Type == type && list[j].Branch == branch && !muravey.Tabu.Contains(j)) { sum += Math.Pow(curves[i, j].T, ALPHA) * Math.Pow(curves[i, j].N, BETA); } } return(sum); }