use of de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair in project elki by elki-project.
the class GreeneSplit method split.
@Override
public <E extends SpatialComparable, A> long[] split(A entries, ArrayAdapter<E, A> getter, int minEntries) {
final int num = getter.size(entries);
// Choose axis by best normalized separation
int axis = -1;
{
// PickSeeds - find the two most distant rectangles
double worst = Double.NEGATIVE_INFINITY;
int w1 = 0, w2 = 0;
// Compute individual areas
double[] areas = new double[num];
for (int e1 = 0; e1 < num - 1; e1++) {
final E e1i = getter.get(entries, e1);
areas[e1] = SpatialUtil.volume(e1i);
}
// Compute area increase
for (int e1 = 0; e1 < num - 1; e1++) {
final E e1i = getter.get(entries, e1);
for (int e2 = e1 + 1; e2 < num; e2++) {
final E e2i = getter.get(entries, e2);
final double areaJ = SpatialUtil.volumeUnion(e1i, e2i);
final double d = areaJ - areas[e1] - areas[e2];
if (d > worst) {
worst = d;
w1 = e1;
w2 = e2;
}
}
}
if (worst > 0) {
// Data to keep
// Initial mbrs and areas
E m1 = getter.get(entries, w1);
E m2 = getter.get(entries, w2);
double bestsep = Double.NEGATIVE_INFINITY;
double bestsep2 = Double.NEGATIVE_INFINITY;
for (int d = 0; d < m1.getDimensionality(); d++) {
final double s1 = m1.getMin(d) - m2.getMax(d);
final double s2 = m2.getMin(d) - m1.getMax(d);
final double sm = Math.max(s1, s2);
final double no = Math.max(m1.getMax(d), m2.getMax(d)) - Math.min(m1.getMin(d), m2.getMin(d));
final double sep = sm / no;
if (sep > bestsep || (sep == bestsep && sm > bestsep2)) {
bestsep = sep;
bestsep2 = sm;
axis = d;
}
}
} else {
// All objects are identical!
final int half = (num + 1) >> 1;
// Put the first half into second node
return BitsUtil.ones(half);
}
}
// Sort by minimum value
DoubleIntPair[] data = new DoubleIntPair[num];
for (int i = 0; i < num; i++) {
data[i] = new DoubleIntPair(getter.get(entries, i).getMin(axis), i);
}
Arrays.sort(data);
// Object assignment
final long[] assignment = BitsUtil.zero(num);
final int half = (num + 1) >> 1;
// Put the first half into second node
for (int i = 0; i < half; i++) {
BitsUtil.setI(assignment, data[i].second);
}
// Tie handling
if (num % 2 == 0) {
// We need to compute the bounding boxes
ModifiableHyperBoundingBox mbr1 = new ModifiableHyperBoundingBox(getter.get(entries, data[0].second));
for (int i = 1; i < half; i++) {
mbr1.extend(getter.get(entries, data[i].second));
}
ModifiableHyperBoundingBox mbr2 = new ModifiableHyperBoundingBox(getter.get(entries, data[num - 1].second));
for (int i = half + 1; i < num - 1; i++) {
mbr2.extend(getter.get(entries, data[i].second));
}
E e = getter.get(entries, data[half].second);
double inc1 = SpatialUtil.volumeUnion(mbr1, e) - SpatialUtil.volume(mbr1);
double inc2 = SpatialUtil.volumeUnion(mbr2, e) - SpatialUtil.volume(mbr2);
if (inc1 < inc2) {
BitsUtil.setI(assignment, data[half].second);
}
}
return assignment;
}
use of de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair in project elki by elki-project.
the class ApproximativeLeastOverlapInsertionStrategy method choose.
@Override
public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) {
final int size = getter.size(options);
assert (size > 0) : "Choose from empty set?";
if (size <= numCandidates) {
// Skip building the heap.
return super.choose(options, getter, obj, height, depth);
}
// Heap of candidates
TopBoundedHeap<DoubleIntPair> candidates = new TopBoundedHeap<>(numCandidates, Collections.reverseOrder());
for (int i = 0; i < size; i++) {
// Existing object and extended rectangle:
SpatialComparable entry = getter.get(options, i);
HyperBoundingBox mbr = SpatialUtil.union(entry, obj);
// Area increase
final double inc_area = SpatialUtil.volume(mbr) - SpatialUtil.volume(entry);
candidates.add(new DoubleIntPair(inc_area, i));
}
// R*-Tree: overlap increase for leaves.
int best = -1;
double least_overlap = Double.POSITIVE_INFINITY;
double least_areainc = Double.POSITIVE_INFINITY;
double least_area = Double.POSITIVE_INFINITY;
// least overlap increase, on reduced candidate set:
while (!candidates.isEmpty()) {
DoubleIntPair pair = candidates.poll();
final double inc_area = pair.first;
// Existing object and extended rectangle:
SpatialComparable entry = getter.get(options, pair.second);
HyperBoundingBox mbr = SpatialUtil.union(entry, obj);
// Compute relative overlap increase.
double overlap_wout = 0.0;
double overlap_with = 0.0;
for (int k = 0; k < size; k++) {
if (pair.second != k) {
SpatialComparable other = getter.get(options, k);
overlap_wout += SpatialUtil.relativeOverlap(entry, other);
overlap_with += SpatialUtil.relativeOverlap(mbr, other);
}
}
double inc_overlap = overlap_with - overlap_wout;
if (inc_overlap < least_overlap) {
final double area = SpatialUtil.volume(entry);
// Volume increase and overlap increase:
least_overlap = inc_overlap;
least_areainc = inc_area;
least_area = area;
best = pair.second;
} else if (inc_overlap == least_overlap) {
final double area = SpatialUtil.volume(entry);
if (inc_area < least_areainc || (inc_area == least_areainc && area < least_area)) {
least_overlap = inc_overlap;
least_areainc = inc_area;
least_area = area;
best = pair.second;
}
}
}
assert (best > -1) : "No split found? Volume outside of double precision?";
return best;
}
use of de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair in project elki by elki-project.
the class MkMaxTree method preInsert.
/**
* Adapts the knn distances before insertion of entry q.
*
* @param q the entry to be inserted
* @param nodeEntry the entry representing the root of the current subtree
* @param knns_q the knns of q
*/
private void preInsert(MkMaxEntry q, MkMaxEntry nodeEntry, KNNHeap knns_q) {
if (LOG.isDebugging()) {
LOG.debugFine("preInsert " + q + " - " + nodeEntry + "\n");
}
double knnDist_q = knns_q.getKNNDistance();
MkMaxTreeNode<O> node = getNode(nodeEntry);
double knnDist_node = 0.;
// leaf node
if (node.isLeaf()) {
for (int i = 0; i < node.getNumEntries(); i++) {
MkMaxEntry p = node.getEntry(i);
double dist_pq = distance(p.getRoutingObjectID(), q.getRoutingObjectID());
// ==> p becomes a knn-candidate
if (dist_pq <= knnDist_q) {
knns_q.insert(dist_pq, p.getRoutingObjectID());
if (knns_q.size() >= getKmax()) {
knnDist_q = knns_q.getKNNDistance();
q.setKnnDistance(knnDist_q);
}
}
// q becomes knn of p
if (dist_pq <= p.getKnnDistance()) {
KNNList knns_p = knnq.getKNNForDBID(p.getRoutingObjectID(), getKmax() - 1);
if (knns_p.size() + 1 < getKmax()) {
p.setKnnDistance(Double.NaN);
} else {
double knnDist_p = Math.max(dist_pq, knns_p.getKNNDistance());
p.setKnnDistance(knnDist_p);
}
}
knnDist_node = Math.max(knnDist_node, p.getKnnDistance());
}
} else // directory node
{
List<DoubleIntPair> entries = getSortedEntries(node, q.getRoutingObjectID());
for (DoubleIntPair distEntry : entries) {
MkMaxEntry dirEntry = node.getEntry(distEntry.second);
double entry_knnDist = dirEntry.getKnnDistance();
if (distEntry.second < entry_knnDist || distEntry.second < knnDist_q) {
preInsert(q, dirEntry, knns_q);
knnDist_q = knns_q.getKNNDistance();
}
knnDist_node = Math.max(knnDist_node, dirEntry.getKnnDistance());
}
}
if (LOG.isDebugging()) {
LOG.debugFine(nodeEntry + "set knn dist " + knnDist_node);
}
nodeEntry.setKnnDistance(knnDist_node);
}
Aggregations