8 #ifndef PAAL_SUBSET_BACKTRACK_HPP
9 #define PAAL_SUBSET_BACKTRACK_HPP
15 #include <boost/range/algorithm/copy.hpp>
16 #include <boost/range/join.hpp>
23 template <
typename Element>
struct tail {
27 std::vector<Element> m_elems;
28 typename std::vector<Element>::const_iterator m_cur_pos;
37 BOOST_CONCEPT_ASSERT((boost::CopyConstructibleConcept<Element>));
38 BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<Element>));
39 const std::size_t INITIAL_TAILS_SIZE = 1;
41 bool m_start_solving =
false;
44 template <
class Elements>
55 boost::iterator_range<typename std::vector<Element>::const_iterator>
57 auto const moves_begin = current_tail().m_cur_pos + m_start_solving,
58 moves_end = current_tail().m_elems.cend();
59 return boost::make_iterator_range(moves_begin, moves_end);
71 template <
typename TryPush,
typename OnPop,
72 typename UpdateMoves = std::mem_fun_ref_t<
73 typename std::vector<Element>::iterator, std::vector<int>>>
75 solve(TryPush try_push, OnPop on_pop,
76 UpdateMoves update_moves = UpdateMoves(&std::vector<Element>::end)) {
78 assert(m_tails.
size() == INITIAL_TAILS_SIZE);
79 if (current_tail().m_elems.empty())
return;
80 auto go_down = [&]() {
81 while (try_push(current_element())) {
82 auto &moves = get_new_tail();
83 moves.erase(update_moves(moves), moves.end());
86 on_pop(current_element());
93 while (try_increase_back()) go_down();
94 if (m_tails.
size() == INITIAL_TAILS_SIZE)
break;
96 on_pop(current_element());
98 current_tail().m_cur_pos = current_tail().m_elems.begin();
99 m_start_solving=
false;
103 std::vector<Element> &get_new_tail() {
105 return current_tail().m_elems;
108 detail::tail<Element> ¤t_tail() {
return m_tails.
top(); }
110 const detail::tail<Element> ¤t_tail()
const {
return m_tails.
top(); }
112 Element current_element()
const {
return *current_tail().m_cur_pos; }
114 bool try_increase_back() {
115 return ++current_tail().m_cur_pos != current_tail().m_elems.end();
118 template <
typename Elements>
void push(Elements &&elements) {
120 auto &new_tail = m_tails.
top();
121 auto &moves = new_tail.m_elems;
122 moves.resize(boost::distance(elements));
123 boost::copy(elements, moves.begin());
124 new_tail.m_cur_pos = moves.begin();
130 template <
class Elements>
stack that doesn't call destructor on pop
std::size_t size() const
size
Concept class for readable range concept.
const T & top() const
top
boost::iterator_range< typename std::vector< Element >::const_iterator > get_moves() const
return range of all Elements that we will be trying to add to the current set
auto make_subset_backtrack(const Elements &elements)
make subset_backtrack
subset_backtrack(const Elements &elements)
constructor
void solve(TryPush try_push, OnPop on_pop, UpdateMoves update_moves=UpdateMoves(&std::vector< Element >::end))
void pop()
pop doesn't call destructor