Index: voting/src/main/java/geniusweb/voting/CollectedVotes.java
===================================================================
--- voting/src/main/java/geniusweb/voting/CollectedVotes.java	(revision 27)
+++ voting/src/main/java/geniusweb/voting/CollectedVotes.java	(revision 28)
@@ -2,8 +2,11 @@
 
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.PriorityQueue;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import geniusweb.actions.PartyId;
@@ -137,4 +140,58 @@
 
 	/**
+	 * Breath-first optimized search, similar as {@link #getMaxPowerGroup(Set)}
+	 * but more efficient on average (remains to be proven). Notice that this
+	 * algorithm may be more expensive particularly if there is no consensus at
+	 * all, because of the added overhead of the breath-first search
+	 * 
+	 * @param allvotes a list of all votes for a particular bid.
+	 * @return a consensus-group with maximum power, so there is no other
+	 *         consensus group that has more power (but there may be other
+	 *         groups with same power). returns empty set if no consensus found
+	 */
+	protected Set<PartyId> getMaxPowerGroupBreathFirst(Set<Vote> allvotes) {
+		/**
+		 * queue that keeps the options for the breath-first search sorted from
+		 * highest to lowest power of the voters.
+		 */
+		PriorityQueue<Set<Vote>> queue = new PriorityQueue<>(
+				new Comparator<Set<Vote>>() {
+					@Override
+					public int compare(Set<Vote> vs1, Set<Vote> vs2) {
+						Set<PartyId> parties1 = vs1.stream()
+								.map(vote -> vote.getActor())
+								.collect(Collectors.toSet());
+						Set<PartyId> parties2 = vs2.stream()
+								.map(vote -> vote.getActor())
+								.collect(Collectors.toSet());
+						return getTotalPower(parties1)
+								.compareTo(getTotalPower(parties2));
+					}
+				});
+		queue.add(allvotes);
+
+		while (!queue.isEmpty()) {
+			// try one with the highest power
+			Set<Vote> vs = queue.poll();
+			if (isViable(vs))
+				return getParties(vs);
+			if (vs.size() > 1) {
+				// vote can be splitted. push all new subsets
+				for (Vote vote : vs) {
+					Set<Vote> subvotes = new HashSet<>(vs);
+					subvotes.remove(vote);
+					// avoid duplicate work. Since this has a removed party,
+					// and assuming power of each party >=1,
+					// we can not already have checked subvotes
+					if (!queue.contains(subvotes))
+						queue.add(subvotes);
+				}
+			}
+
+		}
+		return Collections.emptySet();
+	}
+
+	/**
 	 * 
 	 * @param votes a list of all votes for a particular bid. The parties that
@@ -142,5 +199,5 @@
 	 * @return a consensus-group with maximum power, so there is no other
 	 *         consensus group that has more power (but there may be other
-	 *         groups with same power).
+	 *         groups with same power). returns empty set if no consensus found
 	 */
 	protected Set<PartyId> getMaxPowerGroup(Set<Vote> votes) {
@@ -179,13 +236,24 @@
 				new FixedList<Vote>(votes));
 		// check each possible subset.
+		// TODO stream this
 		for (ImmutableList<Vote> voteList : allVotePermutations) {
-			Set<PartyId> parties = getParties(voteList);
-			Integer totalpower = getTotalPower(parties);
-			if (parties.size() >= 2 && totalpower >= getMinPower(voteList)
-					&& totalpower <= getMaxPower(voteList)) {
-				groups.add(parties);
+			if (isViable(voteList)) {
+				groups.add(getParties(voteList));
 			}
 		}
 		return groups;
+	}
+
+	/**
+	 * 
+	 * @param voteList a list of votes for a single bid.
+	 * @return true if this votelist satisfies the requirements of all
+	 *         participants and there are &ge; 2 parties
+	 */
+	private boolean isViable(Iterable<Vote> voteList) {
+		Set<PartyId> parties = getParties(voteList);
+		Integer totalpower = getTotalPower(parties);
+		return parties.size() >= 2 && totalpower >= getMinPower(voteList)
+				&& totalpower <= getMaxPower(voteList);
 	}
 
@@ -194,5 +262,5 @@
 	 * @return all parties that did a vote
 	 */
-	public static Set<PartyId> getParties(ImmutableList<Vote> voteList) {
+	public static Set<PartyId> getParties(Iterable<Vote> voteList) {
 		Set<PartyId> parties = new HashSet<>();
 		for (Vote vote : voteList) {
@@ -209,5 +277,5 @@
 	 *         accept. This is equal to the max of the vote.getMinPower
 	 */
-	private Integer getMinPower(ImmutableList<Vote> votes) {
+	private Integer getMinPower(Iterable<Vote> votes) {
 		int max = 0;
 		for (Vote vote : votes) {
@@ -224,5 +292,5 @@
 	 *         accept. This is equal to the min of the vote.getMaxPower
 	 */
-	private Integer getMaxPower(ImmutableList<Vote> votes) {
+	private Integer getMaxPower(Iterable<Vote> votes) {
 		int min = Integer.MAX_VALUE;
 		for (Vote vote : votes) {
