Пример #1
0
int BinarySearchTree::getMaxDepth(Node *node)
{
	if(node==NULL)
		return 0;
	else
		return max(1+getMaxDepth(node->getRight()),1+getMaxDepth(node->getLeft()));
}
Пример #2
0
// 递归过程中,直接修改currentDepth, maxDepth, 因此采用引用传参
void getMaxDepth(BinaryTreeNode* data, int& currentDepth, int& maxDepth)
{
	currentDepth ++;
	
	if (data->left == NULL && data->right == NULL)
	{
		maxDepth = (maxDepth < currentDepth ? currentDepth : maxDepth);
		
		//currentDepth--;
		
		return ;
	}
	
	if (data->left != NULL)
	{
		getMaxDepth(data, currentDepth, maxDepth);
		currentDepth--;
	}
	
	if (data->right != NULL)
	{
		getMaxDepth(data, currentDepth, maxDepth);
		currentDepth--;
	}
}
Пример #3
0
		void CustomRule::apply(Builder* b) const {

			int newDepth = -1;
			/// If there is a maxdepth set for this object check it.
			if (getMaxDepth() != -1) {
				if (!b->getState().maxDepths.contains(this)) {
					/// We will add a new maxdepth for this rule to the state.
					newDepth = getMaxDepth()-1;
					
				} else {
					int depth = b->getState().maxDepths[this];
					if (depth <= 0) {
						/// This rule is retired.
						if (retirementRule) {
							b->getState().maxDepths[this] = maxDepth;
							retirementRule->rule()->apply(b);
							
						} 
						return;
					} else {
						/// Decrease depth.
						newDepth = depth-1;
					}
				}
			}

			/// Apply all actions.
			for (int i = 0; i < actions.size(); i++) {
				if (getMaxDepth() != -1) {
					actions[i].apply(b, this, newDepth);
				} else {
					actions[i].apply(b, 0 ,0);
				}
			}
		}
		void getMaxDepth(TreeNode* node, int curDepth, int& maxDepth)
		{
			if (!node->left && !node->right)
			{
				maxDepth = max(maxDepth, curDepth);
			}
			if (node->left) { getMaxDepth(node->left, curDepth + 1, maxDepth); }
			if (node->right) { getMaxDepth(node->right, curDepth + 1, maxDepth); }
		}
Пример #5
0
int KDNode::getMaxDepth(KDNode* node){
	int depth = node->depth;

	if(node->left != NULL){
		depth = getMaxDepth(node->left);
	}

	if(node->right != NULL){
		depth = max(depth, getMaxDepth(node->right));
	}

	return depth;
}
Пример #6
0
int main()
{
	// Initialize the root 
	Node *root = NULL;

	int insertElements(Node **root,int data);
	int printElements(Node *root);
	int getMaxDepth(Node *root,int parentLevel);
	int getNodeCount(Node *root);
	int hasPathSum(Node *root,int sumValue,int parentSumVal);
	int printPath(Node *root);

	int numElements;

	printf("Please enter the number of elements to be inserted\n");
	scanf("%d",&numElements);

	if (numElements > MAXELEMENTS)
	{
		printf("Exceeded total num of elements allowed\n");
		return 0;
	}

	// Input elements into BST
	for (int i=1;i<=numElements;i++)
	{
		int data;
		printf("Enter node data \n");
		scanf("%d",&data);
		if (!insertElements(&root,data))
		{
			printf("Unable to insert element\n");
			return 0;
		}
	}

	// print BST elements
	if (!printElements(root))
	{
		printf("Unable to print elements\n");
		return 0;
	}

	printf("The max depth of the tree %d \n",getMaxDepth(root,100));
	printf("Number of nodes in the tree %d \n",getNodeCount(root));

	int sumVal;
	printf("Enter the sum value \n");
	scanf("%d",&sumVal);

	if (hasPathSum(root,sumVal,100))
	{
		printf("sum of at least one of the path is %d\n",sumVal);
	} else
	{
		printf("There is no path with sum %d\n",sumVal);
	}

	return 1;
}
Пример #7
0
  //This is for real octants only, pseudo-boundary octants can not be tested
  //using this. 
  bool DA::isBoundaryOctant(unsigned char *flags) {
#ifdef __DEBUG_DA_PUBLIC__
    assert(m_bIamActive);
#endif

    unsigned char _flags = 0;
    Point pt = getCurrentOffset();
    unsigned int x = pt.xint();
    unsigned int y = pt.yint();
    unsigned int z = pt.zint();
    unsigned int d = getLevel(curr())-1;
    unsigned int maxD = getMaxDepth()-1;
    unsigned int len  = (unsigned int)(1u<<(maxD - d) );
    unsigned int blen = (unsigned int)(1u << maxD);

    if (!x) _flags |= ot::TreeNode::X_NEG_BDY;  
    if (!y) _flags |=  ot::TreeNode::Y_NEG_BDY; 
    if (!z) _flags |=   ot::TreeNode::Z_NEG_BDY;

    if ( (x+len) == blen )  _flags |= ot::TreeNode::X_POS_BDY;
    if ( (y+len) == blen )  _flags |= ot::TreeNode::Y_POS_BDY;
    if ( (z+len) == blen )  _flags |= ot::TreeNode::Z_POS_BDY;

    if(flags) {
      *flags = _flags;
    }
    return _flags;
  }//end function
