Пример #1
0
void
MTnode::SortEntries ()
{
	int n = NumEntries ();
	MTentry **array = new MTentry *[n], *objEntry = NULL;
	for (int i=0; i<n; i++) {
		array[i] = (MTentry *) ((MTentry *)(*this)[i].Ptr())->Copy();
		if (&((MTentry *)(*this)[i].Ptr())->object() == obj) {
			objEntry = array[i];
		}
	}
	qsort (array, n, sizeof(MTentry *), MTentryCmp);
	while (NumEntries() > 0) {
		DeleteEntry (0);  // also delete the obj
	}

	int obji = -1;
	for (int i=0; i<n; i++) {
		InsertBefore (*(array[i]), i);
		if (array[i] == objEntry) {
			obji = i;
		}
		delete array[i];
	}
	delete []array;

	if (obji >= 0) {
		obj = &((MTentry *)(*this)[obji].Ptr())->object();
	}
}
Пример #2
0
GiSTnode *
MTnode::PickSplit()
{
	MTnode *rightnode;
	int leftdeletes, rightdeletes;	// number of entries to be deleted from each node
	int *leftvec=new int[NumEntries()], *rightvec=new int[NumEntries()];	// array of entries to be deleted from each node

	// promote the right node (possibly reassigning the left node);
	// the right node's page is copied from left node; 
	// we'll delete from the nodes as appropriate after the splitting phase
//	cout << "In PickSplit with node " << this << "\n";
	rightnode=PromotePart();
	// now perform the split
	Split(rightnode, leftvec, rightvec, &leftdeletes, &rightdeletes);	// complexity: O(n)
	// given the deletion vectors, do bulk deletes
	DeleteBulk(leftvec, leftdeletes);
	rightnode->DeleteBulk(rightvec, rightdeletes);
//	cout << "Nodes:\n" << this << rightnode;
	// order the entries in both nodes
	Order();
	rightnode->Order();
	delete []leftvec;
	delete []rightvec;
	// return the right node
	return rightnode;
}
Пример #3
0
const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte) {
   const char *cs = "ISO6937";
   // Workaround for broadcaster stupidity: according to
   // "ETSI EN 300 468" the default character set is ISO6937. But unfortunately some
   // broadcasters actually use ISO-8859-9, but fail to correctly announce that.
   if (OverrideCharacterTable)
      cs = OverrideCharacterTable;
   if (isSingleByte)
      *isSingleByte = false;
   if (length <= 0)
      return cs;
   unsigned int tag = buffer[0];
   if (tag >= 0x20)
      return cs;
   if (tag == 0x10) {
      if (length >= 3) {
         tag = (buffer[1] << 8) | buffer[2];
         if (tag < NumEntries(CharacterTables2) && CharacterTables2[tag]) {
            buffer += 3;
            length -= 3;
            if (isSingleByte)
               *isSingleByte = true;
            return CharacterTables2[tag];
         }
      }
   } else if (tag < NumEntries(CharacterTables1) && CharacterTables1[tag]) {
      buffer += 1;
      length -= 1;
      if (isSingleByte)
         *isSingleByte = tag <= SingleByteLimit;
      return CharacterTables1[tag];
   }
   return cs;
}
Пример #4
0
void
MTnode::Print(ostream& os) const
{
	if(obj!=NULL) os << *obj << " ";
//	else cout << "obj NULL...\n";
	os << ((MTnode *)this)->Path() << " #Entries: " << NumEntries() << ", Level " << Level();
	if(IsLeaf()) os << "(Leaf)";
	else os << "(Internal)";
	os << ", Sibling: " << Sibling() << ", Size: " << Size() << "/" << Tree()->Store()->PageSize() << endl;
	for(int i=0; i<NumEntries(); i++) (*this)[i]->Print(os);
}
Пример #5
0
void
MTnode::Print (ostream& os) const
{
	if (obj) {
		os << *obj << " ";
	}
	os << ((MTnode *)this)->Path() << " #Entries: " << NumEntries() << ", Level " << Level();
	IsLeaf () ? os << "(Leaf)" : os << "(Internal)";
	os << ", Sibling: " << Sibling() << ", Size: " << Size() << "/" << Tree()->Store()->PageSize() << endl;
	for (int i=0; i<NumEntries(); i++) {
		(*this)[i]->Print(os);
	}
}
Пример #6
0
// We are moving entries from node, which is to our right, to this.
// If this is a non-empty internal page, the rightmost entry on this 
// has an upperbound of +inf, and the leftmost entry on node has
// a lower bound of -inf.  This code takes care of that -- both
// these values should be set to the right bound of our parent entry.
void 
BTnode::Coalesce(const GiSTnode& node, 
		 const GiSTentry& entry) // entry is in 1 level up, and
                                         // points to this
{
    if (!NumEntries() || IsLeaf()) {
	GiSTnode::Coalesce(node, entry);
    } else {
	int n = NumEntries();
	GiSTnode::Coalesce(node, entry);
	const BTentry &bte = (const BTentry&) entry;
	((BTentry*)(*this)[n-1].Ptr())->SetUpperBound(bte.UpperBound());
	((BTentry*)(*this)[n].Ptr())->SetLowerBound(bte.UpperBound());
    }
}
Пример #7
0
// insert before the original number according to the sequence instead of index
void
MTnode::InsertBefore (const GiSTentry& newEntry, int index)
{
	int n = NumEntries ();
	assert (index>=0 && index<=n);

	BOOL bOrder = TRUE;
	if (index > 0) {
		bOrder = (*this)[index-1]->Compare(newEntry) <= 0;
	}
	if (index < n) {
		bOrder = bOrder && (*this)[index]->Compare(newEntry) >= 0;
	}

	if (bOrder) {  // yes, the position is right for this entry
		GiSTentry *entry = (GiSTentry *) newEntry.Copy ();
		entry->SetLevel(Level());
		entry->SetPosition(index);
		entry->SetNode(this);
		// Move everything else over
		for (int i=n; i>index; i--) {
			GiSTentry *e = (*this)[i-1];
			e->SetPosition(i);
			(*this)[i] = e;
		}
		// Stick the entry in
		(*this)[index] = entry;
		// Bump up the count
		SetNumEntries (n+1);
	} else {
		Insert (newEntry);  // find the right place
	}
}
Пример #8
0
void 
BTnode::InsertBefore(const GiSTentry& entry, int index)
{
    // Only BTentry's can be inserted into BTnodes.
    assert(entry.IsA() == BTENTRY_CLASS);

    BTentry e((const BTentry&) entry);

    // If this is an internal node, adjust the lower/upper bounds
    if (!IsLeaf()) {
	// If not leftmost entry...
	if (index != 0) {
	    // -inf changes to the upper bound of previous item
	    BTentry *prev = (BTentry*) (*this)[index-1].Ptr();
	    if (e.LowerBound() == NegInf)
		e.SetLowerBound(prev->UpperBound());
	}
	// If not rightmost entry...
	if (index != NumEntries()) {
	    // +inf changes to the lower bound of next item
	    BTentry *next = (BTentry*) (*this)[index].Ptr();
	    if (e.UpperBound() == PosInf)
		e.SetUpperBound(next->LowerBound());
	}
    }

    // Insert it into the node
    GiSTnode::InsertBefore(e, index);
}
Пример #9
0
void
MTnode::InvalidateEntries ()
{
	for (int i=0; i<NumEntries(); i++) {
		((MTentry *)((*this)[i].Ptr()))->Key()->distance = -MaxDist();
	}
}
Пример #10
0
void
MTnode::InsertBefore(const GiSTentry& entry, int index)
{
	int n=NumEntries();
	BOOL ordered=TRUE;

	if(index>0) ordered=((*this)[index-1]->Compare(entry)<=0);
	if(index<n) ordered=ordered&&((*this)[index]->Compare(entry)>=0);
	if(ordered) {	// yes, the position is right for this entry
		assert(index<=n);
		GiSTentry *e=(GiSTentry *)entry.Copy();

		e->SetLevel(Level());
		e->SetPosition(index);
		e->SetNode(this);
		// Move everything else over
		for(int i=n; i>index; i--) {
			GiSTentry *e=(*this)[i-1];

			e->SetPosition(i);
			(*this)[i]=e;
		}
		// Stick the entry in
		(*this)[index]=e;
		// Bump up the count
		SetNumEntries(n+1);
	}
	else Insert(entry);	// find the right place
}
Пример #11
0
int *
MTnode::PickCandidates()
{
	int max_ind=MIN(NUM_CANDIDATES, NumEntries()), *vec=new int[max_ind], i;
	BOOL *used=new BOOL[NumEntries()];

	for(i=0; i<NumEntries(); i++) used[i]=(((MTentry *)(*this)[i].Ptr())->Key()->distance==0);
	// insert in vec the indices of the candidates for promotion
	for(i=0; i<max_ind; i++) {
		int j;

		do j=PickRandom(0, NumEntries());
		while(used[j]);
		vec[i]=j;
		used[j]=TRUE;
	}
	return vec;
}
Пример #12
0
void 
GiSTnode::InsertBefore (const GiSTentry& entry, int index)
{
	assert (index <= NumEntries());
	GiSTentry *e = (GiSTentry*)entry.Copy();

	e->SetLevel (Level());
	e->SetPosition (index);
	e->SetNode (this);
	// Move everything else over
	for (int i=NumEntries(); i>index; i--) {
		GiSTentry *e = (*this)[i-1];
		e->SetPosition (i);
		(*this)[i] = e;
	}
	// Stick the entry in
	(*this)[index] = e;
	// Bump up the count
	numEntries++;
}
Пример #13
0
void 
GiSTnode::Coalesce (const GiSTnode &source)
{
	// Coalesce by one-by-one insertion
	//   Take each entry from the source node
	//   and insert it into this node.
	for (int i=0; i<source.numEntries; i++) {
//		GiSTentry& e=source[i];  // this is deleted by myself
		InsertBefore ((GiSTentry&)source[i], NumEntries());
	}
}
Пример #14
0
// quick-sort the entries with respect to the distance from the parent
void
MTnode::Order()
{
	int i, obji=-1, n=NumEntries();
	MTentry **array=new MTentry *[n], *objEntry=NULL;

	for(i=0; i<n; i++) {
		array[i]=(MTentry *)((MTentry *)(*this)[i].Ptr())->Copy();
		if(obj==&((MTentry *)(*this)[i].Ptr())->object()) objEntry=array[i];
	}
	qsort(array, n, sizeof(MTentry *), MTentrycmp);
	while(NumEntries()>0) DeleteEntry(0);
	for(i=0; i<n; i++) {
		InsertBefore(*(array[i]), i);
		if(objEntry==array[i]) obji=i;
		delete array[i];
	}
	delete []array;
	if(obji>=0) obj=&((MTentry *)(*this)[obji].Ptr())->object();
}
Пример #15
0
void 
GiSTnode::Insert(const GiSTentry& entry)
{
    // Find out where to insert it
    int i;
    for (i=0; i<NumEntries(); i++)
	if ((*this)[i]->Compare(entry) > 0)
	    break;

    // Do the deed
    InsertBefore(entry, i);
}
Пример #16
0
void 
GiSTnode::Coalesce(const GiSTnode &source,
		   const GiSTentry& entry) // entry is the entry in the
                                           // parent node that points to this
{
    // Coalesce by one-by-one insertion
    //   Take each entry from the source node
    //   and insert it into this node.
    for (int i=0; i<source.numEntries; i++) {
	GiSTentry& e = source[i];
	InsertBefore(e, NumEntries());
    }
}
Пример #17
0
GiSTnode *
MTnode::PickSplit ()
{
	int lDel, rDel;  // number of entries to be deleted from each node
	int *lArray = new int[NumEntries()], *rArray = new int[NumEntries()];  // array of entries to be deleted from each node

	// promote the right node (possibly reassigning the left node);
	// the right node's page is copied from left node;
	// we'll delete from the nodes as appropriate after the splitting phase
	MTnode *rNode = PromotePart ();
	// now perform the split
	Split (rNode, lArray, rArray, &lDel, &rDel);  // complexity: O(n)
	// given the deletion vectors, do bulk deletes
	DeleteBulk (lArray, lDel);
	rNode->DeleteBulk(rArray, rDel);
	// order the entries in both nodes
	SortEntries ();
	rNode->SortEntries();

	delete []lArray;
	delete []rArray;
	return rNode;  // return the right node
}
Пример #18
0
bool SetSystemCharacterTable(const char *CharacterTable) {
   if (CharacterTable) {
      for (unsigned int i = 0; i < NumEntries(CharacterTables1); i++) {
         if (CharacterTables1[i] && strcasecmp(CharacterTable, CharacterTables1[i]) == 0) {
            SystemCharacterTable = CharacterTables1[i];
            SystemCharacterTableIsSingleByte = i <= SingleByteLimit;
            return true;
         }
      }
      for (unsigned int i = 0; i < NumEntries(CharacterTables2); i++) {
         if (CharacterTables2[i] && strcasecmp(CharacterTable, CharacterTables2[i]) == 0) {
            SystemCharacterTable = CharacterTables2[i];
            SystemCharacterTableIsSingleByte = true;
            return true;
         }
      }
   } else {
      SystemCharacterTable = NULL;
      SystemCharacterTableIsSingleByte = true;
      return true;
   }
   return false;
}
Пример #19
0
GiSTlist<MTentry *>
MTnode::RangeSearch(const MTquery &query)
{
	GiSTlist<MTentry *> result;

	if(IsLeaf())
		for(int i=0; i<NumEntries(); i++) {
			MTentry *e=(MTentry *)(*this)[i].Ptr()->Copy();
			MTquery *q=(MTquery *)query.Copy();

			if(q->Consistent(*e)) {	// object qualifies
				e->setmaxradius(q->Grade());
				result.Append(e);
			}
			else delete e;
			delete q;
		}
	else
		for(int i=0; i<NumEntries(); i++) {
			MTentry *e=(MTentry *)(*this)[i].Ptr();
			MTquery *q=(MTquery *)query.Copy();

			if(q->Consistent(*e)) {	// sub-tree not excluded
				GiSTpath childpath=Path();
				MTnode *child;
				GiSTlist<MTentry *>list;

				childpath.MakeChild(e->Ptr());
				child=(MTnode *)((MT *)Tree())->ReadNode(childpath);
				list=child->RangeSearch(*q);	// recurse the search
				while(!list.IsEmpty()) result.Append(list.RemoveFront());
				delete child;
			}
			delete q;
		}
	return result;
}
Пример #20
0
GiSTlist<MTentry *>
MTnode::RangeSearch (const MTquery &query)
{
	GiSTlist<MTentry *> results;

	if (IsLeaf()) {
		for (int i=0; i<NumEntries(); i++) {
			MTentry *entry = (MTentry *) (*this)[i].Ptr()->Copy();
			MTquery *newQuery = (MTquery *) query.Copy();
			if (newQuery->Consistent(*entry)) {  // object qualifies
				entry->SetMaxRadius(newQuery->Grade());
				results.Append (entry);
			} else {
				delete entry;
			}
			delete newQuery;
		}
	} else {
		for (int i=0; i<NumEntries(); i++) {
			MTentry *entry = (MTentry *) (*this)[i].Ptr();
			MTquery *newQuery = (MTquery *) query.Copy();
			if (newQuery->Consistent(*entry)) {  // sub-tree included
				GiSTpath childPath = Path ();
				childPath.MakeChild (entry->Ptr());
				MTnode *childNode = (MTnode *) ((MT *)Tree())->ReadNode(childPath);
				GiSTlist<MTentry *> childResults = childNode->RangeSearch(*newQuery);  // recurse the search
				while (!childResults.IsEmpty()) {
					results.Append (childResults.RemoveFront());
				}
				delete childNode;
			}
			delete newQuery;
		}
	}

	return results;
}
Пример #21
0
void
MTnode::mMRadius(MTentry *e) const
{
	for (int i=0; i<NumEntries(); i++) {
		MTentry *mte=(MTentry *)(*this)[i].Ptr();

		mte->Key()->recomp=FALSE;
		if (mte->Key()->distance<0) {	// this code should be unreachable
			cout << "Computing distance with " << mte << "??????????????????????????????????????????????\n";	// this code should be unreachable
			mte->Key()->distance=obj->distance(mte->object());
		}
		if (mte->Key()->distance+mte->maxradius()>e->maxradius()) e->setmaxradius(mte->Key()->distance+mte->maxradius());
		if (MAX(mte->Key()->distance-mte->maxradius(), 0)<e->minradius()) e->setminradius(MAX(mte->Key()->distance-mte->maxradius(), 0));
	}
}
Пример #22
0
void 
GiSTnode::Print (ostream& os) const
{
	os << path << " #Entries: " << NumEntries() << ", ";
	os << "Level " << Level();
	if (IsLeaf()) {
		os << "(Leaf)";
	} else {
		os << "(Internal)";
	}
	os << ", Sibling: " << Sibling();
	os << ", Size: " << Size() << "/" << tree->Store()->PageSize() << endl;
	for (int i=0; i<numEntries; i++) {
		(*this)[i]->Print(os);
	}
}
Пример #23
0
GiSTentry* 
BTnode::Union() const
{
  BTentry *u = new BTentry;
  int first = 1;

  for (int i=0; i<NumEntries(); i++) {
      BTentry *bte = (BTentry*) (*this)[i].Ptr();
      if (first || bte->LowerBound() < u->LowerBound())
	  u->SetLowerBound(bte->LowerBound());
      if (first || bte->UpperBound() > u->UpperBound())
	  u->SetUpperBound(bte->UpperBound());
      first = 0;
  }

//u->SetPtr(node.Path().Page());
  return u;
}
Пример #24
0
void 
GiSTnode::Pack(char *page) const
{
  // Pack the header
  GiSTheader *h  = (GiSTheader *) page;
  h->level     = Level();
  h->numEntries = NumEntries();
  h->sibling    = Sibling();

  int fixlen = FixedLength();
  GiSTlte *ltable = (GiSTlte *) (page+tree->Store()->PageSize());
  GiSTlte ltptr = GIST_PAGE_HEADER_SIZE;

  for (int i=0; i<numEntries; i++) {
      GiSTcompressedEntry compressedEntry = (*this)[i]->Compress();

      if (fixlen)
	  assert(fixlen == compressedEntry.keyLen);

      // Copy the entry onto the page
      if (compressedEntry.keyLen > 0)
	  memcpy(page+ltptr,
		 compressedEntry.key,
		 compressedEntry.keyLen);

      memcpy(page+ltptr+compressedEntry.keyLen,
	     &compressedEntry.ptr,
	     sizeof(GiSTpage));

      // Be tidy
      if (compressedEntry.key)
	delete compressedEntry.key;

      // Enter a pointer to the entry in the line table
      if (!fixlen) *--ltable = ltptr;

      int entryLen = compressedEntry.keyLen + sizeof(GiSTpage);
      ltptr += entryLen;
  }

  // Store extra line table entry so we know last entry's length
  *--ltable = ltptr;
}
Пример #25
0
void
MTnode::mMRadius (MTentry *unionEntry) const
{
	for (int i=0; i<NumEntries(); i++) {
		MTentry *entry = (MTentry *) (*this)[i].Ptr();
		entry->Key()->splitted = FALSE;
		if (entry->Key()->distance < 0) {
			entry->Key()->distance = obj->distance(entry->object());
		}

		double tempMax = entry->Key()->distance + entry->MaxRadius();
		if (tempMax > unionEntry->MaxRadius()) {
			unionEntry->SetMaxRadius(tempMax);
		}
		double tempMin = MAX(entry->Key()->distance - entry->MaxRadius(), 0);
		if (tempMin < unionEntry->MinRadius()) {
			unionEntry->SetMinRadius(tempMin);
		}
	}
}
Пример #26
0
int *
MTnode::PickCandidates ()
{
	int n = NumEntries ();
	BOOL *bUsed = new BOOL[n];
	for (int i=0; i<n; i++) {
		bUsed[i] = ((MTentry *)(*this)[i].Ptr())->Key()->distance == 0;  // exclude parent entry
	}

	int count = MIN (NUM_CANDIDATES, n-1), *results = new int[count];
	// insert in results the indices of the candidates for promotion
	for (int i=0; i<count; i++) {
		int j;
		do {
			j = PickRandom (0, n);
		} while (bUsed[j]);
		results[i] = j;
		bUsed[j] = TRUE;
	}

	delete []bUsed;
	return results;
}
Пример #27
0
// SearchMinPenalty returns where a new entry should be inserted.
// Overriden to insert the distance from the parent in the new entry.
GiSTpage
MTnode::SearchMinPenalty(const GiSTentry& newEntry) const
{
	MTentry *minEntry=NULL;
	MTpenalty *minPenalty=NULL;

	for(int i=0; i<NumEntries(); i++) {
		MTentry *e=(MTentry *)((*this)[i].Ptr());

		assert((MTnode *)e->Node()==this);
		MTpenalty *penalty=(MTpenalty *)e->Penalty(newEntry, minPenalty);	// use the alternate Penalty method in order to avoid some distance computations

		if((minEntry==NULL)||(*penalty)<(*minPenalty)) {
			minEntry=e;
			if(minPenalty) delete minPenalty;
			minPenalty=penalty;
		}
		else delete penalty;
	}
	((MTentry&)newEntry).Key()->distance=minPenalty->distance;
	delete minPenalty;
	return minEntry->Ptr();
}
Пример #28
0
void
MTnode::Split (MTnode *node, int *lArray, int *rArray, int *lDel, int *rDel)
{
	*lDel = *rDel = 0;
	int n = NumEntries ();
	double *lDist = new double[n], *rDist = new double[n];
	for (int i=0; i<n; i++) {  // compute the distance between entries and their parent entry
		lDist[i] = Distance (i);
		rDist[i] = node->Distance(i);
	}
	// balance entries up to minimum utilization
	while (*lDel < n*MIN_UTIL && *rDel < n*MIN_UTIL) {
		int i = FindMin (lDist, n);
		((MTentry *)(*this)[i].Ptr())->Key()->distance = lDist[i];
		((MTentry *)(*node)[i].Ptr())->Key()->distance = rDist[i];
		rArray[(*rDel)++] = i;
		lDist[i] = rDist[i] = MAXDOUBLE;
		i = FindMin (rDist, n);
		if (i >= 0) {
			((MTentry *)(*node)[i].Ptr())->Key()->distance = rDist[i];
			((MTentry *)(*this)[i].Ptr())->Key()->distance = lDist[i];
			lArray[(*lDel)++] = i;
			lDist[i] = rDist[i] = MAXDOUBLE;
		}
	}
	// then perform the hyperplane split (assigning each entry to its nearest node)
	for (int i=0; i<n; i++) {
		if (rDist[i] == MAXDOUBLE) {  // entry have been assigned through balanced policy
			continue;
		}
		((MTentry *)(*this)[i].Ptr())->Key()->distance = lDist[i];
		((MTentry *)(*node)[i].Ptr())->Key()->distance = rDist[i];
		((MTentry *)(*this)[i].Ptr())->Key()->distance < ((MTentry *)(*node)[i].Ptr())->Key()->distance ? rArray[(*rDel)++] = i : lArray[(*lDel)++] = i;
	}
	delete []rDist;
	delete []lDist;
}
Пример #29
0
void
MTnode::Split(MTnode *node, int *leftvec, int *rightvec, int *leftdeletes, int *rightdeletes)
{
	int i;

	*rightdeletes=0;
	*leftdeletes=0;
//	cout << "Now splitting between:\n";
//	cout << obj << " & " << node->obj << endl;
	switch(SPLIT_FUNCTION) {
		case G_HYPERPL: {
			int numentries=NumEntries();
			double *rightdistances=new double[numentries], *leftdistances=new double[numentries];

			for(i=0; i<numentries; i++) {
				leftdistances[i]=distance(i);
				rightdistances[i]=node->distance(i);
			}
			while((*rightdeletes<numentries*MIN_UTIL)&&(*leftdeletes<numentries*MIN_UTIL)) {	// balance entries up to minimum utilization (assigning to each node its remaining nearest entry)
				i=FindMin(leftdistances, numentries);
				((MTentry *)(*this)[i].Ptr())->Key()->distance=leftdistances[i];
				((MTentry *)(*node)[i].Ptr())->Key()->distance=rightdistances[i];
//				cout << (*this)[i].Ptr() << " (" << leftdistances[i] << ", " << rightdistances[i] << ") to the left\n";
				rightvec[(*rightdeletes)++]=i;
				rightdistances[i]=MAXDOUBLE;
				leftdistances[i]=MAXDOUBLE;
				i=FindMin(rightdistances, numentries);
				if(i>=0) {
					((MTentry *)(*node)[i].Ptr())->Key()->distance=rightdistances[i];
					((MTentry *)(*this)[i].Ptr())->Key()->distance=leftdistances[i];
//					cout << (*node)[i].Ptr() << " (" << leftdistances[i] << ", " << rightdistances[i] << ") to the right\n";
					leftvec[(*leftdeletes)++]=i;
					rightdistances[i]=MAXDOUBLE;
					leftdistances[i]=MAXDOUBLE;
				}
			}
			for(i=0; i<numentries; i++) {	// then perform the hyperplane split (assigning each entry to its nearest node)
				if(rightdistances[i]==MAXDOUBLE) continue;
//				((MTentry *)(*this)[i].Ptr())->Key()->distance=distance(i)+((MTentry *)(*this)[i].Ptr())->maxradius();
//				((MTentry *)(*node)[i].Ptr())->Key()->distance=node->distance(i)+((MTentry *)(*node)[i].Ptr())->maxradius();
				((MTentry *)(*this)[i].Ptr())->Key()->distance=leftdistances[i];
				((MTentry *)(*node)[i].Ptr())->Key()->distance=rightdistances[i];
				if (((MTentry *)(*this)[i].Ptr())->Key()->distance<((MTentry *)(*node)[i].Ptr())->Key()->distance) {
//					cout << (*this)[i].Ptr() << " (" << ((MTentry *)(*this)[i].Ptr())->Key()->distance << ", " << ((MTentry *)(*node)[i].Ptr())->Key()->distance << ") to the left\n";
					rightvec[(*rightdeletes)++]=i;
				}
				else {
//					cout << (*node)[i].Ptr() << " (" << ((MTentry *)(*this)[i].Ptr())->Key()->distance << ", " << ((MTentry *)(*node)[i].Ptr())->Key()->distance << ") to the right\n";
					leftvec[(*leftdeletes)++]=i;
				}
			}
			delete []rightdistances;
			delete []leftdistances;
			break;
		}
		case BAL_G_HYPERPL: {
			int numentries=NumEntries(), j;

			for(i=0; i<NumEntries(); i++) {	// assign the parents' entries
				if(obj==&((MTentry *)((*this)[i].Ptr()))->object()) {
//					cout << (*this)[i].Ptr() << " to the left\n";
					((MTentry *)(*this)[i].Ptr())->Key()->distance=0;
					rightvec[(*rightdeletes)++]=i;
				}
				if(node->obj==&((MTentry *)((*node)[i].Ptr()))->object()) {
//					cout << (*node)[i].Ptr() << " to the right\n";
					((MTentry *)(*node)[i].Ptr())->Key()->distance=0;
					leftvec[(*leftdeletes)++]=i;
				}
			}
			for(i=0; (*rightdeletes<(numentries+1)/2)&&(*leftdeletes<(numentries+1)/2); i++) {	// perform the hyperplane split up to a node utilization of the 50%
				if((obj!=&((MTentry *)((*this)[i].Ptr()))->object())&&(node->obj!=&((MTentry *)((*node)[i].Ptr()))->object())) {	// the parents' entries were already assigned
					((MTentry *)(*this)[i].Ptr())->Key()->distance=distance(i);
					((MTentry *)(*node)[i].Ptr())->Key()->distance=node->distance(i);
					if (((MTentry *)(*this)[i].Ptr())->Key()->distance<((MTentry *)(*node)[i].Ptr())->Key()->distance) {
//						cout << (*this)[i].Ptr() << " (" << ((MTentry *)(*this)[i].Ptr())->Key()->distance << ", " << ((MTentry *)(*node)[i].Ptr())->Key()->distance << ") to the left\n";
						rightvec[(*rightdeletes)++]=i;
					}
					else {
//						cout << (*node)[i].Ptr() << " (" << ((MTentry *)(*this)[i].Ptr())->Key()->distance << ", " << ((MTentry *)(*node)[i].Ptr())->Key()->distance << ") to the right\n";
						leftvec[(*leftdeletes)++]=i;
					}
				}
			}
			// then balance the remaining entries
			for(j=*rightdeletes; j<numentries/2; j++, i++)
				if((obj!=&((MTentry *)((*this)[i].Ptr()))->object())&&(node->obj!=&((MTentry *)((*node)[i].Ptr()))->object())) {	// the parents' entries were already assigned
					((MTentry *)(*this)[i].Ptr())->Key()->distance=distance(i);
					((MTentry *)(*node)[i].Ptr())->Key()->distance=-maxDist();
//					cout << (*this)[i].Ptr() << " (" << ((MTentry *)(*this)[i].Ptr())->Key()->distance << ") to the left\n";
					rightvec[(*rightdeletes)++]=i;
				}
				else j--;
			for(j=*leftdeletes; j<numentries/2; j++, i++)
				if((obj!=&((MTentry *)((*this)[i].Ptr()))->object())&&(node->obj!=&((MTentry *)((*node)[i].Ptr()))->object())) {	// the parents' entries were already assigned
					((MTentry *)(*node)[i].Ptr())->Key()->distance=node->distance(i);
					((MTentry *)(*this)[i].Ptr())->Key()->distance=-maxDist();
//					cout << (*node)[i].Ptr() << " (" << ((MTentry *)(*node)[i].Ptr())->Key()->distance << ") to the right\n";
					leftvec[(*leftdeletes)++]=i;
				}
				else j--;
			break;
		}
		case BALANCED: {	// assign iteratively to each node its remaining nearest entry
			int numentries=NumEntries();
			double *rightdistances=new double[numentries], *leftdistances=new double[numentries];

			for(i=0; i<numentries; i++) {
				leftdistances[i]=distance(i);
				rightdistances[i]=node->distance(i);
			}
			while((*rightdeletes<(numentries+1)/2)&&(*leftdeletes<(numentries+1)/2)) {
				i=FindMin(leftdistances, numentries);
				((MTentry *)(*this)[i].Ptr())->Key()->distance=leftdistances[i];
				((MTentry *)(*node)[i].Ptr())->Key()->distance=rightdistances[i];
//				cout << (*this)[i].Ptr() << " (" << leftdistances[i] << ", " << rightdistances[i] << ") to the left\n";
				rightvec[(*rightdeletes)++]=i;
				rightdistances[i]=MAXDOUBLE;
				leftdistances[i]=MAXDOUBLE;
				i=FindMin(rightdistances, numentries);
				if(i>=0) {
					((MTentry *)(*node)[i].Ptr())->Key()->distance=rightdistances[i];
					((MTentry *)(*this)[i].Ptr())->Key()->distance=leftdistances[i];
//					cout << (*node)[i].Ptr() << " (" << leftdistances[i] << ", " << rightdistances[i] << ") to the right\n";
					leftvec[(*leftdeletes)++]=i;
					rightdistances[i]=MAXDOUBLE;
					leftdistances[i]=MAXDOUBLE;
				}
			}
			delete []rightdistances;
			delete []leftdistances;
			break;
		}
	}
}
Пример #30
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;
}