Subject: One mistake your making that can ruin your diet success

From: Know The Facts <[email-masked]>
Date: Thu, 04 Sep 2014 17:05:34 -0700

Only 1 out of 25 people answered this question correctly...

What food should you avoid if you are trying to watch your waistline?
a.) Bananas
b.) Bacon
c.) Orange Juice

You may be surprised... Watch and Learn.
Surprising Answer: http://www.sortwo.com/facebook-q-a/.vid?45346345

^
^
^
^
^
^
^
^
Facebook Quizel-101 | SZ-Team | 68 Linden St., Evereet, MA
-=- Exi-Q-updates: http://www.sortwo.com/7-34.htm

-3515044456 - 
null for testing "emptyness"
length/size for element count
elem/member for set inclusion
empty and/or singleton for default feb470acd1530eaa786a3bd95e4b9565
union for set union
(\\45)/diff for set difference
(64)/() for unsafe indexing (partial function)
(6534)/lookup for safe indexing (total function)-- 

     Console.WriteLine();
        for (int Loop = 0; Loop < FieldsPerLine; Loop++)
        {
            Rnd = rngMain.Next(LIMIT);
            Console.Write(Rnd.ToString().PadLeft(3) + " ");
        }
    }
}
The output looks like this

My use case is Branch and Bound Optimization. Expanding the candidate with the best bound is provably optimal when you're given an unlimited time. Assuming an unlimited time is provably wrong.

Strictly following this strategy often ends up with having no solution at all when the deadline comes. A simple band-aid is to direct the search towards a solution first and then switch to the best bound strategy. This is rather unsatisfactory as the first solution found can be of an arbitrary low quality.

That's why I'd like to use the two criteria queue: In one step, expand the best bound candidate and in another, expand the "best looking" candidate according to some heuristics.

Another possible use would be for pareto-optimization.

java priority-queue
share|improve this question
edited Aug 31 at 15:31

asked Aug 20 at 21:52

maaartinus
13k43997
This question has an open bounty worth +50 reputation from maaartinus ending in 3 days.
This question has not received enough attention.

9	 	
Why not create a facade backed by two PriorityQueues?   Sotirios Delimanolis Aug 20 at 21:53
  	 	
Agreed. The mechanics of a PriorityQueue rely on being able to compare to items.   Micah Smith Aug 20 at 21:55
  	 	
@SotiriosDelimanolis How would you remove the element obtained by poll1() from the second queue?   maaartinus Aug 20 at 22:12
1	 	
I guess you could have a counter of invalid references per queue. And if counter goes above specified threshold, you would just use iterator to remove them. You could use a ReadWrite lock to sync cleanups: use read lock for polling and write lock for cleanup. Atomics should work well as counters   Sami Korhonen Aug 31 at 2:05
1	 	
Sounds somewhat interesting, but I'd be curious to see how this is intended to be used (particularly, a convincing example where this makes more sense than two separate priority queues)   Marco13 Aug 31 at 14:59
show 10 more comments
5 Answers
activeoldestvotes
up vote
3
down vote
Use two TreeSets. Each set takes their respected comparator, and the add() method adds the provided value to each set. poll1() would acquire the first() value in the first set, and remove the value from both sets. Similarly for poll2().

add(), poll1() and poll2() will have (log n).

An example implementation follows (the real thing probably needs more error checking and additional methods):

class Priority2Queue <E>
{
    private TreeSet<E> q1;
    private TreeSet<E> q2;

    public Priority2Queue (Comparator<E> c1, Comparator<E> c2) {
        q1 = new TreeSet<E>(c1);
        q2 = new TreeSet<E>(c2);
    }

    public void add (E e) {
        q1.add(e);
        q2.add(e);
    }

    private E pollx (TreeSet<E> a, TreeSet<E> b) {
        E top = a.first();
        a.remove(top);
        b.remove(top);
        return top;
    }

    public E poll1 () { return pollx(q1, q2); }
    public E poll2 () { return pollx(q2, q1); }
}
share|improve this answer
edited 2 days ago

answered Aug 31 at 15:11

jxh
34.5k62459
  	 	
+1 This is simple and sure to work, but pretty wasteful as a TreeSet takes much more memory and probably also time than a heap.   maaartinus 47 mins ago
  	 	
@maaartinus: I picked a data structure that would provide the correct big-O behavior. If your queue sizes are relatively small, two priority queues are probably sufficient. If you expect your queues to be very large, consider using a B+Tree implementation instead of TreeSet.   jxh 25 mins ago 
add a comment

up vote
2
down vote
Use two priority queues.

One way to do this is tag an item for deletion when it's next in one's poll. If the other queue sees it, skip and move to next. I'm not sure the complexity of this, but it will depend on subtle questions such as how much longer one item remains in a queue than the other. I would suggest profiling for your actual situation.

share|improve this answer
edited Aug 31 at 12:49

answered Aug 31 at 12:36

djechlin
18.9k73698
  	 	
+1 This is good, except for one thing, namely possible accumulation of already consumed things in one of the queues (as you noted). It may work well and profiling is no bad idea, but it can't tell me what happens for other inputs.   maaartinus 44 mins ago
add a comment
up vote
2
down vote
If you care only about asymptotic complexity, i would go with @jxh's solution, which uses O(n) memory and guaranteed time O(log(n)) per operation (that is the best possible) and requires very little coding.

However TreeSet is backed by TreeMap and that uses TreeEntry for entries, and one entry will take total 32B of memory, plus having 2 trees will result into 64B of memory per element

EDIT: After some investigation, the following data structure doesn't seem as promising anymore, since the add() method will fail in some cases. I will leave there as it is, if somebody finds a fix, either leave a comment or edit the answer. (end of edit)

However with custom modification of Binary Heap you can get by with a single array of references, resulting into 4B per object, which is 16 times less than with the tree sets, and time per operation is still guaranteed O(log(n)).

The modification is rather simple: with two comparators (call them C1 and C2):

Each element on an odd floor (floor = height from the top) has to be lower or equal to all elements below it according to comparator C1
Similarly, each element on an even floor has to be lower or equal to all elements below it according to comparator C2
Now let's say that the root is at floor 1. Let's start with peek1() (read the minimum element according to C1) that is simply the root. For peek2(), we need to check the root and it's direct 2 children, but among these 3, the minimum according to C2 must be.

The add() operation will be a bit more difficult, make sure you understand the add in regular heap first.

Add the new element at the first unused position as usual.
Check if it is greater or equal to the element 2 floors above according to that element's comparator. If it is, do nothing. If not, swap these 2 elements.
Check if the element at the inserting position if greater or equal to it's parent according to parent's floor's comparator. If it is, do nothing. If not, swap these 2 elements.
If swapping was made in point 2, repeat from point 1 as if the swapped element was newly inserted. Else if swapping was made in point 3, do the same. Else work is done.