Пример #8
0
Entry*
NameTree::findExactMatch(const Name& name, size_t prefixLen) const
{
  prefixLen = std::min(name.size(), prefixLen);
  if (prefixLen > getMaxDepth()) {
    return nullptr;
  }

  const Node* node = m_ht.find(name, prefixLen);
  return node == nullptr ? nullptr : &node->entry;
}
Пример #9
0
int getMaxDepth(Node *root,int currentDepth)
{
	static char firstCall = 'Y';

	// Set currentPath to 0 for first call
	if (firstCall == 'Y')
	{
		currentDepth = 0;
		firstCall = 'N';
	}

	// If no root, depth 0
	if (!root)
	{
		return currentDepth;
	}
	

	// Increment the depth by 1
	++currentDepth;

	// Initialize the left & right child depth to current depth
	int leftChildDepth = currentDepth;
	int rightChildDepth = currentDepth;

	if (root->leftChild)
	{
		leftChildDepth = getMaxDepth(root->leftChild, currentDepth);
	}

	if (root->rightChild)
	{
		rightChildDepth = getMaxDepth(root->rightChild, currentDepth);
	}

	// return the max of the child depth
	return (leftChildDepth>rightChildDepth? leftChildDepth:rightChildDepth);
}
Пример #10
0
int getDepthOfBinaryTree(BinaryTreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	
	int currentDepth = 0;
	int maxDepth = 0;
	
	getMaxDepth(root, currentDepth, maxDepth);
	
	return maxDepth;
}
Пример #11
0
Entry*
NameTree::findLongestPrefixMatch(const Name& name, const EntrySelector& entrySelector) const
{
  size_t depth = std::min(name.size(), getMaxDepth());
  HashSequence hashes = computeHashes(name, depth);

  for (ssize_t i = depth; i >= 0; --i) {
    const Node* node = m_ht.find(name, i, hashes);
    if (node != nullptr && entrySelector(node->entry)) {
      return &node->entry;
    }
  }

  return nullptr;
}
Пример #12
0
  std::vector<bool> ot::TreeNode  ::getMorton() const {
    unsigned int dim = getDim();
    unsigned int maxDepth = getMaxDepth();
    unsigned int Ln = 1;
    if(maxDepth > 0) {
      Ln = binOp::binLength(maxDepth);
    }
    unsigned int const N = (dim*maxDepth) + Ln;
    std::vector<bool> numBin(N);
    std::vector<bool> xBin(maxDepth);
    std::vector<bool> yBin(maxDepth);
    std::vector<bool> zBin(maxDepth);
    std::vector<bool> levBin(Ln);

    //create Binary Representations
    binOp::toBin(getX(), maxDepth, xBin);
    if(dim > 1) { binOp::toBin(getY(), maxDepth, yBin); }
    if(dim > 2) { binOp::toBin(getZ(), maxDepth, zBin); }
    binOp::toBin(getLevel(), Ln, levBin);

    //Interleave bits
    if(dim > 2) {
      for(unsigned int j = 0; j < maxDepth; j++) {        
        numBin[(j*dim)] = zBin[j];
        numBin[((j*dim)+1)] = yBin[j];
        numBin[((j*dim)+2)] = xBin[j];
      }//end for  
    }else if(dim > 1) {
      for(unsigned int j = 0; j < maxDepth; j++) {        
        numBin[(j*dim)] = yBin[j];
        numBin[((j*dim)+1)] = xBin[j];
      }//end for  
    }else {
      for(unsigned int j = 0; j < maxDepth; j++) {        
        numBin[j] = xBin[j];
      }//end for  
    }//end if-else

    //Append level
    for(unsigned int j = 0; j < Ln; j++) {
      numBin[((maxDepth*dim)+j)] = levBin[j];
    }

    return numBin ;
  }
