【发布时间】:2015-10-04 06:32:54
【问题描述】:
我有一个元素序列(通常是std::vector<T>)和一个方法overlap_range(Iterator, Iterator, T),用于获取这些元素的子集,这些元素是overlaped 和T。
如果元素的序列满足某些条件,那么overlap_range 的结果将是连续的,并且可以在对数时间内确定。否则可能存在多个不连续的此类子范围,这些子范围只能在线性时间内确定。确定是否满足条件需要线性时间。
我想要以下内容:
-
overlap_range是多态的,从某种意义上说,如果已知满足条件,算法在对数时间内运行。 - 返回的子范围是多态的,如果满足条件,则能够利用子范围的已知属性。
我建议的解决方案是在overlap_range 中使用默认值标志参数,这可以解决 (1)。然后我想通过使用boost::filter_iterator<std::function<bool(T)>, Iterator> 来解决(2),如果已知满足条件,std::function<bool(T)> 只需返回true。然而,事实证明这是大约。在这两种情况下,都比简单地使用仿函数测试overlaped 慢 50 倍。 overlap 的逻辑并不是特别复杂,但该范围内的元素数量足够大,如果可能的话,不必对其进行不必要的评估,这是一个显着的优势。
还有其他方法可以帮助我解决这个问题吗?
更多详情
虽然我认为以上内容足以理解问题,但这里还有一些可能有用的背景知识。
-
T是可以简化为GenomicRegion的任何对象,它只是在单个连续序列(即两个坐标)上定义一组坐标。任何这样的T实际上是一个Mappable<T>,它基本上需要一个方法get_region。 -
overlaps然后定义为inline GenomicRegion::DifferenceType overlap_size(const GenomicRegion& lhs, const GenomicRegion& rhs) noexcept { return static_cast< GenomicRegion::DifferenceType>(std::min(lhs.get_end(), rhs.get_end())) - static_cast< GenomicRegion::DifferenceType>(std::max(lhs.get_begin(), rhs.get_begin())); } inline bool overlaps(const GenomicRegion& lhs, const GenomicRegion& rhs) noexcept { auto num_bases_overlaped = overlap_size(lhs, rhs); return (num_bases_overlaped == 0) ? !are_adjacent(lhs, rhs) || empty(std::min(lhs, rhs)) : num_bases_overlaped > 0; } - 任何
Mappable类都可以按开始坐标排序,然后是结束坐标(如果开始坐标相等)。 - 对数重叠搜索(和连续的结果区域)的“标准”是:如果
a <= b则为end(a) <= end(b),例如,如果所有T大小相同,则为 true。 -
朴素过滤迭代器定义为
template <typename MappableType> class IsOverlapped { public: IsOverlapped() = delete; template <typename MappableType_> IsOverlapped(const MappableType_& mappable) : region_ {get_region(mappable)} {} bool operator()(const MappableType& mappable) { return overlaps(mappable, region_); } private: GenomicRegion region_; }; template <typename Iterator> using OverlapIterator = boost::filter_iterator<IsOverlapped<typename Iterator::value_type>, Iterator>; template <typename Iterator> using OverlapRange = boost::iterator_range<OverlapIterator<Iterator>>; -
overlap_range然后可以声明为template <typename ForwardIterator, typename MappableType> OverlapRange<ForwardIterator> overlap_range(ForwardIterator first, ForwardIterator last, const MappableType& mappable, bool is_bidirectional=false)
当然,这可以简单地返回范围OverlapRange<ForwardIterator>(first, last),但我们可以通过有效地找到右边界以及如果范围is_bidirectional 的左边界来做得更好。
【问题讨论】: