docs: public Clustering<Model> run(Database database, Relation<NumberVector> relation) {
      Clustering<Model> ret = new Clustering<>("LMCLUS Clustering", "lmclus-clustering");
      FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Clustered objects", relation.size(), LOG) : null;
      IndefiniteProgress cprogress = LOG.isVerbose() ? new IndefiniteProgress("Clusters found", LOG) : null;
      ModifiableDBIDs unclustered = DBIDUtil.newHashSet(relation.getDBIDs());
      Random r = rnd.getSingleThreadedRandom();
  
      final int maxdim = Math.min(maxLMDim, RelationUtil.dimensionality(relation));
      int cnum = 0;
      while(unclustered.size() > minsize) {
        DBIDs current = unclustered;
        int lmDim = 1;
        for(int k = 1; k <= maxdim; k++) {
          // Implementation note: this while loop is from the original publication
          // and the published LMCLUS source code. It doesn't make sense to me -
          // it is lacking a stop criterion other than "cluster is too small" and
          // "cluster is inseparable"! Additionally, there is good criterion for
          // stopping at the appropriate dimensionality either.
          while(true) {
            Separation separation = findSeparation(relation, current, k, r);
            // logger.verbose("k: " + k + " goodness: " + separation.goodness +
            // " threshold: " + separation.threshold);
            if(separation.goodness <= sensitivityThreshold) {
              break;
            }
            ModifiableDBIDs subset = DBIDUtil.newArray(current.size());
            for(DBIDIter iter = current.iter(); iter.valid(); iter.advance()) {
              if(deviation(minusEquals(relation.get(iter).toArray(), separation.originV), separation.basis) < separation.threshold) {
                subset.add(iter);
              }
            }
            // logger.verbose("size:"+subset.size());
            if(subset.size() < minsize) {
              break;
            }
            current = subset;
            lmDim = k;
            // System.out.println("Partition: " + subset.size());
          }
        }
        // No more clusters found
        if(current.size() < minsize || current == unclustered) {
          break;
        }
        // New cluster found
        // TODO: annotate cluster with dimensionality
        final Cluster<Model> cluster = new Cluster<>(current);
        cluster.setName("Cluster_" + lmDim + "d_" + cnum);
        cnum++;
        ret.addToplevelCluster(cluster);
        // Remove from main working set.
        unclustered.removeDBIDs(current);
        if(progress != null) {
          progress.setProcessed(relation.size() - unclustered.size(), LOG);
        }
        if(cprogress != null) {
          cprogress.setProcessed(cnum, LOG);
        }
      }
      // Remaining objects are noise
      if(unclustered.size() > 0) {
        ret.addToplevelCluster(new Cluster<>(unclustered, true));
      }
      if(progress != null) {
        progress.setProcessed(relation.size(), LOG);
        progress.ensureCompleted(LOG);
      }
      LOG.setCompleted(cprogress);
      return ret;
    }