Beispiel #1
0
        // Copied from PriorityQueueTest, to ensure consistency.
        private void CheckOrder <TData>(AlternativePriorityQueue <int, TData> q, int nodesToKeep = 0, bool reversed = false)
        {
            int  curr  = 0;
            bool first = true;

            while (q.Count > nodesToKeep)
            {
                int next = q.Dequeue().Priority;
                Console.WriteLine(next);
                if (!first)
                {
                    int comparison = next.CompareTo(curr);
                    if (reversed)
                    {
                        Assert.LessOrEqual(comparison, 0);
                    }
                    else
                    {
                        Assert.GreaterOrEqual(comparison, 0);
                    }
                }

                first = false;
                curr  = next;
            }
        }
Beispiel #2
0
        public void TestOrderRandom1()
        {
            var q = new AlternativePriorityQueue <int, int>();

            addRandomItems(q, 100);
            CheckOrder(q);
        }
Beispiel #3
0
        public void TestDifferentComparer()
        {
            IComparer <int> comparer = new BackwardsInt32Comparer();
            var             q        = new AlternativePriorityQueue <int, int>(comparer);

            addRandomItems(q, 15);
            CheckOrder(q, reversed: true);
        }
Beispiel #4
0
        public void TestOrder1()
        {
            var q = new AlternativePriorityQueue <int, int>();

            q.Enqueue(new PriorityQueueNode <int, int>(1), 1);
            q.Enqueue(new PriorityQueueNode <int, int>(10), 10);
            q.Enqueue(new PriorityQueueNode <int, int>(5), 5);
            q.Enqueue(new PriorityQueueNode <int, int>(8), 8);
            q.Enqueue(new PriorityQueueNode <int, int>(-1), -1);
            CheckOrder(q);
        }
Beispiel #5
0
        // Copied from PriorityQueueTest, to ensure consistency.
        private void addRandomItems <TData>(AlternativePriorityQueue <int, TData> q, int num)
        {
            var random = new Random();

            for (int i = 0; i < num; i++)
            {
                // This usually inserts lots of duplicate values in an order
                // that *tends* to be increasing, but usually has some values
                // that should bubble up near the top of the heap.
                int priority = (int)(num * random.NextDouble());

                q.Enqueue(new PriorityQueueNode <int, TData>(default(TData)), priority);
            }
        }
Beispiel #6
0
        public void TestLongSequenceOfOperations()
        {
            var q = new AlternativePriorityQueue <int, int>();

            addRandomItems(q, 15);
            CheckOrder(q, nodesToKeep: 3);
            addRandomItems(q, 33);
            CheckOrder(q);
            q.Clear();
            addRandomItems(q, 13);
            q.ChangePriority(q.Head, 6);
            q.ChangePriority(q.Head, 7);
            q.ChangePriority(q.Head, 8);
            CheckOrder(q, nodesToKeep: 0);
        }
Beispiel #7
0
        public void TestCopiedQueue()
        {
            var q1 = new AlternativePriorityQueue <int, int>();

            addRandomItems(q1, 178);
            var q2 = new AlternativePriorityQueue <int, int>(q1);

            addRandomItems(q2, 28);
            CheckOrder(q1, nodesToKeep: 42);
            addRandomItems(q1, 39);
            CheckOrder(q2, nodesToKeep: 2);
            addRandomItems(q2, 18);

            CheckOrder(q1);
            CheckOrder(q2);
        }
Beispiel #8
0
        public void TestEnumeration()
        {
            const int NodeCount = 18;
            var       q         = new AlternativePriorityQueue <double, object>(NodeCount);

            var random = new Random();
            var nodes  = new PriorityQueueNode <double, object> [NodeCount];

            for (int i = 0; i < NodeCount; i++)
            {
                nodes[i] = new PriorityQueueNode <double, object>((object)null);
                q.Enqueue(nodes[i], random.NextDouble());
            }

            CollectionAssert.AreEquivalent(nodes, q);
        }
