MTnode * MTnode::PromoteVote() { MTnode *newnode=(MTnode *)NCopy(); int i; switch(PROMOTE_VOTE_FUNCTION) { case RANDOMV: { // complexity: constant // cout << "Random voting: "; // pick a random entry (different from the parent) do i=PickRandom(0, NumEntries()); while(((MTentry *)(*this)[i].Ptr())->Key()->distance==0); // cout << "Entry " << (*this)[i].Ptr() << " chosen.\n"; newnode->obj=&((MTentry *)((*newnode)[i].Ptr()))->object(); break; } case SAMPLINGV: { // complexity: O(kn) distance computations // cout << "Sampling voting: "; int *vec=PickCandidates(), bestcand, bestld, bestrd, *bestlv=new int[NumEntries()], *bestrv=new int[NumEntries()]; double minvalue=MAXDOUBLE, sec_minvalue=MAXDOUBLE, **distances=new double *[MIN(NUM_CANDIDATES, NumEntries())]; // distance matrix // find the candidate with minimum radius for (i=0; i<MIN(NUM_CANDIDATES, NumEntries()); i++) { MTentry *cand=(MTentry *)((*this)[vec[i]].Ptr()), *e1=new MTentry, *e2=new MTentry; MTnode *node1=(MTnode *)Copy(), *node2=(MTnode *)NCopy(); double value, sec_value; int leftdeletes, rightdeletes, *leftvec=new int[NumEntries()], *rightvec=new int[NumEntries()], j; // cout << "Entry " << cand; // initialize distance matrix distances[i]=new double[NumEntries()]; for (j=0; j<NumEntries(); j++) distances[i][j]=((vec[i]==j)? 0: cand->object().distance(((MTentry *)((*this)[j].Ptr()))->object())); for(j=0; j<NumEntries(); j++) ((MTentry *)((*node2)[j].Ptr()))->Key()->distance=distances[i][j]; node1->obj=obj; node2->obj=&((MTentry *)((*this)[vec[i]].Ptr()))->object(); // perform the split node1->Split(node2, leftvec, rightvec, &leftdeletes, &rightdeletes); // given the deletion vectors, do bulk deletes node1->DeleteBulk(leftvec, leftdeletes); node2->DeleteBulk(rightvec, rightdeletes); e1->InitKey(); e2->InitKey(); e1->setobject(*node1->obj); e2->setobject(*node2->obj); e1->setmaxradius(0); e2->setmaxradius(0); e1->setminradius(MAXDOUBLE); e2->setminradius(MAXDOUBLE); // compute the radii node1->mMRadius(e1); node2->mMRadius(e2); // check the result value=MAX(e1->maxradius(), e2->maxradius()); // this is minMAX_RADII sec_value=MIN(e1->maxradius(), e2->maxradius()); if((value<minvalue)||((value==minvalue)&&(sec_value<sec_minvalue))) { int index; minvalue=value; sec_minvalue=sec_value; bestld=leftdeletes; bestrd=rightdeletes; for(index=0; index<leftdeletes; index++) bestlv[index]=leftvec[index]; for(index=0; index<rightdeletes; index++) bestrv[index]=rightvec[index]; bestcand=i; } // be tidy delete e1; delete e2; delete node1; delete node2; delete []leftvec; delete []rightvec; } // cout << "Entry " << (*this)[vec[bestcand]].Ptr() << " chosen.\n"; newnode->obj=&((MTentry *)((*newnode)[vec[bestcand]].Ptr()))->object(); // update the distance of the children from the new parent for (i=0; i<NumEntries(); i++) ((MTentry *)((*newnode)[i].Ptr()))->Key()->distance=distances[bestcand][i]; for (i=0; i<MIN(NUM_CANDIDATES, NumEntries()); i++) delete []distances[i]; delete []distances; delete []vec; delete []bestlv; delete []bestrv; break; } case MAX_LB_DIST: { // complexity: constant double maxdist=-1; int maxcand; // cout << "Largest min dist voting:\n"; if(Tree()->IsOrdered()) maxcand=NumEntries()-1; // if the tree is ordered we can choose the last element else // otherwise we have to search the object which is farthest from the parent for (i=0; i<NumEntries(); i++) { MTentry *e=(MTentry *)((*this)[i].Ptr()); if (e->Key()->distance>maxdist) { maxdist=e->Key()->distance; maxcand=i; } } // cout << "Entry " << (*this)[maxcand].Ptr() << " chosen.\n"; newnode->obj=&((MTentry *)((*newnode)[maxcand].Ptr()))->object(); break; } case mM_RAD: { // complexity: constant double minradius=MAXDOUBLE; int bestcand; // cout << "Best radius voting:\n"; for (i=0; i<NumEntries(); i++) { MTentry *cand=(MTentry *)((*this)[i].Ptr()); double radius=0; if(cand->Key()->distance==0) continue; for (int j=0; j<NumEntries(); j++) { MTentry *e=(MTentry *)((*this)[j].Ptr()); double dmin, dmax; if (i==j) continue; dmin=fabs(cand->Key()->distance-e->Key()->distance); dmax=cand->Key()->distance+e->Key()->distance; switch (RADIUS_FUNCTION) { case LB: radius=MAX(radius, dmin); break; case AVG: radius=MAX(radius, (dmin+dmax)/2); break; case UB: radius=MAX(radius, dmax); break; } } if (radius<minradius) { bestcand=i; minradius=radius; } } // cout << "Entry " << (*this)[bestcand].Ptr() << " chosen.\n"; newnode->obj=&((MTentry *)((*newnode)[bestcand].Ptr()))->object(); break; } } return newnode; }
MTnode * MTnode::PromoteVote () { MTnode *newNode = (MTnode *) NCopy (); switch (PROMOTE_VOTE_FUNCTION) { case RANDOMV: { // complexity: constant int i; // pick a random entry (different from the parent) do { i = PickRandom (0, NumEntries()); } while (((MTentry *)(*this)[i].Ptr())->Key()->distance == 0); newNode->obj = &((MTentry *)((*newNode)[i].Ptr()))->object(); break; } case SAMPLINGV: { // complexity: O(kn) distance computations int n = NumEntries (), count = MIN (NUM_CANDIDATES, n-1); int *vec = PickCandidates (), bestCand = 0; double min = MAXDOUBLE, secMin = MAXDOUBLE, **distances = new double *[count]; // distance matrix // find the candidate with minimum radius for (int i=0; i<count; i++) { MTentry *cand = (MTentry *) ((*this)[vec[i]].Ptr()); MTnode *node1 = (MTnode *) Copy (), *node2 = (MTnode *) NCopy (); distances[i] = new double[n]; for (int j=0; j<n; j++) { distances[i][j] = (vec[i]==j) ? 0 : cand->object().distance(((MTentry *)((*this)[j].Ptr()))->object()); // initialize distance matrix ((MTentry *)((*node2)[j].Ptr()))->Key()->distance = distances[i][j]; // if parent entry is i } node1->obj = obj; node2->obj = &((MTentry *)((*this)[vec[i]].Ptr()))->object(); // perform the split int *lVec = new int[n], *rVec = new int[n], lDel, rDel; node1->Split(node2, lVec, rVec, &lDel, &rDel); node1->DeleteBulk(lVec, lDel); node2->DeleteBulk(rVec, rDel); MTentry *entry1 = new MTentry, *entry2 = new MTentry; entry1->InitKey(); entry2->InitKey(); entry1->SetObject(*node1->obj); entry2->SetObject(*node2->obj); entry1->SetMaxRadius(0); entry2->SetMaxRadius(0); entry1->SetMinRadius(MAXDOUBLE); entry2->SetMinRadius(MAXDOUBLE); // compute the radii node1->mMRadius(entry1); node2->mMRadius(entry2); // check the result double val1 = MAX (entry1->MaxRadius(), entry2->MaxRadius()), val2 = MIN (entry1->MaxRadius(), entry2->MaxRadius()); if (val1<min || (val1==min && val2<secMin)) { min = val1; secMin = val2; bestCand = i; } // be tidy delete entry1; delete entry2; delete []lVec; delete []rVec; delete node1; delete node2; } newNode->obj = &((MTentry *)((*newNode)[vec[bestCand]].Ptr()))->object(); // update the distance of the children from the new parent for (int i=0; i<n; i++) { ((MTentry *)((*newNode)[i].Ptr()))->Key()->distance = distances[bestCand][i]; } for (int i=0; i<count; i++) { delete []distances[i]; } delete []distances; delete []vec; break; } case MAX_LB_DISTV: { // complexity: constant double maxDist = -1; int maxCand = 0; if (Tree()->IsOrdered()) { // if the tree is ordered we can choose the last element maxCand = NumEntries() - 1; } else { // otherwise we have to search the object which is farthest from the parent for (int i=0; i<NumEntries(); i++) { MTentry *entry = (MTentry *) (*this)[i].Ptr(); if (entry->Key()->distance > maxDist) { maxDist = entry->Key()->distance; maxCand = i; } } } newNode->obj = &((MTentry *)(*newNode)[maxCand].Ptr())->object(); break; } case mM_RADV: { // complexity: O(n) distance computations int n = NumEntries (); double **distances = new double *[n]; // distance matrix for (int i=0; i<n; i++) { distances[i] = new double[n]; } for (int i=0; i<n; i++) { // initialize distance matrix for (int j=i; j<n; j++) { distances[j][i] = distances[i][j] = -MaxDist(); } } // find the candidate meeting the requirement of minimizing max(1->maxradius, 2->maxradius) double min = MAXDOUBLE; int bestCand = 0; for (int i=0; i<n; i++) { MTentry *cand = (MTentry *) (*this)[i].Ptr(); if (cand->Key()->distance == 0) { // parent entry, actually we can neglect it for (int j=0; j<n; j++) { distances[j][i] = distances[i][j] = ((MTentry *)(*this)[j].Ptr())->Key()->distance; } continue; } MTnode *node1 = (MTnode *) Copy (), *node2 = (MTnode *) NCopy (); for (int j=0; j<n; j++) { distances[j][i] = distances[i][j] = (i==j) ? 0 : (distances[i][j]==-MaxDist() ? cand->object().distance(((MTentry *)(*this)[j].Ptr())->object()) : distances[i][j]); ((MTentry *)(*node2)[j].Ptr())->Key()->distance = distances[i][j]; // if parent entry is i } node1->obj = obj; node2->obj = &((MTentry *)(*this)[i].Ptr())->object(); // perform the split int *lVec = new int[n], *rVec = new int[n], lDel, rDel; node1->Split(node2, lVec, rVec, &lDel, &rDel); node1->DeleteBulk(lVec, lDel); node2->DeleteBulk(rVec, rDel); MTentry *entry1 = new MTentry, *entry2 = new MTentry; entry1->InitKey(); entry2->InitKey(); entry1->SetObject(*node1->obj); entry2->SetObject(*node2->obj); entry1->SetMaxRadius(0); entry2->SetMaxRadius(0); entry1->SetMinRadius(MAXDOUBLE); entry2->SetMinRadius(MAXDOUBLE); node1->mMRadius(entry1); node2->mMRadius(entry2); // check the result double val = MAX (entry1->MaxRadius(), entry2->MaxRadius()); if (val < min) { min = val; bestCand = i; } // be tidy delete entry1; delete entry2; delete []lVec; delete []rVec; delete node1; delete node2; } newNode->obj = &((MTentry *)(*newNode)[bestCand].Ptr())->object(); // update the distance of the children from the new parent for (int i=0; i<n; i++) { ((MTentry *)(*newNode)[i].Ptr())->Key()->distance = distances[bestCand][i]; } for (int i=0; i<n; i++) { delete []distances[i]; } delete []distances; break; } } return newNode; }
MTnode * MTnode::PromotePart() { MTnode *newnode; switch(PROMOTE_PART_FUNCTION) { case RANDOM: { // complexity: constant int i, j; // pick two *different* random entries // cout << "Random promotion: "; i=PickRandom(0, NumEntries()); do j=PickRandom(0, NumEntries()); while (j==i); if(((MTentry *)(*this)[j].Ptr())->Key()->distance==0) { int k=i; i=j; j=k; // if we chose the parent entry, put it in the left node } // cout << "Entries " << (*this)[i].Ptr() << " & " << (*this)[j].Ptr() << " chosen.\n"; newnode=(MTnode *)NCopy(); // re-assign the nodes' object newnode->obj=&((MTentry *)((*newnode)[j].Ptr()))->object(); obj=&((MTentry *)((*this)[i].Ptr()))->object(); if(((MTentry *)(*this)[i].Ptr())->Key()->distance>0) { // if the parent object wasn't confirmed, invalidate also the parent InvalidateEntry(TRUE); InvalidateEntries(); } else InvalidateEntry(FALSE); // else, invalidate only the node's radii break; } case CONFIRMED: { // complexity: determined by the confirmed promotion algorithm int i; BOOL isRoot=TRUE; // cout << "Confirmed promotion: "; // for(i=0; (i<NumEntries())&&(isRoot); i++) isRoot=(((MTentry *)((*this)[i].Ptr()))->Key()->distance==-MAXDIST); isRoot=(((MTentry *)((*this)[0].Ptr()))->Key()->distance==-maxDist()); // we have ordered entries if(isRoot) { // if we're splitting the root we have to use a policy that doesn't use stored distances PROMOTE_PART_FUNCTION=SECONDARY_PART_FUNCTION; newnode=PromotePart(); PROMOTE_PART_FUNCTION=CONFIRMED; } else { int index=-1; for(i=0; (i<NumEntries())&&(index<0); i++) if(((MTentry *)((*this)[i].Ptr()))->Key()->distance==0) index=i; obj=&((MTentry *)((*this)[index].Ptr()))->object(); // now choose the right node parent newnode=PromoteVote(); } InvalidateEntry(FALSE); break; } case MAX_UB_DIST: { // complexity: constant double maxdist=-1, maxdist2; int i, maxcand1, maxcand2; BOOL isRoot=TRUE; // cout << "Largest max dist promotion:\n"; // for(i=0; (i<NumEntries())&&(isRoot); i++) isRoot=(((MTentry *)((*this)[i].Ptr()))->Key()->distance==-MAXDIST); isRoot=(((MTentry *)((*this)[0].Ptr()))->Key()->distance==-maxDist()); // we have ordered entries if(isRoot) { // if we're splitting the root we have to use a policy that doesn't use stored distances PROMOTE_PART_FUNCTION=SECONDARY_PART_FUNCTION; newnode=PromotePart(); PROMOTE_PART_FUNCTION=CONFIRMED; } else if(Tree()->IsOrdered()) { // if the tree is ordered we can choose the last two elements maxcand1=NumEntries()-1; maxcand2=NumEntries()-2; } // the following code should be unreachable else // otherwise we have to search the two objects which are farthest from the parent for (i=0; i<NumEntries(); i++) { MTentry *e=(MTentry *)((*this)[i].Ptr()); if (e->Key()->distance>maxdist) { maxdist2=maxdist; maxdist=e->Key()->distance; maxcand2=maxcand1; maxcand1=i; } else if (e->Key()->distance>maxdist2) { maxdist2=e->Key()->distance; maxcand2=i; } } // cout << "Entries " << (*this)[maxcand1].Ptr() << " & " << (*this)[maxcand2].Ptr() << " chosen.\n"; // for sure the parent isn't confirmed (unless we have a binary tree...) obj=&((MTentry *)((*this)[maxcand1].Ptr()))->object(); InvalidateEntry(TRUE); InvalidateEntries(); newnode=(MTnode *)NCopy(); newnode->obj=&((MTentry *)((*newnode)[maxcand2].Ptr()))->object(); break; } case SAMPLING: { // complexity: O(kn) distance computations // cout << "Sampling: "; int *vec=PickCandidates(), i, j, min1, min2, bestld, bestrd, *bestlv=new int[NumEntries()], *bestrv=new int[NumEntries()]; double minvalue=MAXDOUBLE, sec_minvalue=MAXDOUBLE, **distances=new double*[MIN(NUM_CANDIDATES, NumEntries())]; // distance matrix // initialize distance matrix for(i=0; i<MIN(NUM_CANDIDATES, NumEntries()); i++) { distances[i]=new double[NumEntries()]; for(j=0; j<NumEntries(); j++) distances[i][j]=-maxDist(); } for(i=0; i<MIN(NUM_CANDIDATES, NumEntries()); i++) if(((MTentry *)((*this)[vec[i]].Ptr()))->Key()->distance==0) { for(j=0; j<NumEntries(); j++) distances[i][j]=((MTentry *)((*this)[j].Ptr()))->Key()->distance; break; } for(i=0; i<MIN(NUM_CANDIDATES, NumEntries()); i++) distances[i][vec[i]]=0; // find the candidates with minimum radius for(i=1; i<MIN(NUM_CANDIDATES, NumEntries()); i++) for (j=0; j<i; j++) { MTentry *e1=new MTentry, *e2=new MTentry; MTnode *node1=(MTnode *)NCopy(), *node2=(MTnode *)NCopy(); double value, sec_value; int leftdeletes, rightdeletes, *leftvec=new int[NumEntries()], *rightvec=new int[NumEntries()], k; for(k=0; k<NumEntries(); k++) { ((MTentry *)((*node1)[k].Ptr()))->Key()->distance=distances[i][k]; ((MTentry *)((*node2)[k].Ptr()))->Key()->distance=distances[j][k]; } node1->obj=&((MTentry *)((*this)[vec[i]].Ptr()))->object(); node2->obj=&((MTentry *)((*this)[vec[j]].Ptr()))->object(); // perform the split node1->Split(node2, leftvec, rightvec, &leftdeletes, &rightdeletes); for(k=0; k<NumEntries(); k++) { distances[i][k]=((MTentry *)((*node1)[k].Ptr()))->Key()->distance; distances[j][k]=((MTentry *)((*node2)[k].Ptr()))->Key()->distance; } // given the deletion vectors, do bulk deletes node1->DeleteBulk(leftvec, leftdeletes); node2->DeleteBulk(rightvec, rightdeletes); e1->InitKey(); e2->InitKey(); e1->setobject(*node1->obj); e2->setobject(*node2->obj); e1->setmaxradius(0); e2->setmaxradius(0); e1->setminradius(MAXDOUBLE); e2->setminradius(MAXDOUBLE); // compute the radii node1->mMRadius(e1); node2->mMRadius(e2); // check the result value=MAX(e1->maxradius(), e2->maxradius()); // this is minMAX_RADII sec_value=MIN(e1->maxradius(), e2->maxradius()); if((value<minvalue)||((value==minvalue)&&(sec_value<sec_minvalue))) { int index; minvalue=value; sec_minvalue=sec_value; bestld=leftdeletes; bestrd=rightdeletes; for(index=0; index<leftdeletes; index++) bestlv[index]=leftvec[index]; for(index=0; index<rightdeletes; index++) bestrv[index]=rightvec[index]; min1=i; min2=j; } // be tidy delete []leftvec; delete []rightvec; delete node1; delete node2; delete e1; delete e2; } // cout << "Entries " << (*this)[vec[min1]].Ptr() << " & " << (*this)[vec[min2]].Ptr() << " chosen.\n"; if(((MTentry *)(*this)[vec[min2]].Ptr())->Key()->distance>0) newnode=(MTnode *)NCopy(); else newnode=(MTnode *)Copy(); newnode->obj=&((MTentry *)((*newnode)[vec[min2]].Ptr()))->object(); obj=&((MTentry *)((*this)[vec[min1]].Ptr()))->object(); if(((MTentry *)(*this)[vec[min1]].Ptr())->Key()->distance>0) { // if the parent object wasn't confirmed, invalidate also the parent InvalidateEntry(TRUE); InvalidateEntries(); } else InvalidateEntry(FALSE); // else, invalidate only the node's radii for(i=0; i<NumEntries(); i++) { ((MTentry *)((*this)[i].Ptr()))->Key()->distance=distances[min1][i]; ((MTentry *)((*newnode)[i].Ptr()))->Key()->distance=distances[min2][i]; } delete []bestlv; delete []bestrv; for(i=0; i<MIN(NUM_CANDIDATES, NumEntries()); i++) delete []distances[i]; delete []distances; break; } case MIN_RAD: case MIN_OVERLAPS: { // complexity: O(n^2) distance computations int min1, min2, i, j, bestld, bestrd, *bestlv=new int[NumEntries()], *bestrv=new int[NumEntries()]; double minvalue=MAXDOUBLE, sec_minvalue=MAXDOUBLE, **distances=new double *[NumEntries()]; // distance matrix // initialize distance matrix for(i=0; i<NumEntries(); i++) { distances[i]=new double[NumEntries()]; for(j=0; j<NumEntries(); j++) distances[i][j]=-maxDist(); } for(i=0; i<NumEntries(); i++) if(((MTentry *)((*this)[i].Ptr()))->Key()->distance==0) { for(j=0; j<NumEntries(); j++) { distances[i][j]=((MTentry *)((*this)[j].Ptr()))->Key()->distance; distances[j][i]=distances[i][j]; } break; } for(i=0; i<NumEntries(); i++) distances[i][i]=0; // if(PROMOTE_PART_FUNCTION==MIN_RADII) cout << "Min radii promotion: "; // else cout << "Min overlaps promotion: "; for (i=1; i<NumEntries(); i++) for (j=0; j<i; j++) { MTentry *e1=new MTentry, *e2=new MTentry; MTnode *node1=(MTnode *)NCopy(), *node2=(MTnode *)NCopy(); double value, sec_value; int leftdeletes, rightdeletes, *leftvec=new int[NumEntries()], *rightvec=new int[NumEntries()], k; for(k=0; k<NumEntries(); k++) { ((MTentry *)((*node1)[k].Ptr()))->Key()->distance=distances[i][k]; ((MTentry *)((*node2)[k].Ptr()))->Key()->distance=distances[j][k]; } node1->obj=&((MTentry *)((*this)[i].Ptr()))->object(); node2->obj=&((MTentry *)((*this)[j].Ptr()))->object(); // perform the split node1->Split(node2, leftvec, rightvec, &leftdeletes, &rightdeletes); for(k=0; k<NumEntries(); k++) { distances[i][k]=((MTentry *)((*node1)[k].Ptr()))->Key()->distance; distances[j][k]=((MTentry *)((*node2)[k].Ptr()))->Key()->distance; distances[k][i]=distances[i][k]; distances[k][j]=distances[j][k]; } // given the deletion vectors, do bulk deletes node1->DeleteBulk(leftvec, leftdeletes); node2->DeleteBulk(rightvec, rightdeletes); e1->InitKey(); e2->InitKey(); e1->setobject(*node1->obj); e2->setobject(*node2->obj); e1->setmaxradius(0); e2->setmaxradius(0); e1->setminradius(MAXDOUBLE); e2->setminradius(MAXDOUBLE); // compute the radii node1->mMRadius(e1); node2->mMRadius(e2); // check the result if(PROMOTE_PART_FUNCTION==MIN_RAD) { value=MAX(e1->maxradius(), e2->maxradius()); // this is minMAX_RADII sec_value=MIN(e1->maxradius(), e2->maxradius()); } else value=e1->maxradius()+e2->maxradius()-distances[i][j]; if((value<minvalue)||((value==minvalue)&&(sec_value<sec_minvalue))) { int index; minvalue=value; sec_minvalue=sec_value; bestld=leftdeletes; bestrd=rightdeletes; for(index=0; index<leftdeletes; index++) bestlv[index]=leftvec[index]; for(index=0; index<rightdeletes; index++) bestrv[index]=rightvec[index]; min1=i; min2=j; } // be tidy delete []leftvec; delete []rightvec; delete node1; delete node2; delete e1; delete e2; } // cout << "Entries " << (*this)[min1].Ptr() << " & " << (*this)[min2].Ptr() << " chosen.\n"; if(((MTentry *)(*this)[min2].Ptr())->Key()->distance>0) newnode=(MTnode *)NCopy(); else newnode=(MTnode *)Copy(); newnode->obj=&((MTentry *)((*newnode)[min2].Ptr()))->object(); obj=&((MTentry *)((*this)[min1].Ptr()))->object(); if(((MTentry *)(*this)[min1].Ptr())->Key()->distance>0) { // if the parent object wasn't confirmed, invalidate also the parent InvalidateEntry(TRUE); InvalidateEntries(); } else InvalidateEntry(FALSE); // else, invalidate only the node's radii for(i=0; i<NumEntries(); i++) { ((MTentry *)((*this)[i].Ptr()))->Key()->distance=distances[min1][i]; ((MTentry *)((*newnode)[i].Ptr()))->Key()->distance=distances[min2][i]; } delete bestlv; delete bestrv; for(i=0; i<NumEntries(); i++) delete []distances[i]; delete []distances; break; } } return newnode; }
MTnode * MTnode::PromotePart () { MTnode *newNode = NULL; switch (PROMOTE_PART_FUNCTION) { case RANDOM: { // pick two *different* random entries, complexity: constant int i = PickRandom (0, NumEntries()); int j; do { j = PickRandom (0, NumEntries()); } while (i == j); if (((MTentry *)(*this)[j].Ptr())->Key()->distance == 0) { // if we chose the parent entry, put it in the left node int temp = i; i = j; j = temp; } // re-assign the nodes' object newNode = (MTnode *) NCopy (); newNode->obj = &((MTentry *)((*newNode)[j].Ptr()))->object(); obj = &((MTentry *)((*this)[i].Ptr()))->object(); if (((MTentry *)(*this)[i].Ptr())->Key()->distance > 0) { // unconfirmed, invalidate also the parent InvalidateEntry (TRUE); InvalidateEntries (); } else { InvalidateEntry (FALSE); // confirmed, invalidate only the node's radii } break; } case CONFIRMED: { // complexity: determined by the confirmed promotion algorithm if (((MTentry *)((*this)[0].Ptr()))->Key()->distance == -MaxDist()) { // if we're splitting the root we have to use a policy that doesn't use stored distances PROMOTE_PART_FUNCTION = SECONDARY_PART_FUNCTION; newNode = PromotePart (); PROMOTE_PART_FUNCTION = CONFIRMED; } else { int index = -1; for (int i=0; i<NumEntries() /*&& index<0*/; i++) { if (((MTentry *)((*this)[i].Ptr()))->Key()->distance == 0) { // parent obj index = i; } } obj = &((MTentry *)((*this)[index].Ptr()))->object(); newNode = PromoteVote (); // now choose the right node parent } InvalidateEntry (FALSE); break; } case SAMPLING: { // complexity: O(kn) distance computations int n = NumEntries (), count = MIN (NUM_CANDIDATES, n-1); double **distances = new double*[count]; // distance matrix int *vec = PickCandidates (); // initialize distance matrix for (int i=0; i<count; i++) { distances[i] = new double[n]; for (int j=0; j<n; j++) { j==vec[i] ? distances[i][j]=0 : distances[i][j]=-MaxDist(); } } // find the candidates with minimum radius int min1, min2; double min = MAXDOUBLE, secMin = MAXDOUBLE; for (int i=1; i<count; i++) { for (int j=0; j<i; j++) { MTnode *node1 = (MTnode *) NCopy (), *node2 = (MTnode *) NCopy (); for (int k=0; k<n; k++) { ((MTentry *)(*node1)[k].Ptr())->Key()->distance = distances[i][k]; ((MTentry *)(*node2)[k].Ptr())->Key()->distance = distances[j][k]; } node1->obj = &((MTentry *)(*this)[vec[i]].Ptr())->object(); node2->obj = &((MTentry *)(*this)[vec[j]].Ptr())->object(); // perform the split int lDel, rDel, *lVec = new int[n], *rVec = new int[n]; node1->Split(node2, lVec, rVec, &lDel, &rDel); for (int k=0; k<n; k++) { distances[i][k] = ((MTentry *)(*node1)[k].Ptr())->Key()->distance; distances[j][k] = ((MTentry *)(*node2)[k].Ptr())->Key()->distance; } node1->DeleteBulk(lVec, lDel); node2->DeleteBulk(rVec, rDel); MTentry *entry1 = new MTentry, *entry2 = new MTentry; entry1->InitKey(); entry2->InitKey(); entry1->SetObject(*node1->obj); entry2->SetObject(*node2->obj); entry1->SetMaxRadius(0); entry2->SetMaxRadius(0); entry1->SetMinRadius(MAXDOUBLE); entry2->SetMinRadius(MAXDOUBLE); node1->mMRadius(entry1); node2->mMRadius(entry2); // check the result double val1 = MAX (entry1->MaxRadius(), entry2->MaxRadius()), val2 = MIN (entry1->MaxRadius(), entry2->MaxRadius()); if (val1<min || (val1==min && val2<secMin)) { min = val1; secMin = val2; min1 = i; min2 = j; } // be tidy delete entry1; delete entry2; delete []lVec; delete []rVec; delete node1; delete node2; } } newNode = (MTnode *) NCopy (); obj = &((MTentry *)(*this)[vec[min1]].Ptr())->object(); newNode->obj = &((MTentry *)(*newNode)[vec[min2]].Ptr())->object(); // the parent object wasn't confirmed, invalidate also the parent InvalidateEntry (TRUE); InvalidateEntries (); for (int i=0; i<n; i++) { ((MTentry *)(*this)[i].Ptr())->Key()->distance = distances[min1][i]; ((MTentry *)(*newNode)[i].Ptr())->Key()->distance = distances[min2][i]; } for (int i=0; i<count; i++) { delete []distances[i]; } delete []distances; break; } case mM_RAD: { // complexity: O(n^2) distance computations int n = NumEntries (); double **distances = new double *[n]; // distance matrix // initialize distance matrix for (int i=0; i<n; i++) { distances[i] = new double[n]; for (int j=0; j<n; j++) { j==i ? distances[i][j]=0 : distances[i][j]=-MaxDist(); } } for (int i=0; i<n; i++) { if (((MTentry *)(*this)[i].Ptr())->Key()->distance == 0) { for (int j=0; j<n; j++) { distances[j][i] = distances[i][j] = ((MTentry *)(*this)[j].Ptr())->Key()->distance; } break; } } int min1, min2; double min = MAXDOUBLE, secMin = MAXDOUBLE; for (int i=1; i<n; i++) { for (int j=0; j<i; j++) { MTnode *node1 = (MTnode *) NCopy (), *node2 = (MTnode *) NCopy (); for (int k=0; k<n; k++) { ((MTentry *)(*node1)[k].Ptr())->Key()->distance = distances[i][k]; ((MTentry *)(*node2)[k].Ptr())->Key()->distance = distances[j][k]; } node1->obj = &((MTentry *)(*this)[i].Ptr())->object(); node2->obj = &((MTentry *)(*this)[j].Ptr())->object(); // perform the split int lDel, rDel, *lVec=new int[n], *rVec=new int[n]; node1->Split(node2, lVec, rVec, &lDel, &rDel); for (int k=0; k<n; k++) { distances[k][i] = distances[i][k] = ((MTentry *)(*node1)[k].Ptr())->Key()->distance; distances[k][j] = distances[j][k] = ((MTentry *)(*node2)[k].Ptr())->Key()->distance; } node1->DeleteBulk(lVec, lDel); node2->DeleteBulk(rVec, rDel); MTentry *entry1 = new MTentry, *entry2 = new MTentry; entry1->InitKey(); entry2->InitKey(); entry1->SetObject(*node1->obj); entry2->SetObject(*node2->obj); entry1->SetMaxRadius(0); entry2->SetMaxRadius(0); entry1->SetMinRadius(MAXDOUBLE); entry2->SetMinRadius(MAXDOUBLE); node1->mMRadius(entry1); node2->mMRadius(entry2); // check the result double val1 = MAX (entry1->MaxRadius(), entry2->MaxRadius()), val2 = MIN (entry1->MaxRadius(), entry2->MaxRadius()); if (val1<min || (val1==min && val2<secMin)) { min = val1; secMin = val2; min1 = i; min2 = j; } // be tidy delete entry1; delete entry2; delete []lVec; delete []rVec; delete node1; delete node2; } } ((MTentry *)(*this)[min2].Ptr())->Key()->distance>0 ? newNode=(MTnode *)NCopy() : newNode=(MTnode *)Copy(); obj = &((MTentry *)(*this)[min1].Ptr())->object(); newNode->obj = &((MTentry *)(*newNode)[min2].Ptr())->object(); if (((MTentry *)(*this)[min1].Ptr())->Key()->distance > 0) { // unconfirmed, invalidate also the parent InvalidateEntry (TRUE); InvalidateEntries (); } else { InvalidateEntry (FALSE); // else, invalidate only the node's radii } for (int i=0; i<n; i++) { ((MTentry *)(*this)[i].Ptr())->Key()->distance = distances[min1][i]; ((MTentry *)(*newNode)[i].Ptr())->Key()->distance = distances[min2][i]; } for (int i=0; i<n; i++) { delete []distances[i]; } delete []distances; break; } } return newNode; }