internal void SearchInNode(object q, double radius, VPF_Leaf V,List<ResultPair> results) { double d_q_c=DB.Dist(q,DB[V.center]); int start=natix.SortingSearching.Search.FindFirst<double>(d_q_c-radius,V.dist2center); if (start !=-1) { int end=natix.SortingSearching.Search.FindLast<double>(d_q_c+radius,V.dist2center); if (end !=-1) { for(int i=start;i<=end;i++) { double d=this.DB.Dist(q,this.DB[V.IDs[i]]); if ( d<=radius ) // left leaf is a result { results.Add(new ResultPair(V.IDs[i],d) ); } } } } }
// Constructor // _m must be a value in [0,1] public VP_Forest(MetricDB _DB, double _m=0,double _tau=0) { this.DB=_DB; this.Remaining=new List<int>(this.DB.Count); this.Persist=new bool[this.DB.Count]; this.Tau=double.MaxValue; int[] perm; if (_m!=0) this.m=_m; if (_tau!=0) { BuildingWithTau=true; this.wanted_Tau=2*_tau; } this.Forest=new List<VPF_Tree>(); int N=this.DB.Count; for (int i=0;i<N;i++) this.Remaining.Add(i); do { int a,w,center; double[] Distances=new double[N]; this.Persist=new bool[N]; this.Forest.Add ( new VPF_Tree() ); perm=new int[N]; for (int i=0;i<N;i++) {perm[i]=i;} //Console.WriteLine("Building tree number: {0}",Forest.Count); //Console.WriteLine("Remaining: {0}",Remaining.Count); if (Divide_Interval(N,out a,out w,out center,out Distances,perm)) { this.Forest[this.Forest.Count-1].Root=new VPF_Node(center); BuildTree((VPF_Node)this.Forest[this.Forest.Count-1].Root,Distances,perm,a,w); } else // The root is a leaf { leafs+=N; VPF_Leaf L=new VPF_Leaf(N); L.center=center; for (int i=0;i<N;i++) L.SetValues(this.Remaining[perm[i]],Distances[i],i); this.Forest[this.Forest.Count-1].Root=L; Console.WriteLine("Tau very big. Remaining:{0}",Remaining.Count); } RemoveMarkedOnes(); N=Remaining.Count; }while(Remaining.Count>0); this.Tau/=2; Console.WriteLine("Total trees: {0}",this.Forest.Count); Console.WriteLine("Tau: {0}",this.Tau); Console.WriteLine("Leafs:{0}",leafs); }
// Build the Tree!! internal void BuildTree(VPF_Node Node,double[] Distances,int [] Perm,int a,int w) { //int start=Node.start; //int end=Node.end; int a2=0,w2=0,center2=0; int count=Perm.Length; //Console.WriteLine("a:{0},w:{1},total:{2}",a,w,count); double lmin=Distances[0],lmax=Distances[a-1],rmin=Distances[a+w],rmax=Distances[Perm.Length-1]; //double[] Distances=new double[Perm.Length]; //int center=0; //Divide_Interval(count,out a,out w,Node,Distances,Perm); // Mark to Remove middle part if (w>0) { Mark2PersistRange(a,w,Perm); if (Distances[ a+w-1 ]-Distances[ a ]>0) this.Tau=Math.Min(this.Tau,Distances[ a+w-1 ]-Distances[ a ]); } double[] Distances2=new double[a]; int[] Perm2=new int[a]; for (int i=0;i<a;i++) { Perm2[i]=Perm[i]; //Distances2[i]=Distances[i]; } if (Divide_Interval(a,out a2,out w2,out center2,out Distances2,Perm2)) // build left node { Node.Lmin=lmin; Node.Lmax=lmax; Node.left=new VPF_Node( center2 ); BuildTree((VPF_Node)Node.left,Distances2,Perm2,a2,w2); } else // build leaf { Node.Lmin=lmin; Node.Lmax=lmax; leafs+=a; VPF_Leaf L= new VPF_Leaf(a); for (int i=0;i<a;i++) { L.SetValues(this.Remaining[Perm[i]],Distances[i],i); } //Console.WriteLine("TotalLeafs:{0}",a); Node.left=L; //Console.WriteLine("Build Leaf:{0}",L.IDs.Length); } Distances2=new double[Perm.Length-1-(a+w-1)]; Perm2=new int[Perm.Length-1-(a+w-1)]; for (int i=a+w;i<Perm.Length;i++) { Perm2[i-a-w]=Perm[i]; //Distances2[i-a-w]=Distances[i]; } if (Divide_Interval(Perm.Length-1-(a+w-1),out a2,out w2,out center2,out Distances2,Perm2)) // build right node { Node.Rmin=rmin; Node.Rmax=rmax; Node.right=new VPF_Node( center2 ); BuildTree((VPF_Node)Node.right,Distances2,Perm2,a2,w2); } else // build leaf { Node.Rmin=rmin; Node.Rmax=rmax; //Console.Write("L:{0} ",this.Remaining[Perm[a+w]]); leafs+=Perm.Length-1-(a+w-1); VPF_Leaf R=new VPF_Leaf(Perm.Length-1-(a+w-1)); for(int i=0;i<Perm.Length-1-(a+w-1);i++) { R.SetValues(this.Remaining[Perm[a+w+i]],Distances[a+w+i],i); } //Console.WriteLine("Total Leafs:{0}",Perm.Length-1-(a+w-1)); Node.right=R; //Console.WriteLine("Build Leaf:{0}",R.IDs.Length); } }