/// <summary> /// Initializes the solver so that the optimization can be run. /// </summary> /// <exception cref="InvalidOperationException"> /// If not all target nodes are connected to the start node. /// </exception> public void Initialize() { BuildSearchGraph(); _searchSpace = _searchGraph.NodeDict.Values.Where(n => IncludeNode(n) && n != StartNodes && !TargetNodes.Contains(n)) .ToList(); var consideredNodes = SearchSpace.Concat(TargetNodes).ToList(); consideredNodes.Add(StartNodes); Distances.CalculateFully(consideredNodes); if (_targetNodes.Any(node => !Distances.AreConnected(StartNodes, node))) { throw new InvalidOperationException("The graph is disconnected."); } // Saving the leastSolution as initial solution. Makes sure there is always a // solution even if the search space is empty or MaxGeneration is 0. BestSolution = SpannedMstToSkillnodes(CreateLeastSolution()); var removedNodes = new List <GraphNode>(); var newSearchSpace = new List <GraphNode>(); foreach (var node in SearchSpace) { if (IncludeNodeUsingDistances(node)) { newSearchSpace.Add(node); } else { removedNodes.Add(node); } } _searchSpace = newSearchSpace; var remainingNodes = SearchSpace.Concat(TargetNodes).ToList(); remainingNodes.Add(StartNodes); Distances.RemoveNodes(removedNodes, remainingNodes); if (_targetNodes.Count / (double)remainingNodes.Count >= PreFilledSpanThreshold) { var prioQueue = new LinkedListPriorityQueue <LinkedGraphEdge>(100); for (var i = 0; i < remainingNodes.Count; i++) { for (var j = i + 1; j < remainingNodes.Count; j++) { prioQueue.Enqueue(new LinkedGraphEdge(i, j), Distances[i, j]); } } _firstEdge = prioQueue.First; } InitializeGa(); _isInitialized = true; }