protected override void OnUpdate()
    {
        int2 gridSize = new int2(WorldManager.MapWorld.regionSize, WorldManager.MapWorld.regionSize);

        NativeList <JobHandle> jobHandles = new NativeList <JobHandle>(Allocator.Temp);

        Entities.ForEach((Entity entity, DynamicBuffer <PathfindingRoute> pathRoute, ref PathfindingParams pathfindingParams) => {
            List <MapGrowth> mapGrowths        = WorldManager.MapWorld.GetMapGrowths(pathfindingParams.growthCode);
            NativeArray <int2> targetLocations = new NativeArray <int2>(GetAllTargetsFromGrowth(mapGrowths), Allocator.TempJob);

            PathFinderJob pathfinderJob = new PathFinderJob {
                pathfindingType = pathfindingParams.pathfindingType,
                positionStart   = pathfindingParams.startPosition,
                positionEnd     = pathfindingParams.endPosition,
                gridSize        = gridSize,
                entity          = entity,
                routeFollow     = GetComponentDataFromEntity <PathfindingRouteFollow>(),
                pathRoute       = pathRoute,
                pathNodes       = WorldManager.PathNodesNA,
                targets         = targetLocations
            };

            jobHandles.Add(pathfinderJob.Schedule());

            PostUpdateCommands.RemoveComponent <PathfindingParams>(entity);
        });

        JobHandle.CompleteAll(jobHandles);
    }
Example #2
0
        private async Task <IEnumerable <byte[]> > GetUniqueNodeCountsAsync(Shape shape)
        {
            const int ThreadCount = 1;

            var tableau = shape.CreateTableau();

            var terminalNodePairs = tableau.TerminalNodeUniqueCombinations()
                                    .GroupBy(nodePair => (TerminalNode)nodePair.Node1)
                                    .Select(grp => (
                                                startNode: grp.Key,
                                                endNodes: grp.Select(node => (TerminalNode)node.Node2).ToList()))
                                    .ToList();

            var jobSpecs = terminalNodePairs.Select(nodePair =>
                                                    new PathFinderJobSpec
            {
                Tableau     = tableau,
                Name        = nodePair.startNode.Index.ToString(),
                StartPoint  = nodePair.startNode,
                EndPoints   = nodePair.endNodes.ToList(),
                ThreadCount = ThreadCount
            }).ToList();

            var combinedNodeCounts = new Dictionary <byte[], int>(new ByteSequenceEqualEqualityComparer());
            var tokenSource        = new CancellationTokenSource();
            var tasks = new List <Task <(IDictionary <byte[], int>, PathFinderState)> >();

            foreach (var jobSpec in jobSpecs)
            {
                var pathFinderJob = new PathFinderJob(jobSpec);

                var pathFinderState = new PathFinderState
                {
                    Name     = jobSpec.Name,
                    Steps    = jobSpec.StartPoint.Links.Select(link => new Step(link.Value, link.Key)).ToList(),
                    Progress = new Progress()
                };

                tasks.Add(pathFinderJob.ExploreAsync(pathFinderState, tokenSource.Token));
            }

            await Task.WhenAll(tasks);

            foreach (var task in tasks)
            {
                var(nodeCounts, pathFinderState) = task.Result;

                foreach (var nodeCount in nodeCounts)
                {
                    if (!combinedNodeCounts.TryAdd(nodeCount.Key, nodeCount.Value))
                    {
                        combinedNodeCounts[nodeCount.Key] += nodeCount.Value;
                    }
                }
            }

            return(combinedNodeCounts
                   .Where(kv => kv.Value == 1)
                   .Select(kv => kv.Key));
        }
Example #3
0
    void Start()
    {
        float startTime = Time.realtimeSinceStartup;

        int findPathJobCount = 5;
        NativeArray <JobHandle> jobHandleArray = new NativeArray <JobHandle>(findPathJobCount, Allocator.TempJob);

        for (int i = 0; i < findPathJobCount; i++)
        {
            PathFinderJob pathJob = new PathFinderJob {
                positionStart = new int2(0, 0),
                positionEnd   = new int2(1023, 1023),
                gridSize      = new int2(1024, 1024)
            };
            jobHandleArray[i] = pathJob.Schedule();
            Debug.Log("Creating Job Time: " + ((Time.realtimeSinceStartup - startTime) * 1000f));
        }

        JobHandle.CompleteAll(jobHandleArray);
        Debug.Log("Total Time: " + ((Time.realtimeSinceStartup - startTime) * 1000f));
        jobHandleArray.Dispose();
    }
