Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Priority not persisted after enqueuing #63

Open
daleao opened this issue May 14, 2024 · 1 comment
Open

Priority not persisted after enqueuing #63

daleao opened this issue May 14, 2024 · 1 comment

Comments

@daleao
Copy link

daleao commented May 14, 2024

I'm using a SimplePriorityQueue<TItem, TPriority>, where TItem : GenericPriorityQueueNode<TPriority> and TPriority : IComparable<TPriority>; i.e., my Node class is derived from GenericPriorityQueueNode and uses a custom struct as the priority.

The prioritization seems to work correctly. But immediately after calling .Enqueue(item, priority), the Priority property of the queued item iis set to the default value, instead of the value priority which was passed to Enqueue.

Have I misunderstood how to use these objects? I'm implementing D* and was hoping to get the Key value from the Priority property.

Minimal working example (included the whole Key struct in case it's important):

public readonly struct Key(float k1, float k2) : IComparable<Key>
{
    public readonly float K1 = k1;
    public readonly float K2 = k2;

    public static bool operator <(Key left, Key right) => left.K1 < right.K1 || (left.K1 == right.K1 && left.K2 < right.K2);
    public static bool operator >(Key left, Key right) => left.K1 > right.K1 || (left.K1 == right.K1 && left.K2 > right.K2);
    public static bool operator ==(Key left, Key right) => left.K1 == right.K1 && left.K2 == right.K2;
    public static bool operator !=(Key left, Key right) => !(left == right);

    public int CompareTo(Key other)
    {
        return this < other ? -1 : this > other ? 1 : 0;
    }

    public override bool Equals(object? @object)
    {
        return @object is Key key && this == key;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(this.K1, this.K2);
    }

    public override string ToString()
    {
        return $"{this.K1}, {this.K2}";
    }
}

public sealed class Node : GenericPriorityQueueNode<Key>
{
    public Node() { }
}

class Program
{
    static void Main()
    {
        var queue = new SimplePriorityQueue<Node, Key>();
        queue.Enqueue(new Node(), new Key(1, 1));
        // inspect the queue here and notice that item 0 has Priority = Key {0, 0};
    }
}
@BlueRaja
Copy link
Owner

I'm not able to reproduce this issue. Specifically, I added this unit test, which passes

       public readonly struct TestKey : IComparable<TestKey>
       {
           public readonly float Key1;
           public readonly float Key2;

           public TestKey(float key1, float key2)
           {
               Key1 = key1;
               Key2 = key2;
           }

           public static bool operator <(TestKey left, TestKey right) => left.Key1 < right.Key1 || (left.Key1 == right.Key1 && left.Key2 < right.Key2);
           public static bool operator >(TestKey left, TestKey right) => left.Key1 > right.Key1 || (left.Key1 == right.Key1 && left.Key2 > right.Key2);
           public static bool operator ==(TestKey left, TestKey right) => left.Key1 == right.Key1 && left.Key2 == right.Key2;
           public static bool operator !=(TestKey left, TestKey right) => !(left == right);

           public int CompareTo(TestKey other)
           {
               return this < other ? -1 : this > other ? 1 : 0;
           }

           public override bool Equals(object @object)
           {
               return @object is TestKey key && this == key;
           }

           public override int GetHashCode()
           {
               return Key1.GetHashCode() ^ Key2.GetHashCode();
           }

           public override string ToString()
           {
               return $"{this.Key1}, {this.Key2}";
           }
       }

       public sealed class TestNode : GenericPriorityQueueNode<TestKey>
       {
           public TestNode() { }
       }

       [Test]
       public void TestQueueWithCustomKey()
       {
           TestNode node1 = new TestNode();
           TestNode node2 = new TestNode();
           TestNode node3 = new TestNode();
           TestKey key1 = new TestKey(1, 0);
           TestKey key2 = new TestKey(2, 0);
           TestKey key3 = new TestKey(3, 0);

           SimplePriorityQueue<TestNode, TestKey> queue = new SimplePriorityQueue<TestNode, TestKey>();
           queue.Enqueue(node3, key3);
           queue.Enqueue(node1, key1);
           queue.Enqueue(node2, key2);

           Assert.IsTrue(queue.IsValidQueue());
           Assert.AreEqual(key1, queue.GetPriority(node1));
           Assert.AreEqual(key2, queue.GetPriority(node2));
           Assert.AreEqual(key3, queue.GetPriority(node3));

           Assert.AreEqual(node1, queue.Dequeue());
           Assert.AreEqual(node2, queue.Dequeue());
           Assert.AreEqual(node3, queue.Dequeue());
       }

Less importantly, using a custom node class that extends GenericPriorityQueueNode shouldn't be necessary with SimplePriorityQueue. It won't hurt anything, it's just unnecessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants