Beispiel #1
0
//--------------------------------------------------------------------------------------------------
void Index::get_reachable(unsigned x, std::vector<unsigned>& nodes){
	x=g->getNodeId(x);

	if (!intervals[x])
		return;

	IntervalList* intlist = intervals[x];
	const std::vector<unsigned>& lower=intlist->get_lower();
	const std::vector<unsigned>& upper=intlist->get_upper();

	for (unsigned i=0; i < lower.size(); i++){
		for (unsigned node=lower[i]; node<=upper[i];++node){
			nodes.push_back(g->getNodeById(id2node[node]));
		}
	}
}
/*!
 * \param other interval list to merge into this interval list
 */
void IntervalList::merge_exact(const IntervalList& other) {
  // find starting point
  if (other.empty()) {
    return;
  }
  int last_index = 0;

  // intervals of other list
  const std::vector<unsigned>& o_lower = other.get_lower();
  const std::vector<unsigned>& o_upper = other.get_upper();

  // is this interval list is empty, just copy other list
  if (empty()) {
    std::copy(o_lower.begin(), o_lower.end(), std::back_inserter(lower_));
    std::copy(o_upper.begin(), o_upper.end(), std::back_inserter(upper_));
    return;
  } else {
    // for each interval in other list, find relevant position to insert
    unsigned a, b;
    int idxa, idxb;
    bool insa, insb;
    for (unsigned i = 0; i < o_lower.size(); ++i) {
      a = o_lower[i], b = o_upper[i];
      insa = false, insb = false;
      idxa = find(a); //, last_index_);
      (void) last_index;
      idxb = idxa + 1;

      /* distinguish 4 cases a,b between/within intervals */
      // determine
      //    - index of interval containing or left of a, flag: inside
      //    - index of interval containing or right of b, flag: inside
      if (idxa != -1 && a <= upper_[idxa] + 1) {
        insa = true;
      }
      while (idxb < int(lower_.size()) && b >= lower_[idxb] - 1) {
        ++idxb;
      }

      if (idxb != 0 && b <= upper_[idxb - 1] + 1) {
        insb = true;
        --idxb;
      } else {
        insb = false;
      }

      // special cases
      if (!insb && idxb == 0) {
        // before everything
        lower_.insert(lower_.begin(), a);
        upper_.insert(upper_.begin(), b);
        last_index = 0;
        continue;                 // done
      } else if (!insa && idxa == int(lower_.size()) - 1) {
        // after everything
        lower_.push_back(a);
        upper_.push_back(b);
        last_index = lower_.size() - 1;
        continue;                 // done
      }
      if (!insa) {
        ++idxa;
      }
      if (!insb) {
        --idxb;
      }

      if (idxa > idxb) {
        // new interval between existing
        //assert(int(lower_.size()) > idxa);
        lower_.insert(lower_.begin() + idxa, a);
        upper_.insert(upper_.begin() + idxa, b);
        last_index = idxa;
        continue;                 // done
      }

      // update interval boundaries
      lower_[idxa] = std::min(lower_[idxa], a);
      upper_[idxb] = std::max(upper_[idxb], b);

      // general case
      lower_.erase(lower_.begin() + idxa + 1, lower_.begin() + idxb + 1);
      upper_.erase(upper_.begin() + idxa, upper_.begin() + idxb);
      last_index = idxb - idxa - 1;
    }
  }
}
/*!
 * \param other interval list
 */
