Example usage for com.google.common.collect MinMaxPriorityQueue add

List of usage examples for com.google.common.collect MinMaxPriorityQueue add

Introduction

In this page you can find the example usage for com.google.common.collect MinMaxPriorityQueue add.

Prototype

@Override
public boolean add(E element) 

Source Link

Document

Adds the given element to this queue.

Usage

From source file:it.uniroma3.mat.extendedset.intset.ImmutableSecompaxSet.java

private static ImmutableSecompaxSet doUnion(Iterator<ImmutableSecompaxSet> iterator) {
    IntList retVal = new IntList();

    // lhs = current word position, rhs = the iterator
    // Comparison is first by index, then one fills > literals > zero fills
    // one fills are sorted by length (longer one fills have priority)
    // similarily, shorter zero fills have priority
    MinMaxPriorityQueue<WordHolder> theQ = MinMaxPriorityQueue.orderedBy(new Comparator<WordHolder>() {
        @Override/*from w ww .j a va 2 s . c om*/
        public int compare(WordHolder h1, WordHolder h2) {
            int w1 = h1.getWord();
            int w2 = h2.getWord();
            int s1 = h1.getIterator().startIndex;
            int s2 = h2.getIterator().startIndex;

            if (s1 != s2) {
                return compareInts(s1, s2);
            }

            if (ConciseSetUtils.is1_fill(w1)) {
                if (ConciseSetUtils.is1_fill(w2)) {
                    return -compareInts(ConciseSetUtils.getSequenceNumWords(w1),
                            ConciseSetUtils.getSequenceNumWords(w2));
                }
                return -1;
            } else if (ConciseSetUtils.isLiteral(w1)) {
                if (ConciseSetUtils.is1_fill(w2)) {
                    return 1;
                } else if (ConciseSetUtils.isLiteral(w2)) {
                    return 0;
                }
                return -1;
            } else {
                if (!ConciseSetUtils.is0_fill(w2)) {
                    return 1;
                }
                return compareInts(ConciseSetUtils.getSequenceNumWords(w1),
                        ConciseSetUtils.getSequenceNumWords(w2));
            }
        }
    }).create();

    // populate priority queue
    while (iterator.hasNext()) {
        ImmutableSecompaxSet set = iterator.next();

        if (set != null && !set.isEmpty()) {
            WordIterator itr = set.newWordIterator();
            theQ.add(new WordHolder(itr.next(), itr));
        }
    }

    int currIndex = 0;

    while (!theQ.isEmpty()) {
        // create a temp list to hold everything that will get pushed back into the priority queue after each run
        List<WordHolder> wordsToAdd = Lists.newArrayList();

        // grab the top element from the priority queue
        WordHolder curr = theQ.poll();
        int word = curr.getWord();
        WordIterator itr = curr.getIterator();

        // if the next word in the queue starts at a different point than where we ended off we need to create a zero gap
        // to fill the space
        if (currIndex < itr.startIndex) {
            addAndCompact(retVal, itr.startIndex - currIndex);
            currIndex = itr.startIndex;
        }

        if (ConciseSetUtils.is1_fill(word)) {
            // extract a literal from the flip bits of the one sequence
            //int flipBitLiteral = ConciseSetUtils.getLiteralFromOneSeqFlipBit(word);

            // advance everything past the longest ones sequence
            WordHolder nextVal = theQ.peek();
            while (nextVal != null && nextVal.getIterator().startIndex < itr.wordsWalked) {
                WordHolder entry = theQ.poll();
                int w = entry.getWord();
                WordIterator i = entry.getIterator();

                /*if (i.startIndex == itr.startIndex) {
                  // if a literal was created from a flip bit, OR it with other literals or literals from flip bits in the same
                  // position
                  if (ConciseSetUtils.isOneSequence(w)) {
                    flipBitLiteral |= ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
                  } else if (ConciseSetUtils.isLiteral(w)) {
                    flipBitLiteral |= w;
                  } else {
                    flipBitLiteral |= ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
                  }
                }*/

                i.advanceTo(itr.wordsWalked);
                if (i.hasNext()) {
                    wordsToAdd.add(new WordHolder(i.next(), i));
                }
                nextVal = theQ.peek();
            }

            // advance longest one literal forward and push result back to priority queue
            // if a flip bit is still needed, put it in the correct position
            /*int newWord = word & 0xC1FFFFFF;
            if (flipBitLiteral != ConciseSetUtils.ALL_ONES_LITERAL) {
              flipBitLiteral ^= ConciseSetUtils.ALL_ONES_LITERAL;
              int position = Integer.numberOfTrailingZeros(flipBitLiteral) + 1;
              newWord |= (position << 25);
            }*/
            addAndCompact(retVal, word);
            currIndex = itr.wordsWalked;

            if (itr.hasNext()) {
                wordsToAdd.add(new WordHolder(itr.next(), itr));
            }
        } else if (ConciseSetUtils.isLiteral(word)) {
            // advance all other literals
            WordHolder nextVal = theQ.peek();
            while (nextVal != null && nextVal.getIterator().startIndex == itr.startIndex) {

                WordHolder entry = theQ.poll();
                int w = entry.getWord();
                WordIterator i = entry.getIterator();

                // if we still have zero fills with flipped bits, OR them here
                if (ConciseSetUtils.isLiteral(w)) {
                    word |= w;
                    if (word == 0xffffffff)
                        word = 0x10000001;
                } else {
                    /*int flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
                    if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
                      word |= flipBitLiteral;
                      i.advanceTo(itr.wordsWalked);
                    }*/
                    if (ConciseSetUtils.is1_fill(w)) {
                        word = 0x10000001;
                        i.advanceTo(itr.wordsWalked);
                    }
                }

                if (i.hasNext()) {
                    wordsToAdd.add(new WordHolder(i.next(), i));
                }

                nextVal = theQ.peek();
            }

            // advance the set with the current literal forward and push result back to priority queue
            addAndCompact(retVal, word);
            currIndex++;

            if (itr.hasNext()) {
                wordsToAdd.add(new WordHolder(itr.next(), itr));
            }
        } else { // zero fills
            WordHolder nextVal = theQ.peek();

            while (nextVal != null && nextVal.getIterator().startIndex == itr.startIndex) {
                // check if literal can be created flip bits of other zero sequences
                WordHolder entry = theQ.poll();
                int w = entry.getWord();
                WordIterator i = entry.getIterator();

                if (i.hasNext()) {
                    wordsToAdd.add(new WordHolder(i.next(), i));
                }
                nextVal = theQ.peek();
            }

            // check if a literal needs to be created from the flipped bits of this sequence
            if (itr.hasNext()) {
                wordsToAdd.add(new WordHolder(itr.next(), itr));
            }

        }

        theQ.addAll(wordsToAdd);
    }

    if (retVal.isEmpty()) {
        return new ImmutableSecompaxSet();
    }
    return new ImmutableSecompaxSet(IntBuffer.wrap(retVal.toArray()));
}

