//-------------------------------------------------------------------------------------------------- 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); } } }