Exemple #1
0
        public void Dequeue_Concurrently_Works()
        {
            // Arrange
            var bucket = new BucketQueue <string>(2);
            var count  = 10000;
            var range  = Enumerable.Range(0, count).ToList();

            range.ForEach(i => bucket.Enqueue(i, i.ToString()));

            var dequeuedItems = new ConcurrentBag <string>();

            // Act
            Enumerable.Range(0, 2 * count).AsParallel().ForAll(i =>
            {
                string value;
                if (bucket.TryDequeue(out value))
                {
                    dequeuedItems.Add(value);
                }
            });

            // Assert
            var rangeAsString = range.Select(x => x.ToString()).ToList();

            Assert.True(new HashSet <string>(dequeuedItems).SetEquals(rangeAsString));
        }
Exemple #2
0
        public void Dequeue_NonExistingItem_Works()
        {
            // Arrange
            var bucket = new BucketQueue <string>(1);

            // Act
            string value;
            var    result = bucket.TryDequeue(out value);

            // Assert
            Assert.That(result, Is.False);
            Assert.That(value, Is.Null);
        }
Exemple #3
0
        public void Dequeue_SingleItem_Works()
        {
            // Arrange
            var bucket = new BucketQueue <string>(1);

            bucket.Enqueue(0, "test");

            // Act
            string value;
            var    result = bucket.TryDequeue(out value);

            // Assert
            Assert.That(result, Is.True);
            Assert.That(value, Is.EqualTo("test"));
        }
Exemple #4
0
        public void Dequeue_MultipleItems_Works()
        {
            // Arrange
            var bucket = new BucketQueue <string>(2);

            bucket.Enqueue(0, "0");
            bucket.Enqueue(1, "1");
            bucket.Enqueue(2, "2");

            // Act / Assert
            string value;

            Assert.That(bucket.TryDequeue(out value), Is.True);
            Assert.That(value, Is.EqualTo("1"));
            Assert.That(bucket.TryDequeue(out value), Is.True);
            Assert.That(value, Is.EqualTo("0"));
            Assert.That(bucket.TryDequeue(out value), Is.True);
            Assert.That(value, Is.EqualTo("2"));
            Assert.That(bucket.TryDequeue(out value), Is.False);
        }
Exemple #5
0
        public void Benchmark(int buckets)
        {
            var count  = 2000000;
            var bucket = new BucketQueue <string>(buckets);
            var range  = Enumerable.Range(0, count).ToList();

            range.ForEach(i => bucket.Enqueue(i, i.ToString()));

            var sw = Stopwatch.StartNew();

            for (var i = 0; i < count; i++)
            {
                string value;
                bucket.TryDequeue(out value);
            }
            ;
            sw.Stop();

            Assert.Inconclusive("{0} ops/sec", count / sw.Elapsed.Add(TimeSpan.FromTicks(1)).TotalSeconds);
        }
