Beispiel #1
0
void loopdetect(GenericTree& twd){
	vector<bool> visited(twd.num_nodes(), false);
	for(int i=0; i<twd.num_nodes(); i++){
		if(visited[i]==true)
			continue;
		
		visited[i]=true;
		queue<pair<int, int> > q;
		q.push(pair<int, int>(-1,i));//first is father, second is current_node
		while(q.size()>0){
			pair<int, int> father_current=q.front();
			q.pop();
			for(TreeEdgeList::iterator it=twd.get_neighbors(father_current.second).begin(); it!=twd.get_neighbors(father_current.second).end(); it++){
				if(it->nodeID==father_current.first)
					continue;
				
				if(visited[it->nodeID]==true){
					cout<<"Loop Detected at: "<<it->nodeID<<endl;
					exit(-1);
				}
	
					
				visited[it->nodeID]=true;
				q.push(pair<int, int>(father_current.second, it->nodeID));
			}
		}
	}
}
Beispiel #2
0
void buildBalancedTreeDecomposition(GenericTree& twd, GenericTree& btd, const vector<set<int> >& nodedirectory){
	for(int i=0; i<twd.num_nodes(); i++){
		if(twd[i].visited==true)
			continue;
		
		//calculate the number of vertices in the connected component (BFS)
		twd[i].visited=true;
		int CC_size=1;
		queue<int> q;
		q.push(i);
		while(q.size()>0){
			int j=q.front();
			q.pop();
			for(TreeEdgeList::iterator tit=twd.get_neighbors(j).begin(); tit!=twd.get_neighbors(j).end(); tit++){
				if(twd[tit->nodeID].visited==true)
					continue;
				
				twd[tit->nodeID].visited=true;
				CC_size++;
				q.push(tit->nodeID);
			}
		}
		//calculate the number of vertices in the connected component done
		
		//Fill in the neighbor size info and locate the centroid
		int from_vertex=-1;
		int centroid=-1;
		int centroid_weight=MAX_VAL;
		SubtreeMeasure(twd, centroid, centroid_weight, i, from_vertex, CC_size, nodedirectory);
		//Fill in the neighbor size info and locate the centroid done
		
		//Iteratively build balanced decomposition tree
		BalancedTreeConstr(twd, btd, centroid, 0, nodedirectory);
		SubtreeMeasure(btd, centroid, centroid_weight, i, from_vertex, CC_size, nodedirectory);
		//Iteratively build balanced decomposition tree done
	}
}
Beispiel #3
0
int main(int argc, char* argv[]) {
	if (argc == 1) {
		usage();
		return 1;
	}
	string query_filename, input_filename;
	int input_para_counter=1;
//	int source_vertex=-1;
//	int destination_vertex=-1;
	int rw_queryfile=-1;
	construction_type graph_input_format=ADJ_GRAPH;
	graph_type	direct_info=UNDIRECT;
	int query_num=100000;
	int verify_enable=1;
	while (input_para_counter < argc) {
		if (strcmp("-h", argv[input_para_counter]) == 0) {
			usage();
			return 1;
		}
		
		if (strcmp("-g", argv[input_para_counter]) == 0) {
			input_para_counter++;
			graph_input_format=static_cast<construction_type>(atoi(argv[input_para_counter++]));			
		}else if (strcmp("-d", argv[input_para_counter]) == 0) {
			input_para_counter++;
			direct_info=static_cast<graph_type>(atoi(argv[input_para_counter++]));			
		}else if (strcmp("-l", argv[input_para_counter]) == 0){
			input_para_counter++;
			rw_queryfile= atoi(argv[input_para_counter++]);
		}else if (strcmp("-q", argv[input_para_counter]) == 0){
			input_para_counter++;
			query_filename= argv[input_para_counter++];
		}else if (strcmp("-n", argv[input_para_counter]) == 0){
			input_para_counter++;
			query_num= atoi(argv[input_para_counter++]);
		}else if (strcmp("-v", argv[input_para_counter]) == 0){
			input_para_counter++;
			verify_enable= atoi(argv[input_para_counter++]);
		}else{
			input_filename = argv[input_para_counter++];
//			source_vertex = atoi(argv[input_para_counter++]);
//			destination_vertex = atoi(argv[input_para_counter++]);
		}
	}
	
	
	ifstream infile(input_filename.c_str());
	if (!infile) {
		cout << "Error: Cannot open " << input_filename << endl;
		return -1;
	}
	
	vector<int> src;
	vector<int> trg;
	

	Graph g(infile, graph_input_format, direct_info);
	if(direct_info==UNDIRECT)
		cout << "#vertex size:" << g.num_vertices() << "\t#edge size:" << g.num_edges() << endl;
	else
		cout << "#vertex size:" << g.num_vertices() << "\t#undirect edge size:" << g.num_edges() << "\t#direct edge size:"<< g.num_directed_edges() << endl;
		

	//Symmetric test is enforced right now. In the future, we can allowed directed graphs
	//Note the program requires that a vertex itself does not appear in its adjacent list and the adjacent list is in ascending order.
	if(!g.isSymmetric()){
		cout<<"Internal Error: Intend to treat a directed graph as undirected."<<endl;
		exit(-1);
	}	
	
	if(rw_queryfile==1){
		GraphUtil::generate_queryfile(src, trg, g.num_vertices(), query_filename.c_str(), query_num);
	}else if(rw_queryfile==0){
		GraphUtil::load_queryfile(src, trg, query_filename.c_str());
	}else{//generate query without loading from or saving into files.
		GraphUtil::generate_query(src, trg, g.num_vertices(), query_num);
	}	

	
	//Start index construction
	struct timeval after_index_const_time, before_index_const_time;
	gettimeofday(&before_index_const_time, NULL);
	
	GenericTree twd;
	vector<set<int> > nodedirectory; //middle result.
	Graph g1=g;
	int max_bag_size=buildTreeWidthDecomposition(g1, twd, nodedirectory);
	cout<<"max_bag_size of this decomposition: "<<max_bag_size<<endl;
	vector<vector<int> > node_mapping_directory(nodedirectory.size(), vector<int>());
	//twd.printTree();
	
	
	cout<<"Tree Width Decomposition successful. "<<endl;
	cout<<"twd.num_nodes(): "<<twd.num_nodes()<<endl;

	
	
	GenericTree btd(twd.num_nodes());
	buildBalancedTreeDecomposition(twd, btd, nodedirectory);
	cout<<"Balanced Tree decomposition successful. "<<endl;
	cout<<"btd.num_nodes(): "<<btd.num_nodes()<<endl;
	//btd.printTree();
	
	BinaryTree btree(btd.num_nodes());
	vector<int> virtualnode_to_realnode;//The virtual node to real node mapping table. //middle result.
	
	buildBinaryTree(btd, btree, virtualnode_to_realnode);
	cout<<"Binary Tree construction successful. "<<endl;
	cout<<"btree.num_nodes(): "<<btree.num_nodes()<<endl;
	cout<<"btree.access_height(): "<<btree.access_height()<<endl;	
	//btree.printTree();
	
	
	
	if(btree.access_height()>63){
		cout<<"The current program maximally supports a balanced binary tree with height no more than 63, i.e., about 2^61 vertices in the original graph."<<endl;
		cout<<"This number shall satisfy almost all current applications. Please verify you really need to run such a giant graph. If yes, a simple update on the Machine_WORD data structure will make it work."<<endl;
		cout<<"Program exit."<<endl;
		exit(0);
	}
	
	vector<MACHINE_WORD> TreeNodeBitLabel(btree.num_nodes(), 0);//middle result
	BitOperators::set_one(TreeNodeBitLabel[btree.access_root()], btree.access_height());
	cout<<"Start building Tree Node Bit label"<<endl;
	BuildTreeNodeBitlabel(btree, btree.access_root(), TreeNodeBitLabel);
	cout<<"End building Tree Node Bit label"<<endl;
	
	//hashmap implementation
	hash_map<int, int> BitLabelTreeNode;//Map bit label to real tree node. Part of final label.
	for (int i=0; i<int(TreeNodeBitLabel.size()); i++){
		if (i>=btd.num_nodes()){
			BitLabelTreeNode[TreeNodeBitLabel[i]]=virtualnode_to_realnode[i-btd.num_nodes()];//virtualnode_to_realnode gets -1 if no real node can be mapped. 
		}
		else
			BitLabelTreeNode[TreeNodeBitLabel[i]]=i;
	}
	
	vector<vector<VertexDistancePair> > LabelGT(g.num_vertices());//The first is vertex ID, and the second is distance. //middle result
	vector<vector<VertexDistancePair> > LabelGT_From(g.num_vertices());//middle result
	vector<vector<VertexDistancePair> > LabelGT_To(g.num_vertices());//middle result
	vector<vertex_mapping_info> vertex_mapping_table(g.num_vertices());//The table recording the mapping between vertex, and btree level and label offset. //Part of final label.
	vector<int> vertex_to_nodeID(g.num_vertices());//middle result	
	cout<<"Start building LabelGT"<<endl;
	if(direct_info==DIRECT)
		BuildLabelGTDirect(g, btree, nodedirectory, node_mapping_directory, LabelGT_From, LabelGT_To, vertex_mapping_table, vertex_to_nodeID);
	else
		BuildLabelGT(g, btree, nodedirectory, node_mapping_directory, LabelGT, vertex_mapping_table, vertex_to_nodeID);

	cout<<"End building LabelGT"<<endl;
	for(size_t i=0; i<vertex_mapping_table.size(); i++){
		vertex_mapping_table[i].NodeBitLabel=TreeNodeBitLabel[vertex_to_nodeID[i]];
	}
	
	//sort and printout LabelGT or LabelGT_From, LabelGT_To
	if(direct_info==DIRECT){
		for(size_t i=0; i<LabelGT_From.size(); i++){
			sort(LabelGT_From[i].begin(), LabelGT_From[i].end(), VertexDistanceCompare);
		}
		
		for(size_t i=0; i<LabelGT_To.size(); i++){
			sort(LabelGT_To[i].begin(), LabelGT_To[i].end(), VertexDistanceCompare);
		}			
	
	}else{
		for(size_t i=0; i<LabelGT.size(); i++){
			sort(LabelGT[i].begin(), LabelGT[i].end(), VertexDistanceCompare);
		}
	}
	//printout LabelGT done
	
	
	//release memory first time
	g1.clear();
	TreeNodeBitLabel.clear();
	virtualnode_to_realnode.clear();
	btd.clear();
	twd.clear();
	
	cout<<"Start prequery"<<endl;
	vector<vector<vector<int> > > LabelGTUpdate(g.num_vertices());//It is a partial update in this version
	vector<vector<vector<int> > > LabelGT_From_Update(g.num_vertices());
	vector<vector<FlatVector> >  LabelGT_From_Mask(g.num_vertices());
	vector<vector<vector<int> > > LabelGT_To_Update(g.num_vertices());
	vector<vector<FlatVector> >  LabelGT_To_Mask(g.num_vertices());

	for (int v=0; v<g.num_vertices(); v++){
		if(v%1000==0)
			cout<<"prequery on "<<v<<endl;
		if(direct_info==DIRECT){
			LabelGT_From_Update[v].resize(vertex_mapping_table[v].level+1);
			LabelGT_From_Mask[v].resize(vertex_mapping_table[v].level+1);
			LabelGT_To_Update[v].resize(vertex_mapping_table[v].level+1);
			LabelGT_To_Mask[v].resize(vertex_mapping_table[v].level+1);
		}else
			LabelGTUpdate[v].resize(vertex_mapping_table[v].level+1);
			
		int current_node=int(vertex_to_nodeID[v]);
		while(current_node!=-1){
			if(current_node<int(nodedirectory.size())){
				if(direct_info==DIRECT){
					set<int>::iterator	sit=nodedirectory[current_node].begin();
					vector<int>::iterator vit=node_mapping_directory[current_node].begin();
					int nodedirectory_offset=0;
					while(sit!=nodedirectory[current_node].end()){
						int To_distance=prequeryDirect(LabelGT_From, LabelGT_To, v, *sit);
						int From_distance=prequeryDirect(LabelGT_From, LabelGT_To, *sit, v);
						if(vit!=node_mapping_directory[current_node].end()){
							if(*sit==*vit){
								LabelGT_To_Update[v][btree[current_node].level].push_back(To_distance);
								if (To_distance<MAX_VAL)
									LabelGT_To_Mask[v][btree[current_node].level].insert(nodedirectory_offset);
									
								LabelGT_From_Update[v][btree[current_node].level].push_back(From_distance);
								if (From_distance<MAX_VAL)
									LabelGT_From_Mask[v][btree[current_node].level].insert(nodedirectory_offset);
							
								sit++;
								vit++;
							}else if (*sit<*vit){
								if (To_distance<MAX_VAL)
									LabelGT_To_Mask[v][btree[current_node].level].insert(nodedirectory_offset);
									
								if (From_distance<MAX_VAL)
									LabelGT_From_Mask[v][btree[current_node].level].insert(nodedirectory_offset);
							
								sit++;
							}else{
								cout<<"This should not happen because one is the subset of the other."<<endl;
								exit(-1);
							}
						}else{
							if (To_distance<MAX_VAL)
								LabelGT_To_Mask[v][btree[current_node].level].insert(nodedirectory_offset);
								
							if (From_distance<MAX_VAL)
								LabelGT_From_Mask[v][btree[current_node].level].insert(nodedirectory_offset);
							sit++;
						}
						nodedirectory_offset++;

					}
				
				}else{
					for(vector<int>::iterator vit=node_mapping_directory[current_node].begin(); vit!=node_mapping_directory[current_node].end(); vit++){
						LabelGTUpdate[v][btree[current_node].level].push_back(prequery(LabelGT, v, *vit));
						
					}
				}
			}
			current_node=btree[current_node].parent;
		}
	}
	cout<<"End prequery"<<endl;
	
	
	//release memory second time
	LabelGT.clear();
	LabelGT_From.clear();
	LabelGT_To.clear();
	vertex_to_nodeID.clear();
	node_mapping_directory.clear();
	
	int tree_height=btree.access_height();
	if(int(BitLabelTreeNode.size())<btree.num_nodes())
		cout<<"HashMap has compressed the index size"<<endl;
	else if (int(BitLabelTreeNode.size())>btree.num_nodes())
		cout<<"HashMap has introduced more index size than the tree node number."<<endl;
	btree.clear();
	
	vector<vector<int> > node_directory(nodedirectory.size());
	vector<int>	TreeNodeLevel(nodedirectory.size());//Only real node levels are necessary.
	int node_directory_size=0;
	for(size_t i=0; i<nodedirectory.size(); i++){
		TreeNodeLevel[i]=btree[i].level;
		for(set<int>::iterator sit=nodedirectory[i].begin(); sit!=nodedirectory[i].end(); sit++){
			node_directory[i].push_back(*sit);
			node_directory_size++;
		}
	}
	nodedirectory.clear();
	//release memory done
	//End index construction
	gettimeofday(&after_index_const_time, NULL);
	double index_construct_time=(after_index_const_time.tv_sec - before_index_const_time.tv_sec)*1000.0 + (after_index_const_time.tv_usec - before_index_const_time.tv_usec)*1.0/1000.0;
	cout<<"Index construction completed in : "<<index_construct_time<<" (ms). This time includes outputting the running information."<<endl;
	
	
	
	//Data structure must be used for ALL query: vertex_mapping_table, BitLabelTreeNode, tree_height;
	
	//Data structure must be used for distance query on undirected graphs:  LabelGTUpdate, node_directory;

	//Data structure must be used for distance query on directed graphs: LabelGT_From_Update, LabelGT_To_Update, node_directory;
	//Optional Data structure for distance query on directed graphs: LabelGT_From_Mask, LabelGT_To_Mask, TreeNodeLevel;
	
	//Calculate TC size:
	long int TC_size=0;

	if(direct_info==DIRECT){
		int From_size_1=0;
		int From_size_2=0;
		for (size_t i=0; i<LabelGT_From_Update.size(); i++){
			for(size_t j=0; j<LabelGT_From_Update[i].size(); j++){
				From_size_1+=LabelGT_From_Update[i][j].size();
				From_size_2+=LabelGT_From_Mask[i][j].size();
			}
		}
		int To_size_1=0;
		int To_size_2=0;
		for (size_t i=0; i<LabelGT_To_Update.size(); i++){
			for(size_t j=0; j<LabelGT_To_Update[i].size(); j++){
				To_size_1+=LabelGT_To_Update[i][j].size();
				To_size_2+=LabelGT_To_Mask[i][j].size();
			}
		}
		if(From_size_1!=To_size_1){
			cout<<"From size and To size do not match. Error in direct labeling."<<endl;
			exit(-1);
		}else{
			TC_size=From_size_1+To_size_1+From_size_2+To_size_2;
		}
	}else{
		for (size_t i=0; i<LabelGTUpdate.size(); i++){
			for(size_t j=0; j<LabelGTUpdate[i].size(); j++){
				TC_size+=LabelGTUpdate[i][j].size();
			}
		}
	}
	
	
	
	if(direct_info==DIRECT)
		cout<<"Total indexing size: "<<TC_size+vertex_mapping_table.size()*3+BitLabelTreeNode.size()+TreeNodeLevel.size()+node_directory_size+1<<endl;
	else
		cout<<"Total indexing size: "<<TC_size+vertex_mapping_table.size()*3+BitLabelTreeNode.size()+node_directory_size+1<<endl;
	

	cout<<"Start query..."<<endl;	
	struct timeval after_time, before_time;
	int twd_distance, bfs_distance;
	vector<int>::iterator sit, tit;	
	
	if(direct_info==DIRECT){
		gettimeofday(&before_time,NULL);	
		for(sit = src.begin(), tit = trg.begin(); 		sit != src.end(); ++sit, ++tit)
			twd_distance=queryDirectMask(vertex_mapping_table, BitLabelTreeNode, TreeNodeLevel, node_directory, LabelGT_From_Update, LabelGT_To_Update, LabelGT_From_Mask, LabelGT_To_Mask, tree_height, *sit, *tit);
		gettimeofday(&after_time,NULL);
		float query_time=(after_time.tv_sec - before_time.tv_sec)*1000.0 + (after_time.tv_usec - before_time.tv_usec)*1.0/1000.0;
		cout<<"twd distance query time: "<<query_time<<endl;
		
		
	}else{
		gettimeofday(&before_time,NULL);	
		for(sit = src.begin(), tit = trg.begin(); 		sit != src.end(); ++sit, ++tit)
			twd_distance=query(vertex_mapping_table, BitLabelTreeNode, node_directory, LabelGTUpdate, tree_height, *sit, *tit);
		gettimeofday(&after_time,NULL);
		float query_time=(after_time.tv_sec - before_time.tv_sec)*1000.0 + (after_time.tv_usec - before_time.tv_usec)*1.0/1000.0;
		cout<<"twd distance query time: "<<query_time<<endl;
		
	}

	cout<<"End Query..."<<endl;
	
	if(verify_enable==1){
		cout<<"Start query verification."<<endl;
		if(direct_info==DIRECT){
			for(sit = src.begin(), tit = trg.begin(); 		sit != src.end(); ++sit, ++tit){
				twd_distance=queryDirectMask(vertex_mapping_table, BitLabelTreeNode, TreeNodeLevel, node_directory, LabelGT_From_Update, LabelGT_To_Update, LabelGT_From_Mask, LabelGT_To_Mask, tree_height, *sit, *tit);
				bfs_distance=GraphUtil::BFSDistanceDirect(g, *sit, *tit);
				if(twd_distance!=bfs_distance){
					cout<<"twd_distance direct: "<<twd_distance<<endl;
					cout<<"bfs_distance direct: "<<bfs_distance<<endl;
				}
			}
		
		}else{
			for(sit = src.begin(), tit = trg.begin(); 		sit != src.end(); ++sit, ++tit){
				twd_distance=query(vertex_mapping_table, BitLabelTreeNode, node_directory, LabelGTUpdate, tree_height, *sit, *tit);
				bfs_distance=GraphUtil::BFSDistance(g, *sit, *tit);
				if(twd_distance!=bfs_distance){
					cout<<"twd_distance: "<<twd_distance<<endl;
					cout<<"bfs_distance: "<<bfs_distance<<endl;
				}
			}
		}

		cout<<"end query verification."<<endl;
	}
	else{
		cout<<"verification option waived."<<endl;
	}
	
	//find the minimum distance
	cout<<"end of the program"<<endl;
	

}
Beispiel #4
0
int buildTreeWidthDecomposition(Graph& g, GenericTree& twd, vector<set<int> >& nodedirectory){//return the max_bag_size of this decomposition
	set<VertexDegreePair,VertexDegreePairComp> DegreeRank;//first is degree; second is vertex id;
	vector<int> DegreeList(g.num_vertices(),0);
	int max_bag_size=-1;
	for(int i=0; i<g.num_vertices(); i++){
		int current_degree=g.get_degree(i);
		DegreeRank.insert(VertexDegreePair(i, current_degree));
		DegreeList[i]=current_degree;
	}
	
	while(DegreeRank.size()>0){
		set<VertexDegreePair,VertexDegreePairComp>::iterator minDegreeVertex=DegreeRank.begin();
		DegreeRank.erase(DegreeRank.begin());
		int current_vertexID=minDegreeVertex->first;
		//build treenode
		nodedirectory.push_back(set<int>());
		int current_nodeID=nodedirectory.size()-1;
		nodedirectory.back().insert(current_vertexID);

		for(EdgeList::iterator vit=g.get_neighbors(current_vertexID).begin(); vit<g.get_neighbors(current_vertexID).end(); vit++){
			nodedirectory.back().insert(*vit);
			g[*vit].nodes.push_back(current_nodeID);

			
			//update on graph
			EdgeList::iterator iit=g.get_neighbors(current_vertexID).begin();
			EdgeList::iterator jit=g.get_neighbors(*vit).begin();
			EdgeList combined;
			while(iit<g.get_neighbors(current_vertexID).end() && jit<g.get_neighbors(*vit).end()){
				
				//It is assumed that a vertex itself does not appear in its adjacent list and the adjacent list is in ascending order.
				if(*iit==*vit){
					iit++;
					continue;
				}else if (*jit==current_vertexID){
					jit++;
					continue;
				}
				
				if(*iit<*jit){
					combined.push_back(*iit);
					iit++;
				}else if(*iit>*jit){
					combined.push_back(*jit);
					jit++;
				}else{//implies *iit==*jit
					combined.push_back(*iit);
					iit++;
					jit++;
				}
			}
			
			if(iit<g.get_neighbors(current_vertexID).end() && jit<g.get_neighbors(*vit).end()){
				cout<<"Internal Logic Error. Exit."<<endl;
				exit(-1);
			}
			
			for(; iit<g.get_neighbors(current_vertexID).end(); iit++){
				if(*iit!=*vit)
					combined.push_back(*iit);
			}
			
			for(; jit<g.get_neighbors(*vit).end(); jit++){
				if(*jit!=current_vertexID)
					combined.push_back(*jit);
			}
			
			g.get_neighbors(*vit)=combined;
			//update on graph done
			
			//update on nodes
			vector<int> reduced;
			vector<int>::iterator itern=g[*vit].nodes.begin();
			vector<int>::iterator jtern=g[current_vertexID].nodes.begin();
			while(itern<g[*vit].nodes.end() && jtern<g[current_vertexID].nodes.end()){
				if(*itern<*jtern){
					reduced.push_back(*itern);
					itern++;
				}
				else if (*itern>*jtern){
					jtern++;
				}
				else{//implies *itern==*jtern
					itern++;
					jtern++;
				}
			}
			
			for(; itern<g[*vit].nodes.end(); itern++)
				reduced.push_back(*itern);
			
			g[*vit].nodes=reduced;
			//update on nodes done
			
			//other update
			set<VertexDegreePair,VertexDegreePairComp>::iterator fit=DegreeRank.find(VertexDegreePair(*vit, DegreeList[*vit]));
			DegreeRank.erase(fit);
			DegreeRank.insert(VertexDegreePair(*vit, g.get_degree(*vit)));
			DegreeList[*vit]=g.get_degree(*vit);
			//other update done
		}
		max_bag_size=int(nodedirectory.back().size())>max_bag_size? int(nodedirectory.back().size()) : max_bag_size;
		//build treenode done
		
		
		//build decomposition tree
		twd.addNode(twd.num_nodes());
		for(vector<int>::iterator nit=g[current_vertexID].nodes.begin(); nit<g[current_vertexID].nodes.end(); nit++){
			twd.addEdge(current_nodeID, *nit);//current_nodeID shall always be larger than *nit;
			twd.addEdge(*nit, current_nodeID);
		}
		//build decomposition tree done
		
		
		//clear deleted vertex
		g[current_vertexID].nodes.clear();
		g.get_neighbors(current_vertexID).clear();
		//clear deleted vertex
	}
	return max_bag_size;
}
Beispiel #5
0
void buildBinaryTree(GenericTree& btd, BinaryTree& btree, vector<int>& virtualnode_to_realnode){
	multimap<int, int> subsize_root;////The first int is subtree size, and the second is node ID.
	for(int current_node=0; current_node<btd.num_nodes(); current_node++){
		
		int current_node_level=btd[current_node].nodelevel;
		multimap<int, int> subsize_node;//The first int is subtree size, and the second is node ID.
		int parent=-1;
		int total_size=0;
		for(TreeEdgeList::iterator tit=btd.get_neighbors(current_node).begin(); tit!=btd.get_neighbors(current_node).end(); tit++){
			if(btd[tit->nodeID].nodelevel>current_node_level){
				subsize_node.insert(pair<int, int>(tit->subtree_size, tit->nodeID));
				total_size+=tit->subtree_size;
			}else if (btd[tit->nodeID].nodelevel==current_node_level){
				cout<<"Internal logic error 1 ocurrs on binary tree construction."<<endl;
			}else{//implies btd[tit->nodeID].nodelevel<current_node_level
				if (parent==-1){
					parent=tit->nodeID;
				}else{
					cout<<"Internal logic error 2 (multiple parents) ocurrs on binary tree construction."<<endl;
				}
			}
		}
		
		if (parent==-1){//implies root node
			subsize_root.insert(pair<int, int>(total_size+1, current_node));
		}
		
		btree[current_node].parent=parent;
		if(subsize_node.size()==1){
			btree[current_node].left_child=(subsize_node.begin())->second;
		}else if (subsize_node.size()==2){
			multimap<int, int>::iterator mit=subsize_node.begin();
			btree[current_node].left_child=mit->second;
			mit++;
			btree[current_node].right_child=mit->second;
		}else if (subsize_node.size()>2){ 
			while(subsize_node.size()>2){
				int first_size=(subsize_node.begin())->first;
				int first_node=(subsize_node.begin())->second;
				subsize_node.erase(subsize_node.begin());
				int second_size=(subsize_node.begin())->first;
				int second_node=(subsize_node.begin())->second;
				subsize_node.erase(subsize_node.begin());
				int new_node_id=btree.num_nodes();
				//add a virtual node
				btree.addNode(new_node_id);
				virtualnode_to_realnode.push_back(current_node);
				//add a virtual node done
				btree[new_node_id].left_child=first_node;
				btree[new_node_id].right_child=second_node;
				btree[first_node].parent=new_node_id;
				btree[second_node].parent=new_node_id;
				subsize_node.insert(pair<int, int>(first_size+second_size, new_node_id));
			}
			multimap<int, int>::iterator mit=subsize_node.begin();			
			btree[current_node].left_child=mit->second;
			btree[mit->second].parent=current_node;
			
			mit++;
			btree[current_node].right_child=mit->second;
			btree[mit->second].parent=current_node;
		}
		
	}

	int root=-1;
	if(subsize_root.size()==1){
		root=(subsize_root.begin())->second;
	}else if (subsize_root.size()>1){
		while(subsize_root.size()>1){
			int first_size=(subsize_root.begin())->first;
			int first_node=(subsize_root.begin())->second;
			subsize_root.erase(subsize_root.begin());
			int second_size=(subsize_root.begin())->first;
			int second_node=(subsize_root.begin())->second;
			subsize_root.erase(subsize_root.begin());
			int new_node_id=btree.num_nodes();
			//add a virtual node
			btree.addNode(new_node_id);
			virtualnode_to_realnode.push_back(-1);//If the root node is a virtual node, there is no real node can be associated with it.
			//add a virtual node done
			btree[new_node_id].left_child=first_node;
			btree[new_node_id].right_child=second_node;
			btree[first_node].parent=new_node_id;
			btree[second_node].parent=new_node_id;
			subsize_root.insert(pair<int, int>(first_size+second_size, new_node_id));
			root=new_node_id;
		}
	}
	
	if(root<0){
		cout<<"The btree is empty. Please check input."<<endl;
		return;
	}else{
		btree.access_root()=root;
		btree[root].level=0;
		int maximum_level=0;
		queue<int> q;
		q.push(root);
		while(q.size()>0){
			int j=q.front();
			q.pop();
			maximum_level=maximum_level>btree[j].level?maximum_level:btree[j].level;

			if (btree[j].left_child>=0){
				btree[btree[j].left_child].level=btree[j].level+1;
				q.push(btree[j].left_child);
			}
			
			if (btree[j].right_child>=0){
				btree[btree[j].right_child].level=btree[j].level+1;
				q.push(btree[j].right_child);
			}
			
		}
		btree.access_height()=maximum_level;
	}
}