/** * Run the algorithm * * @param db Database to run on * @param relation Data relation * @return Clustering result */ public PointerHierarchyRepresentationResult run(Database db, Relation<O> relation) { if(SingleLinkage.class.isInstance(linkage)) { LOG.verbose("Notice: SLINK is a much faster algorithm for single-linkage clustering!"); } DistanceQuery<O> dq = db.getDistanceQuery(relation, getDistanceFunction()); final DBIDs ids = relation.getDBIDs(); MatrixParadigm mat = new MatrixParadigm(ids); // Compute the initial (lower triangular) distance matrix. initializeDistanceMatrix(mat, dq, linkage); // Initialize space for result: PointerHierarchyRepresentationBuilder builder = new PointerHierarchyRepresentationBuilder(ids, dq.getDistanceFunction().isSquared()); nnChainCore(mat, builder); return builder.complete(); }
/** * Execute the cluster merge. * * @param size Data set size * @param scratch Scratch space. * @param ix First iterator * @param iy Second iterator * @param builder Hierarchy builder * @param mindist Distance that was used for merging * @param x First matrix position * @param y Second matrix position */ protected void merge(int size, double[] scratch, DBIDArrayIter ix, DBIDArrayIter iy, PointerHierarchyRepresentationBuilder builder, double mindist, int x, int y) { // Avoid allocating memory, by reusing existing iterators: ix.seek(x); iy.seek(y); if(LOG.isDebuggingFine()) { LOG.debugFine("Merging: " + DBIDUtil.toString(ix) + " -> " + DBIDUtil.toString(iy) + " " + mindist); } // Perform merge in data structure: x -> y assert(y < x); // Since y < x, prefer keeping y, dropping x. builder.add(ix, mindist, iy); // Update cluster size for y: final int sizex = builder.getSize(ix), sizey = builder.getSize(iy); builder.setSize(iy, sizex + sizey); // Note: this changes iy. updateMatrix(size, scratch, iy, builder, mindist, x, y, sizex, sizey); }
if(builder.isLinked(ij.seek(j))) { continue; scratch[yb] = linkage.combine(sizex, scratch[xbase + j], sizey, scratch[yb], builder.getSize(ij), mindist); if(builder.isLinked(ij.seek(j))) { continue; scratch[jb] = linkage.combine(sizex, scratch[xbase + j], sizey, scratch[jb], builder.getSize(ij), mindist); if(builder.isLinked(ij.seek(j))) { continue; scratch[jb] = linkage.combine(sizex, scratch[jbase + x], sizey, scratch[jb], builder.getSize(ij), mindist);
PointerHierarchyRepresentationBuilder builder = new PointerHierarchyRepresentationBuilder(ids); if(x == wsize - 1) { --wsize; for(ix.seek(wsize - 1); builder.isLinked(ix); ix.retract()) { --wsize; return builder.complete();
/** * Shrink the active set: if the last x objects are all merged, we can reduce * the working size accordingly. * * @param ix Object iterator * @param builder Builder to detect merged status * @param end Current active set size * @param x Last merged object * @return New active set size */ protected static int shrinkActiveSet(DBIDArrayIter ix, PointerHierarchyRepresentationBuilder builder, int end, int x) { if(x == end - 1) { // Can truncate active set. while(builder.isLinked(ix.seek(--end - 1))) { // Everything happens in while condition already. } } return end; }
builder.add(ix, distances[offset], iy, prots.seek(offset));
PointerHierarchyRepresentationBuilder builder = new PointerHierarchyRepresentationBuilder(ids); if(x == wsize - 1) { --wsize; for(ix.seek(wsize - 1); builder.isLinked(ix); ix.retract()) { --wsize; return builder.complete();
/** * Shrink the active set: if the last x objects are all merged, we can reduce * the working size accordingly. * * @param ix Object iterator * @param builder Builder to detect merged status * @param end Current active set size * @param x Last merged object * @return New active set size */ protected static int shrinkActiveSet(DBIDArrayIter ix, PointerHierarchyRepresentationBuilder builder, int end, int x) { if(x == end - 1) { // Can truncate active set. while(builder.isLinked(ix.seek(--end - 1))) { // Everything happens in while condition already. } } return end; }
builder.add(ix, distances[offset], iy, prots.seek(offset));
/** * Execute the cluster merge. * * @param end Active set size * @param mat Matrix paradigm * @param builder Hierarchy builder * @param mindist Distance that was used for merging * @param x First matrix position * @param y Second matrix position */ protected void merge(int end, MatrixParadigm mat, PointerHierarchyRepresentationBuilder builder, double mindist, int x, int y) { // Avoid allocating memory, by reusing existing iterators: final DBIDArrayIter ix = mat.ix.seek(x), iy = mat.iy.seek(y); if(LOG.isDebuggingFine()) { LOG.debugFine("Merging: " + DBIDUtil.toString(ix) + " -> " + DBIDUtil.toString(iy) + " " + mindist); } // Perform merge in data structure: x -> y assert (y < x); // Since y < x, prefer keeping y, dropping x. builder.add(ix, linkage.restore(mindist, getDistanceFunction().isSquared()), iy); // Update cluster size for y: final int sizex = builder.getSize(ix), sizey = builder.getSize(iy); builder.setSize(iy, sizex + sizey); updateMatrix(end, mat, builder, mindist, x, y, sizex, sizey); }
/** * Run the algorithm * * @param db Database to run on * @param relation Data relation * @return Clustering result */ public PointerHierarchyRepresentationResult run(Database db, Relation<O> relation) { if(SingleLinkage.class.isInstance(linkage)) { LOG.verbose("Notice: SLINK is a much faster algorithm for single-linkage clustering!"); } DistanceQuery<O> dq = db.getDistanceQuery(relation, getDistanceFunction()); final DBIDs ids = relation.getDBIDs(); MatrixParadigm mat = new MatrixParadigm(ids); // Compute the initial (lower triangular) distance matrix. initializeDistanceMatrix(mat, dq, linkage); // Initialize space for result: PointerHierarchyRepresentationBuilder builder = new PointerHierarchyRepresentationBuilder(ids, dq.getDistanceFunction().isSquared()); nnChainCore(mat, builder); return builder.complete(); }
if(builder.isLinked(ij.seek(j))) { continue; scratch[yb] = linkage.combine(sizex, scratch[xbase + j], sizey, scratch[yb], builder.getSize(ij), mindist); if(builder.isLinked(ij.seek(j))) { continue; scratch[jb] = linkage.combine(sizex, scratch[xbase + j], sizey, scratch[jb], builder.getSize(ij), mindist); if(builder.isLinked(ij.seek(j))) { continue; scratch[jb] = linkage.combine(sizex, scratch[jbase + x], sizey, scratch[jb], builder.getSize(ij), mindist);
/** * Find an unlinked object. * * @param pos Starting position * @param end End position * @param ix Iterator to translate into DBIDs * @param builder Linkage information * @return Position */ public static int findUnlinked(int pos, int end, DBIDArrayIter ix, PointerHierarchyRepresentationBuilder builder) { while(pos < end) { if(!builder.isLinked(ix.seek(pos))) { return pos; } ++pos; } return -1; }
builder.add(ix, distances[offset], iy, prots.seek(offset));
/** * Run the algorithm * * @param db Database to run on * @param relation Data relation * @return Clustering result */ public PointerPrototypeHierarchyRepresentationResult run(Database db, Relation<O> relation) { DistanceQuery<O> dq = DatabaseUtil.precomputedDistanceQuery(db, relation, getDistanceFunction(), LOG); final DBIDs ids = relation.getDBIDs(); // Initialize space for result: PointerHierarchyRepresentationBuilder builder = new PointerHierarchyRepresentationBuilder(ids, dq.getDistanceFunction().isSquared()); Int2ObjectOpenHashMap<ModifiableDBIDs> clusters = new Int2ObjectOpenHashMap<>(ids.size()); MatrixParadigm mat = new MatrixParadigm(ids); ArrayModifiableDBIDs prots = DBIDUtil.newArray(MatrixParadigm.triangleSize(ids.size())); MiniMax.initializeMatrices(mat, prots, dq); nnChainCore(mat, prots.iter(), dq, builder, clusters); return (PointerPrototypeHierarchyRepresentationResult) builder.complete(); }
if(builder.isLinked(ij.seek(j))) { continue; final int sizej = builder.getSize(ij); final int yb = ybase + j; scratch[yb] = linkage.combine(sizex, scratch[xbase + j], sizey, scratch[yb], sizej, mindist); if(builder.isLinked(ij.seek(j))) { continue; final int sizej = builder.getSize(ij); final int jb = jbase + y; scratch[jb] = linkage.combine(sizex, scratch[xbase + j], sizey, scratch[jb], sizej, mindist); if(builder.isLinked(ij.seek(j))) { continue; final int sizej = builder.getSize(ij); scratch[jbase + y] = linkage.combine(sizex, scratch[jbase + x], sizey, scratch[jbase + y], sizej, mindist);
/** * Find an unlinked object. * * @param pos Starting position * @param end End position * @param ix Iterator to translate into DBIDs * @param builder Linkage information * @return Position */ public static int findUnlinked(int pos, int end, DBIDArrayIter ix, PointerHierarchyRepresentationBuilder builder) { while(pos < end) { if(!builder.isLinked(ix.seek(pos))) { return pos; } ++pos; } return -1; }
builder.add(ix, distances[offset], iy, prots.seek(offset));
/** * Execute the cluster merge. * * @param end Active set size * @param mat Matrix paradigm * @param builder Hierarchy builder * @param mindist Distance that was used for merging * @param x First matrix position * @param y Second matrix position */ protected void merge(int end, MatrixParadigm mat, PointerHierarchyRepresentationBuilder builder, double mindist, int x, int y) { // Avoid allocating memory, by reusing existing iterators: final DBIDArrayIter ix = mat.ix.seek(x), iy = mat.iy.seek(y); if(LOG.isDebuggingFine()) { LOG.debugFine("Merging: " + DBIDUtil.toString(ix) + " -> " + DBIDUtil.toString(iy) + " " + mindist); } // Perform merge in data structure: x -> y assert (y < x); // Since y < x, prefer keeping y, dropping x. builder.add(ix, linkage.restore(mindist, getDistanceFunction().isSquared()), iy); // Update cluster size for y: final int sizex = builder.getSize(ix), sizey = builder.getSize(iy); builder.setSize(iy, sizex + sizey); updateMatrix(end, mat, builder, mindist, x, y, sizex, sizey); }