From source file:it.uniroma3.mat.extendedset.intset.ImmutableSecompaxSet.java

public static ImmutableSecompaxSet doIntersection(Iterator<ImmutableSecompaxSet> sets) {
    IntList retVal = new IntList();

    // lhs = current word position, rhs = the iterator
    // Comparison is first by index, then zero fills > literals > one fills
    // zero fills are sorted by length (longer zero fills have priority)
    // similarily, shorter one fills have priority
    MinMaxPriorityQueue<WordHolder> theQ = MinMaxPriorityQueue.orderedBy(new Comparator<WordHolder>() {
        @Override//w ww .ja  va2s.  co m
        public int compare(WordHolder h1, WordHolder h2) {
            int w1 = h1.getWord();
            int w2 = h2.getWord();
            int s1 = h1.getIterator().startIndex;
            int s2 = h2.getIterator().startIndex;

            if (s1 != s2) {
                return compareInts(s1, s2);
            }

            if (ConciseSetUtils.is0_fill(w1)) {
                if (ConciseSetUtils.is0_fill(w2)) {
                    return -compareInts(ConciseSetUtils.getSequenceNumWords(w1),
                            ConciseSetUtils.getSequenceNumWords(w2));
                }
                return -1;
            } else if (ConciseSetUtils.isLiteral(w1)) {
                if (ConciseSetUtils.is0_fill(w2)) {
                    return 1;
                } else if (ConciseSetUtils.isLiteral(w2)) {
                    return 0;
                }
                return -1;
            } else {
                if (!ConciseSetUtils.is1_fill(w2)) {
                    return 1;
                }
                return compareInts(ConciseSetUtils.getSequenceNumWords(w1),
                        ConciseSetUtils.getSequenceNumWords(w2));
            }
        }
    }).create();

    // populate priority queue
    while (sets.hasNext()) {
        ImmutableSecompaxSet set = sets.next();

        if (set == null || set.isEmpty()) {
            return new ImmutableSecompaxSet();
        }

        WordIterator itr = set.newWordIterator();
        theQ.add(new WordHolder(itr.next(), itr));
    }

    int currIndex = 0;
    int wordsWalkedAtSequenceEnd = Integer.MAX_VALUE;

    while (!theQ.isEmpty()) {
        // create a temp list to hold everything that will get pushed back into the priority queue after each run
        List<WordHolder> wordsToAdd = Lists.newArrayList();

        // grab the top element from the priority queue
        WordHolder curr = theQ.poll();
        int word = curr.getWord();
        WordIterator itr = curr.getIterator();

        // if a sequence has ended, we can break out because of Boolean logic
        if (itr.startIndex >= wordsWalkedAtSequenceEnd) {
            break;
        }

        // if the next word in the queue starts at a different point than where we ended off we need to create a one gap
        // to fill the space
        if (currIndex < itr.startIndex) {
            // number of 31 bit blocks that compromise the fill minus one
            addAndCompact(retVal, (0x10000000 | (itr.startIndex - currIndex)));
            currIndex = itr.startIndex;
        }

        if (ConciseSetUtils.is0_fill(word)) {
            // extract a literal from the flip bits of the zero sequence
            //int flipBitLiteral = ConciseSetUtils.getLiteralFromZeroSeqFlipBit(word);

            // advance everything past the longest zero sequence
            WordHolder nextVal = theQ.peek();
            while (nextVal != null && nextVal.getIterator().startIndex < itr.wordsWalked) {
                WordHolder entry = theQ.poll();
                int w = entry.getWord();
                WordIterator i = entry.getIterator();

                /*if (i.startIndex == itr.startIndex) {
                  // if a literal was created from a flip bit, AND it with other literals or literals from flip bits in the same
                  // position
                  if (ConciseSetUtils.isZeroSequence(w)) {
                    flipBitLiteral &= ConciseSetUtils.getLiteralFromZeroSeqFlipBit(w);
                  } else if (ConciseSetUtils.isLiteral(w)) {
                    flipBitLiteral &= w;
                  } else {
                    flipBitLiteral &= ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
                  }
                }*/

                i.advanceTo(itr.wordsWalked);
                if (i.hasNext()) {
                    wordsToAdd.add(new WordHolder(i.next(), i));
                } else {
                    wordsWalkedAtSequenceEnd = Math.min(i.wordsWalked, wordsWalkedAtSequenceEnd);
                }
                nextVal = theQ.peek();
            }

            // advance longest zero literal forward and push result back to priority queue
            // if a flip bit is still needed, put it in the correct position
            //int newWord = word & 0xC1FFFFFF;
            /*if (flipBitLiteral != ConciseSetUtils.ALL_ZEROS_LITERAL) {
              int position = Integer.numberOfTrailingZeros(flipBitLiteral) + 1;
              newWord = (word & 0xC1FFFFFF) | (position << 25);
            }*/
            addAndCompact(retVal, word);
            currIndex = itr.wordsWalked;

            if (itr.hasNext()) {
                wordsToAdd.add(new WordHolder(itr.next(), itr));
            } else {
                wordsWalkedAtSequenceEnd = Math.min(itr.wordsWalked, wordsWalkedAtSequenceEnd);
            }
        } else if (ConciseSetUtils.isLiteral(word)) {
            // advance all other literals
            WordHolder nextVal = theQ.peek();
            while (nextVal != null && nextVal.getIterator().startIndex == itr.startIndex) {

                WordHolder entry = theQ.poll();
                int w = entry.getWord();
                WordIterator i = entry.getIterator();

                // if we still have one fills with flipped bits, AND them here
                if (ConciseSetUtils.isLiteral(w)) {
                    word &= w;
                } else {
                    /*int flipBitLiteral = ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
                    if (flipBitLiteral != ConciseSetUtils.ALL_ONES_LITERAL) {
                      word &= flipBitLiteral;
                      i.advanceTo(itr.wordsWalked);
                    }*/
                    if (ConciseSetUtils.is0_fill(w)) {
                        word = 0x00000001;
                        i.advanceTo(itr.wordsWalked);
                    } else {
                        i.advanceTo(itr.wordsWalked);
                    }
                }

                if (i.hasNext()) {
                    wordsToAdd.add(new WordHolder(i.next(), i));
                } else {
                    wordsWalkedAtSequenceEnd = Math.min(i.wordsWalked, wordsWalkedAtSequenceEnd);
                }

                nextVal = theQ.peek();
            }

            // advance the set with the current literal forward and push result back to priority queue
            addAndCompact(retVal, word);
            currIndex++;

            if (itr.hasNext()) {
                wordsToAdd.add(new WordHolder(itr.next(), itr));
            } else {
                wordsWalkedAtSequenceEnd = Math.min(itr.wordsWalked, wordsWalkedAtSequenceEnd);
            }
        } else { // one fills
            //int flipBitLiteral;
            WordHolder nextVal = theQ.peek();

            while (nextVal != null && nextVal.getIterator().startIndex == itr.startIndex) {
                // check if literal can be created flip bits of other one sequences
                WordHolder entry = theQ.poll();
                int w = entry.getWord();
                WordIterator i = entry.getIterator();
                i.advanceTo(itr.wordsWalked);
                /*flipBitLiteral = ConciseSetUtils.getLiteralFromOneSeqFlipBit(w);
                if (flipBitLiteral != ConciseSetUtils.ALL_ONES_LITERAL) {
                  wordsToAdd.add(new WordHolder(flipBitLiteral, i));
                } else */if (i.hasNext()) {
                    wordsToAdd.add(new WordHolder(i.next(), i));
                } else {
                    wordsWalkedAtSequenceEnd = Math.min(i.wordsWalked, wordsWalkedAtSequenceEnd);
                }

                nextVal = theQ.peek();
            }

            // check if a literal needs to be created from the flipped bits of this sequence
            //flipBitLiteral = ConciseSetUtils.getLiteralFromOneSeqFlipBit(word);
            /*if (flipBitLiteral != ConciseSetUtils.ALL_ONES_LITERAL) {
              wordsToAdd.add(new WordHolder(flipBitLiteral, itr));
            } else */if (itr.hasNext()) {
                wordsToAdd.add(new WordHolder(itr.next(), itr));
            } else {
                wordsWalkedAtSequenceEnd = Math.min(itr.wordsWalked, wordsWalkedAtSequenceEnd);
            }
        }

        theQ.addAll(wordsToAdd);
    }

    // fill in any missing one sequences
    if (currIndex < wordsWalkedAtSequenceEnd) {
        addAndCompact(retVal, (0x10000000 | (wordsWalkedAtSequenceEnd - currIndex)));
    }

    if (retVal.isEmpty()) {
        return new ImmutableSecompaxSet();
    }
    return new ImmutableSecompaxSet(IntBuffer.wrap(retVal.toArray()));
}

