/// <summary>
        /// Calculates the TSP.
        /// </summary>
        /// <param name="operation">The operation request.</param>
        /// <param name="router">The router.</param>
        /// <param name="matcher">Contains an algorithm to match points to the route network.</param>
        /// <param name="open">Flag indicating the type of TSP problem, open or not.</param>
        /// <returns></returns>
        private RoutingResponse DoTSP(
            RoutingOperation operation, Router<SimpleWeighedEdge> router, IEdgeMatcher matcher, bool open)
        {
            // create the response.
            var response = new RoutingResponse();

            // resolve the points and do the routing.
            var hooksPerRouterPoints = new Dictionary<RouterPoint, List<RoutingHook>>();
            var routerPoints = new List<RouterPoint>();
            var unroutableHooks = new List<RoutingHook>(); // save the unroutable hooks.
            for (int idx = 0; idx < operation.Hooks.Length; idx++)
            {
                // routing hook tags.
                IDictionary<string, string> tags = operation.Hooks[idx].Tags.ConvertToDictionary();

                // resolve the point.
                RouterPoint routerPoint = router.Resolve(operation.Vehicle, new GeoCoordinate(
                    operation.Hooks[idx].Latitude, operation.Hooks[idx].Longitude), matcher, tags);

                // check the result.
                if (routerPoint == null)
                { // this hook is not routable.
                    unroutableHooks.Add(operation.Hooks[idx]);
                }
                else
                { // a point to hook on was found!
                    List<RoutingHook> hooksAtPoint;
                    if (!hooksPerRouterPoints.TryGetValue(routerPoint, out hooksAtPoint))
                    { // the router point does not exist yet.
                        // check if the router point is routable.
                        if (router.CheckConnectivity(operation.Vehicle, routerPoint, 200))
                        {// the point is routable.
                            // create the hooks list at this point.
                            hooksAtPoint = new List<RoutingHook>();
                            hooksPerRouterPoints.Add(routerPoint, hooksAtPoint);

                            // add the new router point to the list.
                            routerPoint.Tags.Add(new KeyValuePair<string, string>("id", routerPoints.Count.ToString(
                                System.Globalization.CultureInfo.InvariantCulture)));
                            routerPoints.Add(routerPoint);

                            // add the hook.
                            hooksAtPoint.Add(operation.Hooks[idx]);
                        }
                        else
                        {// this hook is not routable.
                            unroutableHooks.Add(operation.Hooks[idx]);
                        }
                    }
                    else
                    {
                        // add the hook.
                        hooksAtPoint.Add(operation.Hooks[idx]);
                    }
                }
            }

            // add the unroutable hooks.
            response.UnroutableHooks = unroutableHooks.ToArray();

            // calculate all the weights.
            double[][] weights = router.CalculateManyToManyWeight(operation.Vehicle, routerPoints.ToArray(), routerPoints.ToArray());

            // calculate the TSP.
            var tspSolver = new RouterTSPAEXGenetic(300, 100);
            IRoute tspRoute = tspSolver.CalculateTSP(weights, routerPoints.Select(x => x.Location).ToArray(), 0, !open);

            // calculate the actual route.
            OsmSharpRoute route = null;
            foreach (Edge edge in tspRoute.Edges())
            {
                // calculate the actual edge-route.
                OsmSharpRoute edgeRoute = router.Calculate(operation.Vehicle,
                                                            routerPoints[edge.From], routerPoints[edge.To]);

                // add the routing hook tags.
                List<RoutingHook> fromHooks = hooksPerRouterPoints[routerPoints[edge.From]];
                edgeRoute.Entries[0].Points = new RoutePoint[fromHooks.Count];
                for (int hookIdx = 0; hookIdx < fromHooks.Count; hookIdx++)
                {
                    var hookPoint = new RoutePoint
                                        {
                                            Latitude = fromHooks[hookIdx].Latitude,
                                            Longitude = fromHooks[hookIdx].Longitude,
                                            Tags = fromHooks[hookIdx].Tags.ConvertToList().ConvertFrom()
                                        };

                    edgeRoute.Entries[0].Points[hookIdx] = hookPoint;
                }
                List<RoutingHook> toHooks = hooksPerRouterPoints[routerPoints[edge.To]];
                edgeRoute.Entries[edgeRoute.Entries.Length - 1].Points = new RoutePoint[toHooks.Count];
                for (int hookIdx = 0; hookIdx < toHooks.Count; hookIdx++)
                {
                    var hookPoint = new RoutePoint
                                        {
                                            Latitude = toHooks[hookIdx].Latitude,
                                            Longitude = toHooks[hookIdx].Longitude,
                                            Tags = toHooks[hookIdx].Tags.ConvertToList().ConvertFrom()
                                        };

                    edgeRoute.Entries[edgeRoute.Entries.Length - 1].Points[hookIdx] = hookPoint;
                }

                // concatenate routes.
                if (route == null)
                {
                    route = edgeRoute;
                }
                else
                {
                    route = OsmSharpRoute.Concatenate(route, edgeRoute);
                }
            }

            response.Route = route;

            // set the response as successfull.
            response.Status = OsmSharpServiceResponseStatusEnum.Success;

            return response;
        }
        /// <summary>
        /// Calculates a matrix of weights between all given points.
        /// </summary>
        /// <param name="operation">The operation request.</param>
        /// <param name="router">The router.</param>
        /// <param name="matcher">Contains an algorithm to match points to the route network.</param>
        /// <returns></returns>
        private RoutingResponse DoManyToMany(
            RoutingOperation operation, Router<SimpleWeighedEdge> router, IEdgeMatcher matcher)
        {
            // create the response.
            var response = new RoutingResponse();

            // resolve the points and do the routing.
            var routerPoints = new List<RouterPoint>();
            var unroutableHooks = new List<RoutingHook>(); // save the unroutable hooks.
            for (int idx = 0; idx < operation.Hooks.Length; idx++)
            {
                // routing hook tags.
                IDictionary<string, string> tags = operation.Hooks[idx].Tags.ConvertToDictionary();

                // resolve the point.
                RouterPoint routerPoint = router.Resolve(operation.Vehicle, new GeoCoordinate(
                    operation.Hooks[idx].Latitude, operation.Hooks[idx].Longitude), matcher, tags);

                // check the result.
                if (routerPoint == null)
                {
                    // this hook is not routable.
                    unroutableHooks.Add(operation.Hooks[idx]);
                }
                else
                {
                    // a point to hook on was found!
                    // check if the router point is routable.
                    if (router.CheckConnectivity(operation.Vehicle, routerPoint, 200))
                    {
                        // the point is routable.

                        // add the new router point to the list.
                        routerPoint.Tags.Add(new KeyValuePair<string, string>("id", routerPoints.Count.ToString(
                            System.Globalization.CultureInfo.InvariantCulture)));
                        routerPoints.Add(routerPoint);
                    }
                    else
                    {
                        // this hook is not routable.
                        unroutableHooks.Add(operation.Hooks[idx]);
                    }
                }
            }

            // add the unroutable hooks.
            response.UnroutableHooks = unroutableHooks.ToArray();

            // calculate and fill the response.
            response.Weights = router.CalculateManyToManyWeight(operation.Vehicle, routerPoints.ToArray(),
                routerPoints.ToArray());

            // report succes!
            response.Status = OsmSharpServiceResponseStatusEnum.Success;
            response.StatusMessage = string.Empty;

            return response;
        }