ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Tree-M/MT/MT.cpp
Revision: 1.1
Committed: Sun May 6 00:45:52 2001 UTC (23 years, 1 month ago) by root
Branch: MAIN
CVS Tags: HEAD
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*********************************************************************
2     * *
3     * Copyright (c) 1997,1998, 1999 *
4     * Multimedia DB Group and DEIS - CSITE-CNR, *
5     * University of Bologna, Bologna, ITALY. *
6     * *
7     * All Rights Reserved. *
8     * *
9     * Permission to use, copy, and distribute this software and its *
10     * documentation for NON-COMMERCIAL purposes and without fee is *
11     * hereby granted provided that this copyright notice appears in *
12     * all copies. *
13     * *
14     * THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE *
15     * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING *
16     * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, *
17     * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHOR *
18     * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A *
19     * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS *
20     * DERIVATIVES. *
21     * *
22     *********************************************************************/
23    
24     #include <stdlib.h>
25     #include "list.h"
26     #include "MT.h"
27     #include "MTpredicate.h"
28     #include "MTcursor.h"
29    
30     #ifdef _WIN32 // these functions are defined under UNIX
31     void srandom(int seed) { srand(seed); }
32     int random() { return rand(); }
33     #endif
34    
35     TruePredicate truePredicate;
36    
37     int
38     PickRandom(int from, int to)
39     {
40     return (random()%(to-from))+from;
41     }
42    
43     MTnode *
44     MT::ParentNode(MTnode *node)
45     {
46     GiSTpath path=node->Path();
47     MTnode *parentnode;
48    
49     path.MakeParent();
50     parentnode=(MTnode *)ReadNode(path);
51     return parentnode; // parentnode should be destroyed by the caller
52     }
53    
54     void
55     MT::CollectStats()
56     {
57     /*#if defined(_DEBUG)
58     CMemoryState msOld, msNew, msDif;
59     msOld.Checkpoint();
60     #endif */
61     GiSTpath path;
62     GiSTnode *node;
63    
64     path.MakeRoot();
65     node=ReadNode(path);
66     if(!node->IsLeaf()) {
67     TruePredicate truePredicate;
68     GiSTlist<GiSTentry*> list=node->Search(truePredicate); // retrieve all the children
69     double *areas, *radii, totarea=0;
70     int *n, maxn=node->Level(), totn=1, i;
71    
72     areas=new double[maxn];
73     radii=new double[maxn];
74     n=new int[maxn];
75     for(i=0; i<maxn; i++) {
76     n[i]=0;
77     areas[i]=0;
78     radii[i]=0;
79     }
80     delete node;
81     while(!list.IsEmpty()) {
82     GiSTentry *e=list.RemoveFront();
83     GiSTlist<GiSTentry*> newlist;
84    
85     path.MakeChild(e->Ptr());
86     node=ReadNode(path);
87     n[node->Level()]++;
88     areas[node->Level()]+=((MTkey *)e->Key())->area();
89     radii[node->Level()]+=((MTkey *)e->Key())->maxradius();
90     if(!node->IsLeaf()) newlist=node->Search(truePredicate); // recurse to next level
91     while(!newlist.IsEmpty()) list.Append(newlist.RemoveFront());
92     path.MakeParent();
93     delete e;
94     delete node;
95     }
96     // output the results
97     cout << "Level:\tPages:\tRadius:\tArea:\n";
98     for(i=maxn-1; i>=0; i--) {
99     totn+=n[i];
100     totarea+=areas[i];
101     cout << i << ":\t" << n[i] << "\t" << radii[i]/n[i] << "\t" << areas[i]/n[i] << endl;
102     }
103     cout << "tot:\t" << totn << "\t" << totarea << endl;
104     delete []areas;
105     delete []radii;
106     delete []n;
107     }
108     else delete node;
109     /* #if defined(_DEBUG)
110     msNew.Checkpoint();
111     msDif.Difference(msOld, msNew);
112     msDif.DumpStatistics();
113     #endif */
114     }
115    
116     BOOL
117     MT::CheckNode(GiSTpath path, MTentry *e)
118     {
119     MTnode *node=(MTnode *)ReadNode(path);
120     BOOL ret=TRUE;
121    
122     for(int i=0; (i<node->NumEntries())&&ret; i++) {
123     MTentry *child=(MTentry *)(*node)[i].Ptr();
124    
125     if((e!=NULL)&&(((child->Key()->distance+child->maxradius())>e->maxradius())||(child->object().distance(e->object())!=child->Key()->distance))) {
126     cout << "Error with entry " << child << "in " << node;
127     ret=FALSE;
128     }
129     path.MakeChild(child->Ptr());
130     if(!node->IsLeaf()) ret&=CheckNode(path, child);
131     path.MakeParent();
132     }
133     delete node;
134     return ret;
135     }
136    
137     GiSTlist<MTentry *>
138     MT::RangeSearch(const MTquery& query)
139     {
140     GiSTpath path;
141    
142     path.MakeRoot();
143     MTnode *root=(MTnode *)ReadNode(path);
144     GiSTlist<MTentry *> list=root->RangeSearch(query);
145    
146     delete root;
147     return list;
148     }
149    
150     MTentry **
151     MT::TopSearch(const TopQuery& query)
152     {
153     GiSTpath path; // path for retrieving root node
154     MTnode *node; // next node to be examined
155     MTentry **results=new MTentry*[query.k]; // the results list (ordered for increasing distances)
156     list<dst *> queue(comparedst); // list for ordering the nodes
157     SimpleQuery q(query.Pred(), maxDist(), TRUE);
158     double *dists=new double[query.k]; // array containing the NN distances
159     int i;
160    
161     for (i=0; i<query.k; i++) dists[i]=maxDist(); // initialization of the NN-distances array
162     path.MakeRoot();
163     node=(MTnode *)ReadNode(path); // retrieve the root node
164     while(node!=NULL) { // examine current node
165     double oldDist=q.Grade();
166    
167     // search the first children to be examined
168     // cout << "Examining node " << node->Path() << endl;
169     for(unsigned int i=0; i<node->NumEntries(); i++) { // for each entry in the current node
170     MTentry *e=(MTentry *)((*node)[i].Ptr());
171    
172     q.SetGrade(oldDist);
173     // cout << "range=" << q.Radius() << ", oldDist=" << q.Grade() << ": Checking " << e;
174     if(q.Consistent(*e)) { // check if the entry is consistent with the query
175     // cout << "grade=" << q.Grade() << endl;
176     if(e->IsLeaf()) { // object qualifies
177     if(dists[query.k-1]<maxDist()) delete results[query.k-1]; // delete last element of the results list
178    
179     MTentry *key=(MTentry *)e->Copy();
180     int j=0;
181    
182     key->setminradius(0);
183     key->setmaxradius(q.Grade()); // we insert the actual distance from the query object as the key radius
184     // insert dist in the results list (sorting for incr. distance)
185     // could be improved using binary search
186     while(dists[j]<q.Grade()) j++;
187     // cout << "\tInserted (" << q.Grade() << "<" << dists[query.k-1] << ") into list in position " << j << endl;
188     for(int l=query.k-1; l>j; l--) { // shift up results array
189     results[l]=results[l-1];
190     dists[l]=dists[l-1];
191     }
192     results[j]=key;
193     dists[j]=q.Grade();
194     q.SetRadius(dists[query.k-1]);
195     }
196     else { // we have to insert the child node in the priority queue
197     GiSTpath path=node->Path();
198     double dmin=q.Grade()-e->maxradius(), dmax=q.Grade()+e->maxradius(); // these are lower- and upper-bounds on the distances of the descendants of the entry from the query object
199    
200     if(dmin<0) dmin=0;
201     // insert the node in the stack (sorting for decr. level and incr. LB on distance)
202     // could be improved using binary search
203     path.MakeChild(e->Ptr());
204     dst *d=new dst(path, dmin, q.Grade());
205    
206     queue.Insert(d);
207     // cout << "\tInserted (" << dmin << "<" << dists[query.k-1] << ") into list\n";
208     }
209     }
210     else {
211     // cout << "\tPruned (" << q.Grade() << ">" << dists[query.k-1] << ") from the list\n";
212     // if we're in a "true" leaf node (i.e. not in the root) and last entry was pruned, we can safely prune all other entries too
213     // if(e->IsLeaf()&&(!e->Node()->Path().IsRoot())&&(fabs(e->Key()->distance-oldDist)>q.Grade()))) break;
214     }
215     }
216     // the next entry to be chosen is that whose distance from the parent is most similar to the distance between the parent and the query object
217     delete node; // delete examined node
218     if(!queue.IsEmpty()) { // retrieve next node to be examined
219     dst *d=queue.RemoveFirst();
220    
221     if(d->Bound()>=dists[query.k-1]) { // terminate the search
222     while(!queue.IsEmpty())
223     delete queue.RemoveFirst();
224     node=NULL;
225     }
226     else {
227     node=(MTnode *)ReadNode(d->Path());
228     q.SetGrade(d->Dist());
229     }
230     delete d;
231     }
232     else node=NULL; // terminate the search
233     }
234     delete []dists;
235     return results;
236     }