Exemple #6
0
    /// <summary>
    /// The main method call for the A* search.
    /// </summary>
    /// <returns>A list of edges. edge.destination contains the world vector2 that each edge points to.</returns>
    public List <Edge> Search()
    {
        var startRecord = new NodeRecord {
            Location           = _start,
            Connection         = null,
            CostSoFar          = 0,
            EstimatedTotalCost = _heuristic.Estimate(_start)
        };

        //TODO Replace with a priority queue
        var openList   = new BucketQueue <NodeRecord>();
        var closedList = new BucketQueue <NodeRecord>();

        openList.Enqueue(startRecord, (int)startRecord.EstimatedTotalCost);

        NodeRecord current = null;

        Assert.raiseExceptions = true;
        while (openList.Count > 0)
        {
            Assert.IsFalse(openList.Count > 50000, "OpenList has an insane number of nodes");
            current = openList.Peek();

            if (openList.Count % 1000 == 0)
            {
                UnityEngine.Debug.LogWarning("<i>Pathfinding:</i> There are too many nodes in the open list. >" + openList.Count);
                //openList.LogContents();
            }
            if (closedList.Count > 0 && closedList.Count % 1000 == 0)
            {
                UnityEngine.Debug.LogWarning("<i>Pathfinding:</i> There are too many nodes in the closed list. >" + closedList.Count);
                //closedList.LogContents();
            }

            //If we're at the goal, end early
            if (current.Location.Equals(_end))
            {
                break;
            }

            //If we're far away, end early
            if ((_end - current.Location).sqrMagnitude > 500f)
            {
                //We are very far away from the destination. It's likely we won't be able to reach it.
                //Let's not waste performance.
                UnityEngine.Debug.DrawLine(_start, _end, Color.gray, 300f);
                UnityEngine.Debug.Log("<i>Pathfinding:</i> Pathfinding has reached a node that is too far away. Aborting. Distance: " + (current.Location - _end).magnitude);
                return(null);
            }

            //Otherwise, get the connections
            var        connections = GetConnections(current);
            NodeRecord endNodeRecord;
            Vector2    endLoc;
            float      endCost;
            float      endHeuristic;
            foreach (var con in connections)
            {
                endLoc  = con.Destination;
                endCost = current.CostSoFar + con.Cost;

                if (_debugMode)
                {
                    UnityEngine.Debug.DrawLine(con.From, con.Destination, Color.blue, 2, false);
                }

                //If the node is closed, we may have to skip or remove from the closed list
                if (closedList.Any(closedRecord => closedRecord.Location == endLoc))
                {
                    Assert.IsNotNull(closedList, "Closed List should not be null.");
                    Assert.IsFalse(closedList.Count == 0, "Closed List should not be empty");
                    endNodeRecord =
                        closedList.First(closedRecord => closedRecord.Location.Equals(endLoc)); //Retrieve the record we found
                    if (endNodeRecord.CostSoFar <= endCost)
                    {
                        //If this route isn't shorter, then skip.
                        continue;
                    }
                    //Otherwise, remove it from the closed list
                    closedList.Remove(endNodeRecord, (int)endNodeRecord.EstimatedTotalCost);
                    //Recalculate the heuristic. TODO: recalculate using old values
                    endHeuristic = _heuristic.Estimate(endLoc);
                }
                else if (openList.Any(openRecord => openRecord.Location == endLoc))
                {
                    //Skip if the node is open and we haven't found a better route
                    endNodeRecord = openList.First(openRecord => openRecord.Location == endLoc);

                    if (endNodeRecord.CostSoFar <= endCost)
                    {
                        continue;
                    }
                    //Recalculate the heuristic
                    endHeuristic = _heuristic.Estimate(endLoc);
                }
                else
                {
                    //Otherwise, we're on an unvisited node that needs a new record
                    endNodeRecord = new NodeRecord {
                        Location = endLoc
                    };
                    endHeuristic = _heuristic.Estimate(endLoc);
                }
                //If we reached this point, it means we need to update the node
                endNodeRecord.CostSoFar          = endCost;
                endNodeRecord.Connection         = con; //remember: we're iterating through the connections right now
                endNodeRecord.EstimatedTotalCost = endCost + endHeuristic;

                //If this record isn't in the openlist already
                if (openList.All(openRecord => openRecord.Location != endLoc))
                {
                    openList.Enqueue(endNodeRecord, (int)endNodeRecord.EstimatedTotalCost);
                }
            }
            //Finished looking at the connections, move it to the closed list.
            openList.Remove(current, (int)current.EstimatedTotalCost);
            closedList.Enqueue(current, (int)current.EstimatedTotalCost);
        }
        Assert.IsNotNull(current, "current != null");
        if (current.Location != _end)
        {
            //We're out of nodes and haven't found the goal. No solution.
            UnityEngine.Debug.DrawLine(current.Location, _end, Color.black, 200f);
            return(null);
        }
        //We found the path, time to compile a list of connections
        var outputList = new List <Edge>(20);

        while (current.Location != _start)
        {
            if (_debugMode)
            {
                UnityEngine.Debug.DrawLine(current.Connection.From, current.Connection.Destination, Color.red, 2, false);
            }
            outputList.Add(current.Connection);
            current = current.Connection.PreviousRecord;
        }
        outputList.Reverse();
        return(outputList);
    }
        private List <TreePart> SolveSimpleGraph(Dictionary <ushort, Dictionary <ushort, int> > graph, IEnumerable <ushort> solveSet, int maxSize)
        {
            BucketQueue <TreeGroup> groups = new BucketQueue <TreeGroup>();

            List <TreePart> initialParts = new List <TreePart>();
            {
                foreach (ushort node in solveSet)
                {
                    initialParts.Add(new TreePart(node));
                }
            }

            TreeGroup initialGroup = new TreeGroup(initialParts.ToArray());

            groups.Enqueue(initialGroup, initialGroup.Size);

            int generation = 0;

            HashSet <TreePart> solutions = new HashSet <TreePart>(EqualityComparer <TreePart> .Default);

            // DO WORK.
            while (!groups.IsEmpty())
            {
                generation++;
                TreeGroup group = groups.Dequeue();

                if (group.Size > maxSize)
                {
                    break;
                }

                if (generation % 100000 == 0)
                {
                    Console.WriteLine(generation + " " + group.Size);
                }

                TreePart smallest = group.Smallest;

                foreach (ushort node in smallest.Nodes.ToList())
                {
                    int remaining = maxSize - group.Size;
                    foreach (var next in graph[node])
                    {
                        if (smallest.Nodes.Contains(next.Key))
                        {
                            continue;
                        }

                        if (next.Value > remaining)
                        {
                            continue;
                        }

                        TreePart part = new TreePart(smallest);
                        Edge     edge = new Edge(node, next.Key);

                        part.Nodes.Add(next.Key);
                        part.Edges.Add(edge);
                        part.Size += next.Value;

                        TreePart  mergePart = group.Containing(next.Key);
                        TreeGroup newGroup;
                        if (mergePart != null)
                        {
                            part.merge(mergePart);

                            TreePart[] other = new TreePart[group.Parts.Length - 1];
                            int        index = 0;
                            for (int i = 0; i < group.Parts.Length; ++i)
                            {
                                if (group.Parts[i] != mergePart)
                                {
                                    other[index++] = group.Parts[i];
                                }
                            }
                            newGroup = new TreeGroup(part, other);
                        }
                        else
                        {
                            newGroup = new TreeGroup(part, group.Parts);
                        }

                        if (newGroup.Parts.Length == 0)
                        {
                            if (newGroup.Size < maxSize)
                            {
                                solutions.Clear();
                                maxSize = newGroup.Size;
                            }

                            solutions.Add(newGroup.Smallest);
                            //	groups.CapPriority(maxSize);
                            continue;
                        }

                        if (newGroup.Size >= maxSize)
                        {
                            continue;
                        }

                        groups.Enqueue(newGroup, newGroup.Size);
                    }
                }
                group.Recycle();
            }

            return(solutions.ToList());
        }