Пример #13
0
Entry&
NameTree::lookup(const pit::Entry& pitEntry)
{
  const Name& name = pitEntry.getName();
  NFD_LOG_TRACE("lookup(PIT " << name << ')');
  bool hasDigest = name.size() > 0 && name[-1].isImplicitSha256Digest();
  if (hasDigest && name.size() <= getMaxDepth()) {
    return this->lookup(name);
  }

  Entry* nte = this->getEntry(pitEntry);
  BOOST_ASSERT(nte != nullptr);
  BOOST_ASSERT(std::count_if(nte->getPitEntries().begin(), nte->getPitEntries().end(),
    [&pitEntry] (const shared_ptr<pit::Entry>& pitEntry1) {
      return pitEntry1.get() == &pitEntry;
    }) == 1);
  return *nte;
}
Пример #14
0
Entry*
NameTree::findLongestPrefixMatch(const pit::Entry& pitEntry, const EntrySelector& entrySelector) const
{
  const Entry* nte = this->getEntry(pitEntry);
  BOOST_ASSERT(nte != nullptr);

  const Name& name = pitEntry.getName();
  size_t depth = std::min(name.size(), getMaxDepth());
  if (nte->getName().size() < pitEntry.getName().size()) {
    // PIT entry name either exceeds depth limit or ends with an implicit digest: go deeper
    for (size_t i = nte->getName().size() + 1; i <= depth; ++i) {
      const Entry* exact = this->findExactMatch(name, i);
      if (exact == nullptr) {
        break;
      }
      nte = exact;
    }
  }

  return this->findLongestPrefixMatch(*nte, entrySelector);
}
Пример #15
0
Entry&
NameTree::lookup(const Name& name, size_t prefixLen)
{
  NFD_LOG_TRACE("lookup(" << name << ", " << prefixLen << ')');
  BOOST_ASSERT(prefixLen <= name.size());
  BOOST_ASSERT(prefixLen <= getMaxDepth());

  HashSequence hashes = computeHashes(name, prefixLen);
  const Node* node = nullptr;
  Entry* parent = nullptr;

  for (size_t i = 0; i <= prefixLen; ++i) {
    bool isNew = false;
    std::tie(node, isNew) = m_ht.insert(name, i, hashes);

    if (isNew && parent != nullptr) {
      node->entry.setParent(*parent);
    }
    parent = &node->entry;
  }
  return node->entry;
}
	void SerialRandomTree::build(){
		// create the attribute indices window
		m_attIndicesWindow = std::vector<int>(data->numAttributes,0);
		int j = 0;
		for(int i = 0; i < m_attIndicesWindow.size(); i++){
			m_attIndicesWindow[i] = j++;
		}

		data->whatGoesWhere = std::vector<int>(data->inBag.size(),0);
		data->createInBagSortedIndices();

		int unprocessedNodes = 1;
		int newNodes = 0;
		
		SerialTreeNodePtr currentNode = SerialTreeNodePtr(new SerialTreeNode);
		currentNode->sortedIndices = (*data->sortedIndices);

		// compute initial class counts
		currentNode->classProbs = std::vector<double>(data->numClasses,0);
		for(int i = 0; i < data->numInstances; i++) {
			currentNode->classProbs[(*data->instClassValues)[i]] += (*data->instWeights)[i];
		}

		m_depth = 0;
		m_treeNodes.push_back(currentNode);
		while(unprocessedNodes != 0){
			// Iterate through unprocessed nodes
			while(unprocessedNodes != 0){
				currentNode = m_treeNodes[m_treeNodes.size()-(unprocessedNodes+newNodes)];

				// Check if node is a leaf
				if((currentNode->sortedIndices.size() > 0  &&  currentNode->sortedIndices[0].size() < max(2, getMinNum()))  // small
					|| (abs(currentNode->classProbs[maxIndex(currentNode->classProbs)] - sum(currentNode->classProbs)) < 1e-6)      // pure
					|| ((getMaxDepth() > 0)  &&  (m_depth >= getMaxDepth()))                           // deep
					){
					createLeafNode(currentNode);
					currentNode->clean();
				}
				else{
					if(findSplit(currentNode)){
						createSplitNodes(currentNode,newNodes);
						currentNode->clean();
					}
					else{
						createLeafNode(currentNode);
						currentNode->clean();
					}
				}
				unprocessedNodes--;
			}
			m_depth++;
			unprocessedNodes = newNodes;
			newNodes = 0;
		}

		m_nodesInTree = m_treeNodes.size();

		data.reset();
		m_dists.clear();
		m_splits.clear();
		m_props.clear();
		m_vals.clear();

		m_dists.shrink_to_fit();
		m_splits.shrink_to_fit();
		m_props.shrink_to_fit();
		m_vals.shrink_to_fit();
	}
