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)); }
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); }
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")); }
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); }
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); }
/// <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()); }