From source file:com.linkedin.pinot.controller.helix.core.relocation.RealtimeSegmentRelocator.java

/**
 * Given the instanceStateMap and a list of consuming and completed servers for a realtime resource,
 * creates a new instanceStateMap, where one replica's instance is replaced from a consuming server to a completed server
 * @param instanceStateMap/*  w  w w .j  a  v  a2s .c o  m*/
 * @param consumingServers
 * @param completedServersQueue
 * @return
 */
private Map<String, String> createNewInstanceStateMap(Map<String, String> instanceStateMap,
        List<String> consumingServers, MinMaxPriorityQueue<Map.Entry<String, Integer>> completedServersQueue) {

    Map<String, String> newInstanceStateMap = null;

    // proceed only if all segments are ONLINE, and at least 1 server is from consuming list
    for (String state : instanceStateMap.values()) {
        if (!state.equals(PinotHelixSegmentOnlineOfflineStateModelGenerator.ONLINE_STATE)) {
            return newInstanceStateMap;
        }
    }

    for (String instance : instanceStateMap.keySet()) {
        if (consumingServers.contains(instance)) {
            // Decide best strategy to pick completed server.
            // 1. pick random from list of completed servers
            // 2. pick completed server with minimum segments, based on ideal state of this resource
            // 3. pick completed server with minimum segment, based on ideal state of all resources in this tenant
            // 4. use SegmentAssignmentStrategy

            // TODO: Using 2 for now. We should use 4. However the current interface and implementations cannot be used as is.
            // We should refactor the SegmentAssignmentStrategy interface suitably and reuse it here

            Map.Entry<String, Integer> chosenServer = null;
            List<Map.Entry<String, Integer>> polledServers = new ArrayList<>(1);
            while (!completedServersQueue.isEmpty()) {
                Map.Entry<String, Integer> server = completedServersQueue.pollFirst();
                if (instanceStateMap.keySet().contains(server.getKey())) {
                    polledServers.add(server);
                } else {
                    chosenServer = server;
                    break;
                }
            }
            completedServersQueue.addAll(polledServers);
            if (chosenServer == null) {
                throw new IllegalStateException("Could not find server to relocate segment");
            }

            newInstanceStateMap = new HashMap<>(instanceStateMap.size());
            newInstanceStateMap.putAll(instanceStateMap);
            newInstanceStateMap.remove(instance);
            newInstanceStateMap.put(chosenServer.getKey(),
                    PinotHelixSegmentOnlineOfflineStateModelGenerator.ONLINE_STATE);

            chosenServer.setValue(chosenServer.getValue() + 1);
            completedServersQueue.add(chosenServer);
            break;
        }
    }
    return newInstanceStateMap;
}

