ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Tree-M/MT/Main.cpp
Revision: 1.1
Committed: Sun May 6 00:45:53 2001 UTC (25 years, 4 months 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 <stdio.h>
25     #include <fstream.h>
26     #include <time.h>
27     #include <malloc.h>
28     #ifdef UNIX
29     #include <unistd.h>
30     #include <ctype.h>
31     #endif
32    
33     #include "MT.h"
34     #include "MTpredicate.h"
35    
36     #define IndObjs 11648
37    
38     int compdists;
39     int IOread, IOwrite;
40     int objs;
41     int dimension=2;
42     double eps;
43    
44     language query_language=FUZZY_STANDARD;
45     dist2sim hfunction=LINEAR;
46    
47     extern double MIN_UTIL;
48     extern pp_function PROMOTE_PART_FUNCTION;
49     extern pv_function PROMOTE_VOTE_FUNCTION;
50     extern pp_function SECONDARY_PART_FUNCTION;
51     extern r_function RADIUS_FUNCTION;
52     extern int NUM_CANDIDATES;
53     extern s_function SPLIT_FUNCTION;
54    
55     MT *gist=NULL;
56    
57     int debug=0;
58    
59     // close the tree and delete it
60     void
61     CommandClose()
62     {
63     if(gist) {
64     delete gist;
65     gist=NULL;
66     }
67     }
68    
69     // create a new tree and open it
70     void
71     CommandCreate(const char *method, const char *table)
72     {
73     CommandClose();
74     if(!strcmp(method, "mtree")) gist=new MT;
75     else {
76     cerr << "The only supported method is mtree.\n";
77     return;
78     }
79     gist->Create(table);
80     if(!gist->IsOpen()) {
81     cout << "Error opening index.\n";
82     delete gist;
83     return;
84     }
85     cout << "Table " << table << " created as type " << method << ".\n";
86     }
87    
88     // delete the tree from disk
89     void
90     CommandDrop(const char *table)
91     {
92     if (unlink(table)) cout << "There is no table by that name.\n";
93     else cout << "Table " << table << " dropped.\n";
94     }
95    
96     // open the specified tree
97     void
98     CommandOpen(const char *method, const char *table)
99     {
100     CommandClose();
101     if(!strcmp(method, "mtree")) gist=new MT;
102     else {
103     cerr << "The only supported method is mtree.\n";
104     return;
105     }
106     gist->Open(table);
107     if(!gist->IsOpen()) {
108     delete gist;
109     cout << "Error opening table.\n";
110     return;
111     }
112     // cout << "Table " << table << " opened.\n";
113     }
114    
115     // execute a nearest neighbor query
116     void
117     CommandNearest(const TopQuery &query)
118     {
119     // cout << "Searching " << query.Pred() << "...\n";
120     MTentry **results=gist->TopSearch(query);
121    
122     for(unsigned int i=0; i<query.k; i++) {
123     MTentry *e=results[i];
124     // cout << e;
125     // cout << e->Ptr() << " ";
126     delete e;
127     objs++;
128     }
129     // cout << endl;
130     delete []results;
131     }
132    
133     // execute a range query
134     void
135     CommandSelect(MTquery& query)
136     {
137     GiSTlist<MTentry *> list=gist->RangeSearch(query);
138    
139     while(!list.IsEmpty()) {
140     MTentry *e=list.RemoveFront();
141     // cout << e;
142     delete e;
143     objs++;
144     }
145     /*#if defined(_DEBUG)
146     CMemoryState msOld, msNew, msDif;
147     msOld.Checkpoint();
148     #endif
149     #if defined(_DEBUG)
150     msNew.Checkpoint();
151     msDif.Difference(msOld, msNew);
152     msDif.DumpStatistics();
153     #endif */
154     }
155    
156     // delete the objects satisfying the predicate
157     void
158     CommandDelete(const GiSTpredicate& pred)
159     {
160     gist->Delete(pred);
161     }
162    
163     // insert an object in the tree
164     void
165     CommandInsert(const MTkey& key, int ptr)
166     {
167     gist->Insert(MTentry(key, (GiSTpage)ptr));
168     // cout << key << "->" << ptr << " inserted into " << table << ".\n";
169     }
170    
171     // use the BulkLoading alogrithm to create the tree
172     void
173     CommandLoad(const char *table, MTentry **data, int n)
174     {
175     CommandDrop(table);
176     CommandCreate("mtree", table);
177     // if(gist==NULL) printf("M3 NULL!!\n");
178     printf("MinUtil=%f\n", MIN_UTIL);
179     gist->BulkLoad(data, n, 1, "tmp");
180     }
181    
182     // close the tree and exit
183     void
184     CommandQuit()
185     {
186     CommandClose();
187     cout << "Goodbye.\n";
188     // exit(0);
189     }
190    
191     // print the prompt
192     void
193     CommandPrompt()
194     {
195     cout << "MTree> ";
196     cout.flush();
197     }
198    
199     // activate the debug mode (currently unavailable)
200     void
201     CommandDebug()
202     {
203     debug=!debug;
204     cout << "Debugging Output ";
205     cout << (debug ? "ON\n" : "OFF\n");
206     }
207    
208     // print the help file (currently unavailable)
209     void
210     CommandHelp()
211     {
212     ifstream is("MTree.help");
213     char c;
214    
215     while(is.get(c)) cout << c;
216     }
217    
218     // perform a check of the nodes of the tree
219     void
220     CommandCheck()
221     {
222     GiSTpath path;
223     path.MakeRoot();
224     gist->CheckNode(path, NULL);
225     }
226    
227     // print a dump of each node of the tree
228     void
229     CommandDump()
230     {
231     GiSTpath path;
232     path.MakeRoot();
233     #ifdef PRINTING_OBJECTS
234     gist->DumpNode(cout, path);
235     #endif
236     }
237    
238     // collect and print statistics on the tree
239     void
240     CommandStats()
241     {
242     gist->CollectStats();
243     }
244    
245     int main(int argc, char **argv)
246     {
247     cerr << "Now starting...\n";
248     malloc_stats();
249     int i=1;
250     char cmdLine[15];
251     BOOL end=FALSE;
252    
253     compdists=IOread=IOwrite=objs=0;
254     cout << "** MTree: An M-Tree based on Generalized Search Trees\n";
255     while(strcmp(cmdLine, "quit")) {
256     scanf("%s", cmdLine);
257     if(!strcmp(cmdLine, "drop")) {
258     CommandDrop("graphs.M3");
259     if(argc<5) {
260     cout << "Usage is: MTree [min_util] [split_f] [promote_f] [sec_promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
261     exit(-1);
262     }
263     MIN_UTIL=atof(argv[1]);
264     SPLIT_FUNCTION=(s_function)atoi(argv[2]);
265     PROMOTE_PART_FUNCTION=(pp_function)atoi(argv[3]);
266     SECONDARY_PART_FUNCTION=(pp_function)atoi(argv[4]);
267     if(SECONDARY_PART_FUNCTION==CONFIRMED) {
268     cout << "The secondary promotion function must be an unconfirmed one\n";
269     exit(-1);
270     }
271     if(PROMOTE_PART_FUNCTION==SAMPLING) {
272     if(argc<6) {
273     cout << "Usage is: MTree [min_util] [split_f] [promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
274     exit(-1);
275     }
276     NUM_CANDIDATES=atoi(argv[5]);
277     }
278     if(PROMOTE_PART_FUNCTION==CONFIRMED) {
279     if(argc<6) {
280     cout << "Usage is: MTree [min_util] [split_f] [promote_f] [sec_promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
281     exit(-1);
282     }
283     PROMOTE_VOTE_FUNCTION=(pv_function)atoi(argv[5]);
284     if(PROMOTE_VOTE_FUNCTION==SAMPLINGV) {
285     if(argc<7) {
286     cout << "Usage is: MTree [min_util] [split_f] [promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
287     exit(-1);
288     }
289     NUM_CANDIDATES=atoi(argv[6]);
290     }
291     else if(PROMOTE_VOTE_FUNCTION==mM_RAD) {
292     if(argc<7) {
293     cout << "Usage is: MTree [min_util] [split_f] [promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
294     exit(-1);
295     }
296     RADIUS_FUNCTION=(r_function)atoi(argv[6]);
297     }
298     }
299     switch(SPLIT_FUNCTION) {
300     case G_HYPERPL:
301     cout << "G_HYPL, ";
302     break;
303     case BAL_G_HYPERPL:
304     cout << "BAL_G_HYPL, ";
305     break;
306     case BALANCED:
307     cout << "BAL, ";
308     break;
309     }
310     switch(PROMOTE_PART_FUNCTION) {
311     case RANDOM:
312     cout << "RAN_2 ";
313     break;
314     case MAX_UB_DIST:
315     cout << "M_UB_d ";
316     break;
317     case SAMPLING:
318     cout << "SAMP" << NUM_CANDIDATES << "_2 ";
319     break;
320     case MIN_RAD:
321     cout << "m_R_2 ";
322     break;
323     case MIN_OVERLAPS:
324     cout << "m_O_2 ";
325     break;
326     case CONFIRMED:
327     switch(PROMOTE_VOTE_FUNCTION) {
328     case RANDOMV:
329     cout << "RAN_1 ";
330     break;
331     case SAMPLINGV:
332     cout << "SAMP" << NUM_CANDIDATES << "_1 ";
333     break;
334     case MAX_LB_DIST:
335     cout << "M_LB_d ";
336     break;
337     case mM_RAD:
338     cout << "mM_";
339     switch(RADIUS_FUNCTION) {
340     case LB:
341     cout << "m";
342     break;
343     case AVG:
344     cout << "A";
345     break;
346     case UB:
347     cout << "M";
348     break;
349     }
350     cout << "_r ";
351     break;
352     }
353     break;
354     }
355     switch(SECONDARY_PART_FUNCTION) {
356     case RANDOM:
357     cout << "(RAN_2)\n";
358     break;
359     case MAX_UB_DIST:
360     cout << "(M_UB_d)\n";
361     break;
362     case SAMPLING:
363     cout << "(SAMP" << NUM_CANDIDATES << "_2)\n";
364     break;
365     case MIN_RAD:
366     cout << "(m_R_2)\n";
367     break;
368     case MIN_OVERLAPS:
369     cout << "(m_O_2)\n";
370     break;
371     }
372     CommandCreate("mtree", "graphs.M3");
373     }
374     else if(!strcmp(cmdLine, "select")) {
375     Object *obj=Read();
376     Pred *pred=new Pred(*obj);
377     double r;
378    
379     scanf("%s", cmdLine);
380     r=atof(cmdLine);
381    
382     SimpleQuery query(pred, r);
383    
384     delete obj;
385     delete pred;
386     if(!gist) CommandOpen("mtree", "graphs.M3");
387     CommandSelect(query);
388     CommandClose();
389     }
390     else if((!strcmp(cmdLine, "nearest"))||(!strcmp(cmdLine, "farthest"))) {
391     int k;
392     BOOL nearest=strcmp(cmdLine, "farthest");
393     MTpred *pred;
394     Object *obj=Read();
395    
396     scanf("%s", cmdLine);
397     k=atoi(cmdLine);
398     if(nearest) pred=new Pred(*obj);
399     else {
400     MTpred *npred=new Pred(*obj);
401    
402     pred=new NotPred(npred);
403     delete npred;
404     }
405     // eps=atof(argv[1]);
406     TopQuery query(pred, k);
407    
408     delete pred;
409     if(!gist) CommandOpen("mtree", "graphs.M3");
410     CommandNearest(query);
411     CommandClose();
412     delete obj;
413     }
414     else if(!strcmp(cmdLine, "cursor")) {
415     Object *obj=Read();
416     Pred pred(*obj);
417    
418     if(!gist) CommandOpen("mtree", "graphs.M3");
419     MTcursor cursor(*gist, pred);
420    
421     scanf("%s", cmdLine);
422     while(strcmp(cmdLine, "close")) {
423     if(!strcmp(cmdLine, "next")) {
424     int k;
425     GiSTlist<MTentry *> list;
426    
427     scanf("%s", cmdLine);
428     k=atoi(cmdLine);
429    
430     // cout << "Fetching next " << k << " entries...\n";
431     for(; k>0; k--) list.Append(cursor.Next());
432     while(!list.IsEmpty()) {
433     MTentry *e=list.RemoveFront();
434     // cout << e;
435     delete e;
436     objs++;
437     }
438     }
439     scanf("%s", cmdLine);
440     }
441     delete obj;
442     CommandClose();
443     }
444     /* else if(!strcmp(cmdLine, "find")) {
445     int n, k, l, oldcompdists, oldIOread, oldobjs;
446    
447     scanf("%s", cmdLine);
448     n=atoi(cmdLine);
449    
450     double **x=(double **)calloc(n, sizeof(double *));
451     for(i=0; i<n; i++) x[i]=(double *)calloc(dimension, sizeof(double));
452     MTpred **p=(MTpred **)calloc(n, sizeof(MTpred *));
453     AndPred **ap=(AndPred **)calloc(n-1, sizeof(AndPred *));
454    
455     for(i=0; i<n; i++) {
456     for(int j=0; j<dimension; j++) {
457     scanf("%s", cmdLine);
458     x[i][j]=atof(cmdLine);
459     }
460     if(x[i][0]>=0) {
461     Object obj(x[i]);
462     // cout << "obj=" << obj << endl;
463     p[i]=new Pred(obj);
464     }
465     else {
466     x[i][0]=-x[i][0];
467     Object obj(x[i]);
468     // cout << "obj=" << obj << endl;
469     Pred *pr=new Pred(obj);
470     p[i]=new NotPred(pr);
471     delete pr;
472     }
473     // cout << "pred=" << *p[i] << endl;
474     }
475     if(n==2) cout << "d=" << p[1]->distance(((Pred *)p[0])->obj()) << endl;
476     ap[0]=new AndPred(p[0], p[1]);
477     for(i=1; i<n-1; i++) ap[i]=new AndPred(ap[i-1], p[i+1]);
478     // cout << "Query: " << *ap[n-2] << endl;
479     scanf("%s", cmdLine);
480     k=atoi(cmdLine);
481     compdists=IOread=IOwrite=0;
482    
483     TopQuery q(ap[n-2], k);
484    
485     if(!gist) CommandOpen("mtree", "graphs.M3");
486     CommandNearest(q);
487     cout << "Computed dists=" << compdists << "\nIO reads=" << IOread << "\nIO writes=" << IOwrite << "\nObjs=" << objs << endl;
488    
489     BOOL (*obs)[IndObjs]=new BOOL [n][IndObjs], pass=FALSE;
490    
491     l=-90;
492     do {
493     int j;
494    
495     for(j=0; j<IndObjs; j++)
496     for(i=0; i<n; i++) obs[i][j]=FALSE;
497     compdists=IOread=IOwrite=objs=0;
498     l+=100;
499     for(i=0; i<n; i++) {
500     TopQuery qi(p[i], l);
501     GiSTlist<GiSTobject *> list=gist->TopSearch(qi);
502    
503     while(!list.IsEmpty()) {
504     MTentry *e=(MTentry *)list.RemoveFront();
505    
506     obs[i][e->Ptr()]=TRUE;
507     delete e;
508     }
509     }
510     for(j=0; j<IndObjs; j++) {
511     BOOL check=TRUE;
512    
513     for(i=0; (i<n)&&check; i++) check=obs[i][j];
514     if(check) objs++;
515     }
516     // cout << l << "=>" << objs << endl;
517     if(objs>k) {
518     pass=TRUE;
519     l-=110;
520     oldcompdists=compdists;
521     oldIOread=IOread;
522     oldobjs=objs;
523     }
524     if(!pass) {
525     oldcompdists=compdists;
526     oldIOread=IOread;
527     oldobjs=objs;
528     }
529     // else if(objs==0) l+=90; // dangerous: could lead to infinite loops...
530     } while(((objs<k)&&!pass)||((objs>k)&&pass));
531     cout << l << "=>" << objs << endl;
532     if(objs<k) cout << "Computed dists=" << oldcompdists << "\nIO reads=" << oldIOread << "\nObjs=" << oldobjs << endl;
533     else cout << "Computed dists=" << compdists << "\nIO reads=" << IOread << "\nObjs=" << objs << endl;
534     delete []obs;
535     for(i=0; i<n; i++) delete x[i];
536     free(x);
537     for(i=0; i<n; i++) delete p[i];
538     free(p);
539     for(i=0; i<n-1; i++) delete ap[i];
540     free(ap);
541     compdists=IOread=IOwrite=objs=0;
542     CommandClose();
543     }
544     */ else if(!strcmp(cmdLine, "check")) {
545     if(!gist) CommandOpen("mtree", "graphs.M3");
546     CommandCheck();
547     CommandClose();
548     }
549     else if(!strcmp(cmdLine, "dump")) {
550     if(!gist) CommandOpen("mtree", "graphs.M3");
551     CommandDump();
552     CommandClose();
553     }
554     else if(!strcmp(cmdLine, "stats")) {
555     if(!gist) CommandOpen("mtree", "graphs.M3");
556     CommandStats();
557     CommandClose();
558     }
559     else if(!strcmp(cmdLine, "add")) {
560     if(!gist) CommandOpen("mtree", "graphs.M3");
561     scanf("%s", cmdLine);
562     i=atoi(cmdLine);
563     if(argc<5) {
564     cout << "Usage is: MTree [min_util] [split_f] [promote_f] [sec_promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
565     exit(-1);
566     }
567     MIN_UTIL=atof(argv[1]);
568     SPLIT_FUNCTION=(s_function)atoi(argv[2]);
569     PROMOTE_PART_FUNCTION=(pp_function)atoi(argv[3]);
570     SECONDARY_PART_FUNCTION=(pp_function)atoi(argv[4]);
571     if(SECONDARY_PART_FUNCTION==CONFIRMED) {
572     cout << "The secondary promotion function must be an unconfirmed one\n";
573     exit(-1);
574     }
575     if(PROMOTE_PART_FUNCTION==SAMPLING) {
576     if(argc<6) {
577     cout << "Usage is: MTree [min_util] [split_f] [promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
578     exit(-1);
579     }
580     NUM_CANDIDATES=atoi(argv[5]);
581     }
582     if(PROMOTE_PART_FUNCTION==CONFIRMED) {
583     if(argc<6) {
584     cout << "Usage is: MTree [min_util] [split_f] [promote_f] [sec_promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
585     exit(-1);
586     }
587     PROMOTE_VOTE_FUNCTION=(pv_function)atoi(argv[5]);
588     if(PROMOTE_VOTE_FUNCTION==SAMPLINGV) {
589     if(argc<7) {
590     cout << "Usage is: MTree [min_util] [split_f] [promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
591     exit(-1);
592     }
593     NUM_CANDIDATES=atoi(argv[6]);
594     }
595     else if(PROMOTE_VOTE_FUNCTION==mM_RAD) {
596     if(argc<7) {
597     cout << "Usage is: MTree [min_util] [split_f] [promote_f] ([vote_f] ([n_cand]|[radius_f]))\n";
598     exit(-1);
599     }
600     RADIUS_FUNCTION=(r_function)atoi(argv[6]);
601     }
602     }
603     switch(SPLIT_FUNCTION) {
604     case G_HYPERPL:
605     cout << "G_HYPL, ";
606     break;
607     case BAL_G_HYPERPL:
608     cout << "BAL_G_HYPL, ";
609     break;
610     case BALANCED:
611     cout << "BAL, ";
612     break;
613     }
614     switch(PROMOTE_PART_FUNCTION) {
615     case RANDOM:
616     cout << "RAN_2 ";
617     break;
618     case MAX_UB_DIST:
619     cout << "M_UB_d ";
620     break;
621     case SAMPLING:
622     cout << "SAMP" << NUM_CANDIDATES << "_2 ";
623     break;
624     case MIN_RAD:
625     cout << "m_R_2 ";
626     break;
627     case MIN_OVERLAPS:
628     cout << "m_O_2 ";
629     break;
630     case CONFIRMED:
631     switch(PROMOTE_VOTE_FUNCTION) {
632     case RANDOMV:
633     cout << "RAN_1 ";
634     break;
635     case SAMPLINGV:
636     cout << "SAMP" << NUM_CANDIDATES << "_1 ";
637     break;
638     case MAX_LB_DIST:
639     cout << "M_LB_d ";
640     break;
641     case mM_RAD:
642     cout << "mM_";
643     switch(RADIUS_FUNCTION) {
644     case LB:
645     cout << "m";
646     break;
647     case AVG:
648     cout << "A";
649     break;
650     case UB:
651     cout << "M";
652     break;
653     }
654     cout << "_r ";
655     break;
656     }
657     break;
658     }
659     switch(SECONDARY_PART_FUNCTION) {
660     case RANDOM:
661     cout << "(RAN_2)\n";
662     break;
663     case MAX_UB_DIST:
664     cout << "(M_UB_d)\n";
665     break;
666     case SAMPLING:
667     cout << "(SAMP" << NUM_CANDIDATES << "_2)\n";
668     break;
669     case MIN_RAD:
670     cout << "(m_R_2)\n";
671     break;
672     case MIN_OVERLAPS:
673     cout << "(m_O_2)\n";
674     break;
675     }
676     }
677     else if(!strcmp(cmdLine, "insert")) {
678     Object *obj=Read();
679    
680     if(!gist) CommandOpen("mtree", "graphs.M3");
681     CommandInsert(MTkey(*obj, 0, 0), i++);
682     delete obj;
683     }
684     else if(!strcmp(cmdLine, "load")) {
685     MTentry **entries;
686     int n;
687    
688     if(argc<2) {
689     cout << "Usage is: MTree [min_util]\n";
690     exit(-1);
691     }
692     MIN_UTIL=atof(argv[1]);
693     i=0;
694     scanf("%s", cmdLine);
695     n=atoi(cmdLine);
696     entries=new MTentry*[n];
697     for(i=0; i<n; i++) {
698     Object *obj=Read();
699    
700     entries[i]=new MTentry(MTkey(*obj, 0, 0), i);
701     delete obj;
702     }
703     CommandLoad("graphs.M3", entries, n);
704     for(i=0; i<n; i++) delete entries[i];
705     delete []entries;
706     }
707     }
708     cout << "Computed dists=" << compdists << "\nIO reads=" << IOread << "\nIO writes=" << IOwrite << "\nObjs=" << objs << endl;
709     CommandQuit();
710     cerr << "Now exiting...\n";
711     malloc_stats();
712     }
713