Beispiel #9
0
        public void TestContainsConsistency()
        {
            var q = new AlternativePriorityQueue <int, int>();

            addRandomItems(q, 150);

            var missingNode = new PriorityQueueNode <int, int>(14);
            var presentNode = new PriorityQueueNode <int, int>(14);

            q.Enqueue(presentNode, 75);

            Assert.True(q.Contains(presentNode));
            Assert.False(q.Contains(missingNode));

            q.Remove(presentNode);
            Assert.False(q.Contains(presentNode));
            CheckOrder(q);
        }
Beispiel #10
0
        public Coordinate[] Simplify()
        {
            // Put every coordinate index into an AlternativePriorityQueueNode.
            // this array doubles as a way to check which coordinates are
            // excluded.
            var nodes = new PriorityQueueNode <IndexWithArea, int> [_pts.Length];

            // Store the coordinates, with their effective areas, in a min heap.
            // Visvalingam-Whyatt repeatedly deletes the coordinate with the
            // min effective area so a structure with efficient delete-min is
            // ideal.
            var queue = new AlternativePriorityQueue <IndexWithArea, int>(_pts.Length);

            // First and last coordinates are included automatically.
            for (int i = 1; i < _pts.Length - 1; i++)
            {
                double area = Triangle.Area(_pts[i - 1], _pts[i], _pts[i + 1]);

                nodes[i] = new PriorityQueueNode <IndexWithArea, int>(i);
                queue.Enqueue(nodes[i], new IndexWithArea(i, area));
            }

            // First = the coord that contributes the minimum effective area.
            while (queue.Head != null &&
                   queue.Head.Priority.Area <= _tolerance)
            {
                var node = queue.Dequeue();

                // Signal that this node has been deleted.
                nodes[node.Data] = null;

                // Find index of the not-yet-deleted coord before the deleted
                // one.  This could be the first coord in the sequence.
                int prev = node.Data - 1;
                while (prev > 0 && nodes[prev] == null)
                {
                    --prev;
                }

                // Find index of the not-yet-deleted coord after the deleted
                // one.  This could be the last coord in the sequence.
                int next = node.Data + 1;
                while (next < _pts.Length - 1 && nodes[next] == null)
                {
                    ++next;
                }

                // If the previous coord is not the first one, then its
                // effective area has changed.  For example:
                // 0  1  2  3  4
                //       ^--------- delete this
                // 0  1     3  4
                // 1's effective area was based on the "0 1 2" triangle.
                // Now, it should be based on the "0 1 3" triangle.
                // This means we take the triangle of curr-2, curr-1, curr+1.
                if (prev > 0 &&
                    queue.Contains(nodes[prev]))
                {
                    int prev2 = prev - 1;
                    while (prev2 > 0 && nodes[prev2] == null)
                    {
                        --prev2;
                    }

                    double area = Triangle.Area(_pts[prev2], _pts[prev], _pts[next]);
                    queue.ChangePriority(nodes[prev], new IndexWithArea(prev, area));
                }

                // Same idea as what we did above for prev.
                // 3's effective area was based on the "2 3 4" triangle.
                // Now, it should be based on the "1 3 4" triangle.
                // This means we take the triangle of curr-1, curr+1, curr+2.
                if (next < _pts.Length - 1 &&
                    queue.Contains(nodes[next]))
                {
                    int next2 = next + 1;
                    while (next2 < _pts.Length - 1 && nodes[next2] == null)
                    {
                        ++next2;
                    }

                    double area = Triangle.Area(_pts[prev], _pts[next], _pts[next2]);
                    queue.ChangePriority(nodes[next], new IndexWithArea(next, area));
                }
            }

            // Consolidate the results.  For consistency, and because it's a
            // good idea anyway, we want to make sure we don't output the same
            // coord multiple times in a row, so we pass "false" for the second
            // parameter to "Add".
            var list = new CoordinateList();

            list.Add(_pts[0], false);
            for (int i = 0; i < nodes.Length; i++)
            {
                if (nodes[i] == null)
                {
                    // This was one we deleted.
                    continue;
                }

                list.Add(_pts[i], false);
            }

            // Special-case: we want to make sure that we don't return a 1-
            // element array, as the outputs of this are typically used to
            // build an LineString.  So if there's just one coordinate, we
            // output it twice, mainly just to ensure equivalence to JTS / old
            // NTS.
            list.Add(_pts[_pts.Length - 1], list.Count == 1);

            return(list.ToArray());
        }