From source file:org.sosy_lab.ccvisu.clustering.ClustererMinDistPerc.java

@Override
protected List<Group> internalCreateClustersOfLayout() throws InterruptedException {
    Stopwatch stopwatch = Stopwatch.createAndStart();

    List<Group> clusters = new ArrayList<Group>();
    List<GraphVertex> vertices = graphData.getVertices();

    ///*w  w  w. ja  v  a 2s .  c o  m*/
    //
    // Initially put each node in a separate cluster.
    //
    setProgress(0, vertices.size(), "Creating initial clusters.");

    double minX = Double.MAX_VALUE;
    double minY = Double.MAX_VALUE;
    double minZ = Double.MAX_VALUE;

    double maxX = Double.MIN_VALUE;
    double maxY = Double.MIN_VALUE;
    double maxZ = Double.MIN_VALUE;

    int clusterSeqNo = 0;
    for (GraphVertex vertex : vertices) {
        Group vertexCluster = new Group("Cluster " + clusterSeqNo++, graphData);
        vertexCluster.setKind(GroupKind.CLUSTER);
        vertexCluster.addNode(vertex);
        clusters.add(vertexCluster);

        maxX = Math.max(maxX, vertex.getPosition().x);
        maxY = Math.max(maxY, vertex.getPosition().y);
        maxZ = Math.max(maxZ, vertex.getPosition().z);

        minX = Math.min(minX, vertex.getPosition().x);
        minY = Math.min(minY, vertex.getPosition().y);
        minZ = Math.min(minZ, vertex.getPosition().z);
    }

    //
    //
    // Calculate the diagonal of the layout.
    //
    double layoutDistanceX = Math.abs(maxX - minX);
    double layoutDistanceY = Math.abs(maxY - minY);
    double layoutDistanceZ = Math.abs(maxZ - minZ);

    double layoutDiagonal = Math.sqrt(layoutDistanceX * layoutDistanceX + layoutDistanceZ * layoutDistanceZ
            + layoutDistanceY * layoutDistanceY);

    //
    //
    // Calculate the parameters.
    //
    int initialNumOfClusters = clusters.size();
    int numberOfClustersWithNodes = initialNumOfClusters;
    double maxDistanceToAutoMerge = layoutDiagonal * maxDistancePercentToAutoMerge;
    double minClusterDistanceAbsoulte = layoutDiagonal * minClusterDistancePercent;

    //
    //
    // Aggregate cluster until there are only k clusters left.
    //
    int iterationNumber = 0;
    int mergesInIteration = 0;

    do {
        iterationNumber++;
        mergesInIteration = 0;

        HashMap<Group, RadiusOfGroup> fixedBarycenters = new HashMap<Group, RadiusOfGroup>();

        setProgress(initialNumOfClusters - numberOfClustersWithNodes, initialNumOfClusters,
                "Creating clusters");
        System.out.println("Num of non-empty clusters: " + numberOfClustersWithNodes);

        // Calculate the distance between all clusters.
        // Merge clusters if their distance is less than lMaxDistanceToAutoMerge.
        MinMaxPriorityQueue<ClusterPair> nearestPairs = MinMaxPriorityQueue.maximumSize(100).create();

        int highestClusterWithRadius = -1;
        for (int a = clusters.size() - 1; a >= 0; a--) {
            Group clusterA = clusters.get(a);
            if (clusterA.getNodes().size() > 0) {
                RadiusOfGroup barycenterA = null;

                if (a > highestClusterWithRadius) {
                    fixedBarycenters.put(clusterA, new RadiusOfGroup(clusterA.getNodes()));
                    highestClusterWithRadius = a;
                } else {
                    barycenterA = fixedBarycenters.get(clusterA);
                }

                if (Thread.interrupted()) {
                    throw new InterruptedException();
                }

                for (int b = a - 1; b >= 0; b--) {
                    Group clusterB = clusters.get(b);
                    if (clusterB.getNodes().size() > 0) {
                        RadiusOfGroup barycenterB = null;
                        if (b > highestClusterWithRadius) {
                            fixedBarycenters.put(clusterB, new RadiusOfGroup(clusterB.getNodes()));
                            highestClusterWithRadius = b;
                        } else {
                            barycenterB = fixedBarycenters.get(clusterB);
                        }

                        ClusterPair clusterPair = new ClusterPair(clusterA, clusterB, barycenterA, barycenterB);
                        double pairDistance = clusterPair.getEucDistanceBetweenBarycenters();

                        // First stage merging:
                        //    Merge clusters without recalculating the distances to the
                        //    merged clusters.
                        // * Only merge clusters having a distance less than...

                        if (pairDistance <= minClusterDistanceAbsoulte) {
                            if (pairDistance < maxDistanceToAutoMerge) {
                                if (numberOfClustersWithNodes > numberOfClusters) {
                                    mergeClusters(clusterB, clusterA);
                                    mergesInIteration++;
                                    numberOfClustersWithNodes--;
                                }
                            } else {
                                nearestPairs.add(clusterPair);
                            }
                        }
                    }
                }
            }
        }

        int mergesIndSecondPhase = 0;
        double nearestPairDistance = -1;

        do {
            if (numberOfClustersWithNodes > numberOfClusters) {
                ClusterPair pair = nearestPairs.poll();
                if (pair != null) {
                    double pairDistance = pair.getEucDistanceBetweenBarycenters();
                    if (nearestPairDistance == -1) {
                        nearestPairDistance = pairDistance;
                    }

                    if (mergesIndSecondPhase == 0 || ((pairDistance / nearestPairDistance) - 1 <= 0.01)) {

                        Group sourceGroup = pair.clusterA;
                        Group targetGroup = pair.clusterB;
                        if (targetGroup.getNodes().size() == 0) {
                            sourceGroup = pair.clusterB;
                            targetGroup = pair.clusterA;
                        }

                        if (sourceGroup.getNodes().size() > 0 && targetGroup.getNodes().size() > 0) {
                            if (numberOfClustersWithNodes > numberOfClusters) {
                                mergeClusters(sourceGroup, targetGroup);
                                numberOfClustersWithNodes--;
                                mergesInIteration++;
                                mergesIndSecondPhase++;
                            }
                        }

                    } else {
                        break;
                    }
                } else {
                    break;
                }
            } else {
                break;
            }
        } while (true);

        // More merging of clusters necessary?
        System.out.println(String.format("%d merges in iteration %d", mergesInIteration, iterationNumber));

    } while (mergesInIteration > 0);

    for (int i = clusters.size() - 1; i > 0; i--) {
        Group group = clusters.get(i);
        if (group.getNodes().size() == 0) {
            clusters.remove(i);
        } else {
            System.out.println(String.format("%s with %d nodes.", group.getName(), group.getNodes().size()));
        }
    }

    setProgress(1, 1, stopwatch.stop().toString());

    return clusters;
}