Example #4
0
        public static async Task Main(string[] args)
        {
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));

            if (!Directory.Exists(Configuration.FolderName))
            {
                Directory.CreateDirectory(Configuration.FolderName);
            }

            var shape           = GetShape(args);
            var tableau         = shape.CreateTableau();
            var concurrency     = GetConcurrency(args);
            var persistInterval = GetPersistInterval(args);

            var terminalNodePairs = tableau.TerminalNodeUniqueCombinations()
                                    .GroupBy(nodePair => (TerminalNode)nodePair.Node1)
                                    .Select(grp => (
                                                startNode: grp.Key,
                                                endNodes: grp.Select(node => (TerminalNode)node.Node2).ToList()))
                                    .ToList();

            foreach (var(startNode, endNodes) in terminalNodePairs)
            {
                Trace.WriteLine($"{startNode.Index}: {string.Join(", ", endNodes.Select(node => node.Index))}");
            }

            var jobs = new List <(PathFinderJob, PathFinderState)>();

            foreach (var(startNode, endNodes) in terminalNodePairs)
            {
                var jobAdded = false;
                var jobSpec  = new PathFinderJobSpec
                {
                    Name            = startNode.Index.ToString(),
                    Tableau         = tableau,
                    StartPoint      = startNode,
                    EndPoints       = endNodes,
                    ThreadCount     = concurrency,
                    MonitorInterval = persistInterval
                };

                if (persistInterval > TimeSpan.Zero)
                {
                    var saveFilePath = Configuration.Filename(shape, jobSpec.Name);
                    Trace.WriteLine($"Save file path: {saveFilePath}");

                    if (File.Exists(saveFilePath))
                    {
                        var savedState = RouteStateReaderWriter.ReadFromFile(saveFilePath);

                        if (savedState.Shape != shape.Name)
                        {
                            throw new Exception($"The shape {savedState.Shape} specfied in file '{saveFilePath}' does not match the expected value {shape.Name}.");
                        }

                        if (savedState.Size != shape.Size)
                        {
                            throw new Exception($"The size {savedState.Size} specfied in file '{saveFilePath}' does not match the expected value {shape.Size}.");
                        }

                        var endPoints = savedState.TerminalNodes
                                        .Select(index => tableau.TerminalNodes[index])
                                        .ToList();

                        var steps = new List <Step>();
                        var queue = new Queue <(Step step, int id)>();
                        var items = savedState.Steps.Where(x => x.PreviousId == 0).ToList();

                        foreach (var item in items)
                        {
                            var step = new Step(
                                node: tableau.Nodes[item.Position],
                                direction: new Direction(item.Direction));

                            queue.Enqueue((step, item.Id));
                        }

                        while (queue.Any())
                        {
                            var(previousStep, id) = queue.Dequeue();
                            items = savedState.Steps.Where(x => x.PreviousId == id).ToList();

                            if (items.Count == 0)
                            {
                                steps.Add(previousStep);
                                continue;
                            }

                            foreach (var item in items)
                            {
                                var direction = new Direction(item.Direction);
                                var twist     = direction - previousStep.Direction;

                                var step = new Step(
                                    node: tableau.Nodes[item.Position],
                                    direction: direction,
                                    twist: twist,
                                    previous: previousStep);

                                queue.Enqueue((step, item.Id));
                            }
                        }

                        var pathFinderJob   = new PathFinderJob(jobSpec); //TODO: paths
                        var pathFinderState = new PathFinderState
                        {
                            Name     = jobSpec.Name,
                            Steps    = steps,
                            Progress = savedState.Progress
                        };

                        jobs.Add((pathFinderJob, pathFinderState));
                        jobAdded = true;
                    }
                }

                if (!jobAdded)
                {
                    var pathFinderJob   = new PathFinderJob(jobSpec);
                    var pathFinderState = new PathFinderState
                    {
                        Name     = jobSpec.Name,
                        Steps    = startNode.Links.Select(link => new Step(link.Value, link.Key)).ToList(),
                        Progress = new Progress()
                    };

                    jobs.Add((pathFinderJob, pathFinderState));
                }
            }

            var tokenSource = new CancellationTokenSource();
            var tasks       = new List <Task <(IDictionary <byte[], int>, PathFinderState)> >();

            foreach (var(pathFinderJob, pathFinderState) in jobs)
            {
                tasks.Add(pathFinderJob.ExploreAsync(pathFinderState, tokenSource.Token));
            }

            await Task.WhenAll(tasks);

            var combinedElapsedTime = TimeSpan.Zero;
            var combinedRouteCount  = 0L;

            var combinedNodeCounts = new Dictionary <byte[], int>(new ByteSequenceEqualEqualityComparer());

            foreach (var task in tasks)
            {
                var(nodeCounts, pathFinderState) = task.Result;

                foreach (var nodeCount in nodeCounts)
                {
                    if (!combinedNodeCounts.ContainsKey(nodeCount.Key))
                    {
                        combinedNodeCounts.Add(nodeCount.Key, 0);
                    }

                    combinedNodeCounts[nodeCount.Key] += nodeCount.Value;
                }

                var uniqueSolutionCount = nodeCounts.Count(item => item.Value == 1);

                combinedRouteCount += pathFinderState.Progress.RouteCount;
                if (pathFinderState.Progress.ElapsedTime > combinedElapsedTime)
                {
                    combinedElapsedTime = pathFinderState.Progress.ElapsedTime;
                }

                Trace.WriteLine($"Result for job {pathFinderState.Name}: routes = {pathFinderState.Progress.RouteCount}, distinct solutions = {nodeCounts.Count}, unique solutions = {uniqueSolutionCount}, elapsed time = {pathFinderState.Progress.ElapsedTime}");
            }

            var combinedUniqueSolutionCount = combinedNodeCounts.Count(item => item.Value == 1);

            Trace.WriteLine($"Overall result: routes = {combinedRouteCount}, distinct solutions = {combinedNodeCounts.Count}, unique solutions = {combinedUniqueSolutionCount}, elapsed time = {combinedElapsedTime}");
        }