Пример #17
0
// Stop criteria:
// 1) When all the training examples agree at each leaf node: in this
//    case we can just return either 1.0 or 0.0 for each leaf node.
// 2) When we have no more examples down a particular branch:
//    we can then assign a default value, such as the overall fraction of
//    positive examples in the entire training set, or the overall fraction 
//    of positive examples under the parent node
// 3) When we have no more attributes to split on: Then we let pl be the
//    proportion of positive examples in that part of the tree.
DecisionTree::Node* DecisionTree::recursiveTrainTree
(const vector<TrainingExample*>& examples, 
 const vector<double>& weights, double sum_weights,
 const set<size_t>& used_feature_indeces) {
  // split on feature that gives greatest increase in the log likelihood..
  // (the feature that gives greatest reduction in entropy)..
  // if((used_feature_indeces.size()==m_features.size())) {
  assert(examples.size()>0);
  assert(examples.size()==weights.size());
  size_t num_features = examples[0]->getNumberOfFeatures();
  if((used_feature_indeces.size()==num_features) || 
     (used_feature_indeces.size()==getMaxDepth())) { // all used up
    // stop criteria 3...
    double pl = countPositiveClassLabels
                     (m_positive_label, examples, weights)/sum_weights;
    Node* T = new Node(this, pl); // leaf
    // cerr << "encountered main leaf: features used up.\n";
    return T;
  }
 
  size_t chosen_feature_index = 
               chooseFeature(m_positive_label, examples, weights, sum_weights,
                             m_feature_thresholds, used_feature_indeces);
  if(chosen_feature_index==(size_t)(-1)) { // all examples are one or the other
    double pl = countPositiveClassLabels
                     (m_positive_label, examples,weights)/sum_weights;
    Node* T = new Node(this, pl); // leaf
    // cerr << "encountered main leaf: invalid chosen_feature_index, all examples one or the other.\n";
    return T;
  }
  set<size_t> now_used_feature_indeces = used_feature_indeces;
  now_used_feature_indeces.insert(chosen_feature_index);
  // cerr << "Chosen feature ["<< chosen_feature_index<< "]: " << m_features[chosen_feature_index] << endl;
  // make this the root of the tree
  Node* T = new Node(this, chosen_feature_index);
  // instead of for loop over values v of feature, we just have two...
  vector<TrainingExample*> above_examples;
  vector<TrainingExample*> below_examples;
  vector<double> above_weights;
  vector<double> below_weights;
  double sum_above_weights = 0;
  double sum_below_weights = 0;
  splitExamplesByThreshold(above_examples, above_weights, sum_above_weights,
                           below_examples, below_weights, sum_below_weights,
                           examples, weights, sum_weights,
                           chosen_feature_index,
                           m_feature_thresholds[chosen_feature_index]);
  Node* right_child=0;
  double count_positive_class_labels_for_above_examples = 
                 countPositiveClassLabels(m_positive_label, 
                              above_examples, above_weights);
  if(above_examples.size()==0) { // stop criteria 2... (use parents examples)...
    double pl = count_positive_class_labels_for_above_examples/sum_weights;
    right_child = new Node(this,pl); // leaf
    // cerr << "encountered right leaf: no above examples\n";
  } else if(count_positive_class_labels_for_above_examples==sum_above_weights) {
    // stop criteria 1... (use probability 1)...
    right_child = new Node(this, 1.0); // leaf
    // cerr << "encountered right leaf: no negative examples in class 'above'\n";
  } else if(count_positive_class_labels_for_above_examples==0) {
    // stop criteria 1... (use probability 0)...
    right_child = new Node(this, 0.0); // leaf
    // cerr << "encountered right leaf: no positive examples in class 'above'\n";
  } else {
    // cerr << "Splitting right on feature [" << chosen_feature_index << "]: \"" << m_features[chosen_feature_index];
    // cerr << "\" using " << above_examples.size() << " 'above' examples\n";
    right_child = recursiveTrainTree(above_examples, above_weights, 
                                     sum_above_weights, now_used_feature_indeces);
  }
  T->setRightChild(right_child);
 
  Node* left_child=0; 
  double count_positive_class_labels_for_below_examples = 
                 countPositiveClassLabels(m_positive_label, 
                            below_examples, below_weights);
  if(below_examples.size()==0) { // stop criteria 2... (use parents examples)...
    double pl = count_positive_class_labels_for_below_examples/sum_weights;
    left_child = new Node(this,pl); // leaf
    // cerr << "encountered left leaf: no examples in class 'below'\n";
  } else if(count_positive_class_labels_for_below_examples==sum_below_weights) {
    // stop criteria 1... (use probability 1)...
    left_child = new Node(this, 1.0); // leaf
    // cerr << "encountered left leaf: no positive examples in class 'below'\n";
  } else if(count_positive_class_labels_for_below_examples==0) {
    // stop criteria 1... (use probability 0)...
    left_child = new Node(this, 0.0); // leaf
    // cerr << "encountered left leaf: no negative examples in class 'below'\n";
  } else {
    // cerr << "Splitting left on feature [" << chosen_feature_index << "]: \"" << m_features[chosen_feature_index];
    // cerr << "\" using " << below_examples.size() << " 'below' examples\n";
    left_child = recursiveTrainTree(below_examples, below_weights,
                                    sum_below_weights, now_used_feature_indeces);
  }
  T->setLeftChild(left_child);
  
  return T; 
}
Пример #18
0
int BinarySearchTree::getMaxDepth()
{
	return getMaxDepth(this->root);
}
Пример #19
0
  int TreeNode ::balanceSubtree(std::vector<TreeNode > & inp,
      std::vector<TreeNode  > & out, bool incCorner,
      bool isSortedCompleteLinear) const {

    PROF_BAL_SUBTREE_BEGIN

      unsigned int dim = getDim();
    unsigned int maxDepth = getMaxDepth();	
    unsigned int maxCornerX = this->maxX();	
    unsigned int maxCornerY = this->maxY();	
    unsigned int maxCornerZ = this->maxZ();	
    unsigned int minLevInp = maxDepth;
    unsigned int maxLevInp = 0;

    out.clear();
    if( (maxDepth == 0) || (getLevel() == maxDepth) || (inp.empty()) ) {
      //No decendants.
      PROF_BAL_SUBTREE_END
    }

    std::vector<TreeNode > *workVec = NULL;
    unsigned int *workVecSz = NULL;	

    if(maxDepth - getLevel()) {
      workVec = new std::vector<TreeNode >[maxDepth - getLevel()];	
      workVecSz = new unsigned int [maxDepth-getLevel()];	
    }

    for(unsigned int i = 0; i < (maxDepth - getLevel()); i++) {
      workVecSz[i] = 0;
    }

    for(unsigned int i = 0; i < inp.size(); i++) {
#ifdef __DEBUG_TN__
      assert(areComparable(*this, inp[i]));
#endif
      if( this->isAncestor(inp[i]) ) {
        unsigned int currOctLev = inp[i].getLevel();
        workVecSz[maxDepth - currOctLev]++;
        if(currOctLev < minLevInp) {
          minLevInp = currOctLev;
        }
        if(currOctLev > maxLevInp) {
          maxLevInp = currOctLev;
        }
      }//end if decendant of block
    }//end for

    if(isSortedCompleteLinear && ((maxLevInp - minLevInp) < 2) ) {
      //Already balanced
      out = inp;

      if(workVecSz) {
        delete [] workVecSz;
        workVecSz = NULL;
      }

      if(workVec) {
        delete [] workVec;
        workVec = NULL;
      }

      PROF_BAL_SUBTREE_END
    }
Пример #20
0
JNIEXPORT jint JNICALL Java_FTAGUI_FTACanvas_nativeGetMaxDepth(JNIEnv *env, jobject obj){
	jint maxDepth;

	maxDepth = getMaxDepth();
	return maxDepth;
}
		int maxDepth(TreeNode* root) {
			if (!root) { return 0; }
			int maxDepth = 0;
			getMaxDepth(root, 1, maxDepth);
			return maxDepth;
		}
Пример #22
0
unsigned ClusterAlg::getDist(ClusterAlg* other)
{
  // construct graph
  MGraph<ClusterAlg*, unsigned> *graph (constructGraph ( other ));

  // compute path(s)
  std::list<ClusterAlg*> path0, path1, path2;
  unsigned dist0 (graph->getPathsAndDist ( this, other, path0, path1, path2 ));
  unsigned dist1(std::numeric_limits<unsigned>::max()), dist2(dist1), tmp_dist;
  delete graph;

  // *** first level refinement
  // compute refined graph for path0
  unsigned max_depth (depth), refine_level(3);
  getMaxDepth(max_depth);
  if (max_depth - depth < refine_level) refine_level = max_depth - depth;
  if (refine_level != 0) {
    refine_level += depth;
    graph = constructRefinedGraph (refine_level, path0);

    // choose a new src and target node in the new graph
    // starting from old src and target
    ClusterAlg*src (*path0.begin()), *target (*(--path0.end()));
    getNode (refine_level, src);
    other->getNode (refine_level, target);

    // compute distance in refined graph
    std::list<ClusterAlg*> path00, path01, path02;
    tmp_dist = graph->getPathsAndDist ( src, target, path00, path01, path02 );

    if (tmp_dist < dist1) dist1 = tmp_dist;

    // tidy up
    if (graph) delete graph;

    // *** second level refinement
    // *** refinement path p00
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3) {
      refine_level += depth;
      graph = constructRefinedGraph(refine_level, path00);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path00.begin();
      target = *(--path00.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path000, path001, path002;
      tmp_dist = graph->getPathsAndDist ( src, target, path000, path001, path002 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }
    // *** refinement path p01
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3 && path01.size() != 0) {
      refine_level += depth;
      graph = constructRefinedGraph (refine_level, path01);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path01.begin();
      target = *(--path01.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path010, path011, path012;
      tmp_dist = graph->getPathsAndDist ( src, target, path010, path011, path012 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }

    // *** refinement path p02
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3 && path02.size() != 0) {
      refine_level += depth;
      graph = constructRefinedGraph (refine_level, path02);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path02.begin();
      target = *(--path02.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path020, path021, path022;
      tmp_dist = graph->getPathsAndDist ( src, target, path020, path021, path022 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }
  }

  // *** first level refinement
  // compute refined graph for path1
  refine_level=3;
  if (max_depth - depth < refine_level) refine_level = max_depth - depth;
  if (refine_level != 0 && path1.size() > 0) {
    refine_level += depth;
    graph = constructRefinedGraph (refine_level, path1);

    // choose a new src and target node in the new graph
    // starting from old src and target
    ClusterAlg *src (*path1.begin()), *target (*(--path1.end()));
    other->getNode (refine_level, target);
    getNode (refine_level, src);

    // std::cout << "\033[32m |p1| " << dist << " \033[0m" << std::flush;
    // compute distance in refined graph
    std::list<ClusterAlg*> path10, path11, path12;
    tmp_dist = graph->getPathsAndDist ( src, target, path10, path11, path12 );

    if (tmp_dist < dist1) dist1 = tmp_dist;

    // tidy up
    if (graph) delete graph;

    // *** second level refinement
    // *** refinement path p10
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3) {
      refine_level += depth;
      graph = constructRefinedGraph (refine_level, path10);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path10.begin();
      target = *(--path10.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path100, path101, path102;
      tmp_dist = graph->getPathsAndDist ( src, target, path100, path101, path102 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }
    // *** refinement path p11
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3 && path11.size() != 0) {
      refine_level += depth;
      graph = constructRefinedGraph (refine_level, path11);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path11.begin();
      target = *(--path11.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path110, path111, path112;
      tmp_dist = graph->getPathsAndDist ( src, target, path110, path111, path112 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }

    // *** refinement path p12
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3 && path12.size() != 0) {
      refine_level += depth;
      graph = constructRefinedGraph (refine_level, path12);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path12.begin();
      target = *(--path12.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path120, path121, path122;
      tmp_dist = graph->getPathsAndDist ( src, target, path120, path121, path122 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }
  }
  // *** first level refinement
  // compute refined graph for path2
  refine_level=3;
  if (max_depth - depth < refine_level) refine_level = max_depth - depth;
  if (refine_level != 0 && path2.size() > 0) {
    refine_level += depth;
    graph = constructRefinedGraph (refine_level, path2);

    // choose a new src and target node in the new graph
    // starting from old src and target
    ClusterAlg *src (*path2.begin()), *target (*(--path2.end()));
    other->getNode (refine_level, target);
    getNode (refine_level, src);

    // compute distance in refined graph
    std::list<ClusterAlg*> path20, path21, path22;
    tmp_dist = graph->getPathsAndDist ( src, target, path20, path21, path22 );

    if (tmp_dist < dist1) dist1 = tmp_dist;

    // tidy up
    if (graph) delete graph;

    // *** second level refinement
    // *** refinement path p20
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3) {
      refine_level += depth;
      graph = constructRefinedGraph (refine_level, path20);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path20.begin();
      target = *(--path20.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path200, path201, path202;
      tmp_dist = graph->getPathsAndDist ( src, target, path200, path201, path202 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }
    // *** refinement path p21
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3 && path21.size() != 0) {
      refine_level += depth;
      graph = constructRefinedGraph (refine_level, path21);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path21.begin();
      target = *(--path21.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path210, path211, path212;
      tmp_dist = graph->getPathsAndDist ( src, target, path210, path211, path212 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }

    // *** refinement path p22
    refine_level=6;
    if (max_depth - depth < refine_level) refine_level = max_depth - depth;
    if (refine_level != 0 && refine_level > 3 && path22.size() != 0) {
      refine_level += depth;
      graph = constructRefinedGraph (refine_level, path22);

      // choose a new src and target node in the new graph
      // starting from old src and target
      src = *path22.begin();
      target = *(--path22.end());
      getNode (refine_level, target);
      other->getNode (refine_level, src);

      // compute distance in refined graph
      std::list<ClusterAlg*> path220, path221, path222;
      tmp_dist = graph->getPathsAndDist ( src, target, path220, path221, path222 );

      if (tmp_dist < dist2) dist2 = tmp_dist;

      // tidy up
      if (graph) delete graph;
    }
  }

  if (dist2 < std::numeric_limits<unsigned>::max())
    return dist2;
  if (dist1 < std::numeric_limits<unsigned>::max())
    return dist1;

  return dist0;
}