public static Ant RunMMAS(Graph graph, Parameters parameters, UInt32 iterations) { var greedySolution = CreateSolutionNN(graph); var greedyCost = graph.CalculateRouteLength(greedySolution.visited); var initialLimits = CalcTrailLimitsMMAS(parameters, graph.dimension, greedyCost); var minPheromone = initialLimits.Item1; var maxPheromone = initialLimits.Item2; PheromoneMemory pheromone = new PheromoneMemory(graph.dimension, maxPheromone); double[] heuristic = new double[graph.dimension * graph.dimension]; foreach (var distance in graph.edgeWeight) { for (int i = 0; i < graph.dimension; i++) { for (int j = 0; j < graph.dimension; j++) { heuristic[j + (graph.dimension * i)] = (1 / Math.Pow(graph.edgeWeight[i, j], parameters.beta)); } } } Ant[] ants = new Ant[parameters.antsCount]; for (int i = 0; i < parameters.antsCount; i++) { ants[i] = new Ant(); } Ant bestAnt = new Ant(); for (UInt32 iteration = 0; iteration < iterations; ++iteration) { foreach (Ant ant in ants) { ant.Initialize(graph.dimension); var startNode = GetRandomUInt32(0, graph.dimension - 1); ant.Visit(startNode); for (UInt32 j = 1; j < graph.dimension; ++j) { moveAntMMAS(graph, pheromone, heuristic, ant); } ant.cost = graph.CalculateRouteLength(ant.visited); } var iterationBest = ants[0]; bool newBestFound = false; foreach (Ant ant in ants) { if (ant.cost < bestAnt.cost) { bestAnt = ant; newBestFound = true; Console.WriteLine("New best solution found with the cost: {0} at iteration {1}", bestAnt.cost, iteration); } if (ant.cost < iterationBest.cost) { iterationBest = ant; } } if (newBestFound) { var limits = CalcTrailLimitsMMAS(parameters, graph.dimension, bestAnt.cost); minPheromone = limits.Item1; maxPheromone = limits.Item2; } pheromone.EvaporateFromAll(parameters.GetEvaporationRate(), minPheromone); var updateAnt = iterationBest; double deposite = 1.0 / updateAnt.cost; var previousNode = updateAnt.visited[updateAnt.visited.Count - 1]; foreach (var node in updateAnt.visited) { pheromone.Increase(previousNode, node, deposite, maxPheromone, graph.isSymetric); previousNode = node; } } return(bestAnt); }
public static UInt32 moveAntMMAS(Graph graph, PheromoneMemory pheromone, double [] heuristic, Ant ant) { var dimension = graph.dimension; var currentNode = ant.visited[ant.visited.Count - 1]; UInt32 offset = currentNode * dimension; UInt32 [] candList = new UInt32 [MaxCandListSize]; UInt32 candListSize = 0; for (int i = 0; i < graph.dimension; i++) { if (!ant.IsVisited((UInt32)i)) { candList[candListSize] = (UInt32)i; ++candListSize; } } UInt32 chosenNode = currentNode; if (candListSize > 0) { double[] productsPrefixSum = new double[MaxCandListSize]; double total = 0; for (UInt32 j = 0; j < candListSize; ++j) { var node = candList[j]; var product = pheromone.Get(currentNode, node) * heuristic[offset + node]; total += product; productsPrefixSum[j] = total; } chosenNode = candList[candListSize - 1]; var r = GetRandomDouble() * total; for (UInt32 i = 0; i < candListSize; ++i) { if (r < productsPrefixSum[i]) { chosenNode = candList[i]; break; } } } else { double maxProduct = 0; for (UInt32 node = 0; node < dimension; ++node) { if (!ant.IsVisited(node)) { var product = pheromone.Get(currentNode, node) * heuristic[offset + node]; if (product > maxProduct) { maxProduct = product; chosenNode = node; } } } } ant.Visit(chosenNode); return(chosenNode); }