Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}