void IntervalList::merge(const IntervalList& other) {
  // find starting point
  if (other.empty()) {
    return;
  }
  int last_index = 0;

  // other interval list
  const std::vector<unsigned>& o_lower = other.get_lower();
  const std::vector<unsigned>& o_upper = other.get_upper();
  const std::vector<char>& o_exact = other.get_exact();
  //assert((o_lower.size() == o_upper.size()) && (o_lower.size() == o_exact.size()));

  // if this list is empty, just copy other list
  if (empty()) {
    std::copy(o_lower.begin(), o_lower.end(), std::back_inserter(lower_));
    std::copy(o_upper.begin(), o_upper.end(), std::back_inserter(upper_));
    std::copy(o_exact.begin(), o_exact.end(), std::back_inserter(exact_));
    return;
  } else {
    // for each interval in other list, find relevant position to insert
    unsigned a, b;
    char ex;
    int idxa, idxb;
    bool insa, insb;
    for (unsigned i = 0; i < o_lower.size(); ++i) {
      a = o_lower[i], b = o_upper[i];
      ex = o_exact[i];
      insa = false, insb = false;

      // determine idxa
      if (a < lower_.front()) {
        idxa = -1;
      } else if (a > upper_.back()) {
        idxa = upper_.size() - 1;
      } else {
        // no special case, perform binary search
        int _min = last_index, _max = lower_.size(), _mid;
        while (true) {
          if (_min == _max) {
            if (a < lower_[_min]) {
              idxa = _min - 1; // immediately to the left
              break;
            } else {
              idxa = _min; // included in interval, or immediately to the right
              break;
            }
          }
          _mid = (_max + _min) / 2;
          if (lower_[_mid] <= a && a <= upper_[_mid]) {
            idxa = _mid;
            break;
          } else if (a < lower_[_mid]) {
            _max = _mid;
          } else {
            _min = _mid + 1;
          }
        }
      }
      idxb = idxa + 1;

      /* distinguish 4 cases a,b between/within intervals */
      // determine
      //    - index of interval containing or left of a, flag: inside
      //    - index of interval containing or right of b, flag: inside
      if (idxa != -1 && a <= upper_[idxa] + 1) {
        insa = true;
      }
      while (idxb < int(lower_.size()) && b >= lower_[idxb] - 1) {
        ++idxb;
      }

      if (idxb != 0 && b <= upper_[idxb - 1] + 1) {
        insb = true;
        --idxb;
      } else {
        insb = false;
      }

      // special cases
      if (!insb && idxb == 0) {
        // before everything
        lower_.insert(lower_.begin(), a);
        upper_.insert(upper_.begin(), b);
        exact_.insert(exact_.begin(), ex);
        last_index = 0;
        continue;                 // done
      } else if (!insa && idxa == int(lower_.size()) - 1) {
        // after everything
        lower_.push_back(a);
        upper_.push_back(b);
        exact_.push_back(ex);
        last_index = lower_.size() - 1;
        continue;                 // done
      }

      if (!insa) {
        ++idxa;
      }
      if (!insb) {
        --idxb;
      }

      if (idxa > idxb) {
        // new interval between existing
        //assert(int(lower_.size()) > idxa);
        lower_.insert(lower_.begin() + idxa, a);
        upper_.insert(upper_.begin() + idxa, b);
        exact_.insert(exact_.begin() + idxa, ex);
        last_index = idxa;
        continue;                 // done
      }

      // non-exact interval subsumed
      if (!ex && insa && insb && idxa == idxb && lower_[idxa] <= a
          && b <= upper_[idxa]) {
        last_index = idxa;
        continue;
      }

      // update interval boundaries
      lower_[idxa] = std::min(lower_[idxa], a);
      upper_[idxb] = std::max(upper_[idxb], b);

      // general case
      assert(idxb <= int(lower_.size()));
      lower_.erase(lower_.begin() + idxa + 1, lower_.begin() + idxb + 1);
      upper_.erase(upper_.begin() + idxa, upper_.begin() + idxb);
      char new_exact = ex;
      if (ex) {
        for (int i = idxa; i <= idxb; ++i) {
          if (!exact_[i]) {
            new_exact = 0;
            break;
          }
        }
      }
      exact_[idxa] = new_exact;
      exact_.erase(exact_.begin() + idxa + 1, exact_.begin() + idxb + 1);
      last_index = std::max(0, idxa);
    }
  }
}