URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-03-14 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Disambiguate component tree iterators.
* mln/morpho/tree/data.hh:
Add children image to get instant access to child relationship.
Remove mln_fwd_piter, mln_bkd_piter and mln_piter definition
from tree structure.
Add mln_up_site_piter, mln_dn_site_piter, mln_up_node_piter,
mln_dn_node_piter iterator adaptator.
Add mln_preorder_piter, the preorder tree traversal
iterator.
Move inline code out of class definition.
* sandbox/edwin/tree/propagate_node.hh: Fix with new iterator,
but not yet optimized with new tree structure.
* sandbox/edwin/tree/propagate_value.hh: Fix with new
iterator, but not yet optimized with new tree structure.
* sandbox/edwin/tree/propagation.cc: Update test file.
---
mln/morpho/tree/data.hh | 462 +++++++++++++++++++++++++++-------
sandbox/edwin/tree/propagate_node.hh | 10
sandbox/edwin/tree/propagate_value.hh | 12
sandbox/edwin/tree/propagation.cc | 31 ++
4 files changed, 410 insertions(+), 105 deletions(-)
Index: trunk/milena/mln/morpho/tree/data.hh
===================================================================
--- trunk/milena/mln/morpho/tree/data.hh (revision 3530)
+++ trunk/milena/mln/morpho/tree/data.hh (revision 3531)
@@ -38,10 +38,27 @@
/// learn why we want the 1st pass to be in forward scan of s).
# include <mln/morpho/tree/compute_parent.hh>
-# include <mln/core/image/sub_image.hh>
+//# include <mln/core/image/sub_image.hh>
# include <mln/core/site_set/p_array.hh>
-# include <mln/core/site_set/p_set.hh>
-# include <mln/data/fill.hh>
+# include <mln/core/internal/site_set_iterator_base.hh>
+# include <mln/core/internal/piter_identity.hh>
+# include <deque>
+
+# define mln_up_site_piter(T) typename T::up_site_piter
+# define mln_dn_site_piter(T) typename T::dn_site_piter
+# define mln_up_node_piter(T) typename T::up_node_piter
+# define mln_dn_node_piter(T) typename T::dn_node_piter
+# define mln_preorder_piter(T) typename T::preorder_piter
+
+# define mln_up_site_piter_(T) T::up_site_piter
+# define mln_dn_site_piter_(T) T::dn_site_piter
+# define mln_up_node_piter_(T) T::up_node_piter
+# define mln_dn_node_piter_(T) T::dn_node_piter
+# define mln_preorder_piter_(T) T::preorder_piter
+
+// FIXME: rename these iterators.
+//# define mln_up_leaf_piter(T) typename T::up_leaf_piter;
+//# define mln_dn_leaf_piter(T) typename T::dn_leaf_piter;
namespace mln
{
@@ -52,144 +69,243 @@
namespace tree
{
+ // Forward declarations.
+
+ /// Iterate on tree's sites from leaves to roots.
+ template <typename T> struct up_site_piter;
+
+ /// Iterate on tree's sites from roots to leaves.
+ template <typename T> struct dn_site_piter;
+
+ /// Iterate on tree's nodes (component representants) from leaves to roots.
+ template <typename T> struct up_node_piter;
+
+ /// Iterate on tree's nodes (component representants) from leaves to roots.
+ template <typename T> struct dn_node_piter;
+
+ /// Preorder tree traversal iterator.
+ template <typename T> struct preorder_piter;
+
+ /// Postorder tree traversal iterator.
+ //template <typename T> struct postorder_piter;
+
// FIXME: Doc!
+
+
template <typename I, typename S>
class data
{
- public:
-
+ typedef data<I, S> self_;
+ public:
/// Associated type of the function f.
typedef I function;
+ /// Psite associated type.
+ typedef mln_psite(I) psite;
+ typedef mln_site(I) site;
+ /// Site set associated type.
+ typedef S sites_t;
+ /// Node list associated type.
+ typedef p_array<mln_psite(I)> nodes_t;
+ /// Parent image associated type.
+ typedef mln_ch_value(I, mln_psite(I)) parent_t;
- /// Ctor.
+ // Iterate on all sites.
+ typedef mln::morpho::tree::up_site_piter<self_> up_site_piter;
+ typedef mln::morpho::tree::dn_site_piter<self_> dn_site_piter;
+
+ // Iterate on nodes only.
+ typedef mln::morpho::tree::up_node_piter<self_> up_node_piter;
+ typedef mln::morpho::tree::dn_node_piter<self_> dn_node_piter;
+
+ typedef mln::morpho::tree::preorder_piter<self_> preorder_piter;
+
+// typedef mln_bkd_piter(S) piter;
+// typedef mln_bkd_piter(S) fwd_piter;
+// typedef mln_fwd_piter(S) bkd_piter;
+
+ /// Constructor.
template <typename N>
- data(const Image<I>& f, const Site_Set<S>& s, const
Neighborhood<N>& nbh);
+ explicit data(const Image<I>& f, const Site_Set<S>& s, const
Neighborhood<N>& nbh);
/// \{ Parent-related materials.
- typedef mln_ch_value(I, mln_psite(I)) parent_t;
+ const mln_psite(I)& parent(const mln_psite(I)& p) const;
+ const parent_t& parent_image() const;
+
+ /// \}
- const mln_psite(I)& parent(const mln_psite(I)& p) const
+ const p_array<mln_psite(I)>& children(const mln_psite(I)& p) const
{
- mln_precondition(is_valid());
- mln_precondition(parent_.domain().has(p));
- return parent_(p);
+ return children_(p);
}
- const parent_t& parent_image() const
+ const mln_ch_value(I, nodes_t)& children_image() const
{
- mln_precondition(is_valid());
- return parent_;
+ return children_;
}
- /// \}
+ /// \{ Tests.
+ bool is_valid() const;
+ bool is_root(const mln_psite(I)& p) const;
+ bool is_a_node(const mln_psite(I)& p) const;
+ bool is_a_non_root_node(const mln_psite(I)& p) const;
+ bool is_a_leaf(const mln_psite(I)& p) const;
- /// \{ Tests.
+ /// \}
- bool is_valid() const
- {
- return parent_.is_valid(); // FIXME: and... (?)
- }
- bool is_root(const mln_psite(I)& p) const
- {
- mln_precondition(is_valid());
- mln_precondition(parent_.domain().has(p));
- return parent_(p) == p;
- }
+ /// \{ Nodes-related materials.
- bool is_a_node(const mln_psite(I)& p) const
- {
- mln_precondition(is_valid());
- mln_precondition(parent_.domain().has(p));
- return parent_(p) == p || f_(parent_(p)) != f_(p);
- }
+ const p_array<mln_psite(I)>& nodes() const;
- bool is_a_non_root_node(const mln_psite(I)& p) const
- {
- mln_precondition(is_valid());
- mln_precondition(parent_.domain().has(p));
- return f_(parent_(p)) != f_(p);
- }
+ /// \}
- /// Return true iff p is a leaf (in log time).
- bool is_a_leaf(const mln_psite(I)& p) const
- {
- mln_precondition(is_valid());
- mln_precondition(parent_.domain().has(p));
- return leaves_.has(p);
- }
+ /// \{ Sites-related materials.
+
+ const S& domain() const;
/// \}
+ unsigned nroots() const;
- /// \{ Nodes-related materials.
- typedef p_array<mln_psite(I)> nodes_t;
+ const I& f() const;
- const p_array<mln_psite(I)>& nodes() const
- {
- mln_precondition(is_valid());
- return nodes_;
- }
- /// \}
+ mln_rvalue(I) f(const mln_psite(I)& p) const;
- /// \{ Nodes-related materials.
+ protected:
+ const function& f_;
+ const sites_t& s_;
+ mln_ch_value(I, mln_psite(I)) parent_; // Parent image.
+ mln_ch_value(I, nodes_t) children_; // Children image.
+ nodes_t nodes_;
+ unsigned nroots_;
+ };
+
- typedef p_set<mln_psite(I)> leaves_t;
+ template <typename T>
+ struct up_site_piter
+ : public mln::internal::piter_identity_< typename T::sites_t::bkd_piter, // Adaptee.
+ up_site_piter<T> > // Exact.
+ {
+ private:
+ typedef typename T::sites_t::bkd_piter Pi_;
+ typedef mln::internal::piter_identity_< Pi_, up_site_piter<T> > super_;
- const leaves_t& leaves() const
+ public:
+ up_site_piter(const T& t)
{
- mln_precondition(is_valid());
- return leaves_;
+ this->change_target(t.domain());
}
- /// \}
+ up_site_piter(const Pi_& pi)
+ : super_(pi)
+ {
+ }
+ };
- /// \{ How-to iterate on all sites.
+ template <typename T>
+ struct dn_site_piter
+ : public mln::internal::piter_identity_< typename T::sites_t::fwd_piter, // Adaptee.
+ dn_site_piter<T> > // Exact.
+ {
+ private:
+ typedef typename T::sites_t::fwd_piter Pi_;
+ typedef mln::internal::piter_identity_< Pi_, dn_site_piter<T> > super_;
- typedef mln_bkd_piter(S) piter;
- typedef mln_bkd_piter(S) fwd_piter;
- typedef mln_fwd_piter(S) bkd_piter;
+ public:
+ dn_site_piter(const T& t)
+ {
+ this->change_target(t.domain());
+ }
- const S& domain() const
+ dn_site_piter(const Pi_& pi)
+ : super_(pi)
{
- return s_;
}
+ };
- /// \}
+ template <typename T>
+ struct up_node_piter
+ : public mln::internal::piter_identity_< typename T::nodes_t::fwd_piter, // Adaptee.
+ up_node_piter<T> > // Exact.
+ {
+ private:
+ typedef typename T::sites_t::fwd_piter Pi_;
+ typedef mln::internal::piter_identity_< Pi_, up_node_piter<T> > super_;
- unsigned nroots() const
+ public:
+ up_node_piter(const T& t)
{
- return nroots_;
+ this->change_target(t.nodes());
}
- const I& f() const
+ up_node_piter(const Pi_& pi)
+ : super_(pi)
{
- return f_;
}
+ };
- mln_rvalue(I) f(const mln_psite(I)& p) const
+ template <typename T>
+ struct dn_node_piter
+ : public mln::internal::piter_identity_< typename T::nodes_t::bkd_piter, // Adaptee.
+ dn_node_piter<T> > // Exact.
+ {
+ private:
+ typedef typename T::sites_t::bkd_piter Pi_;
+ typedef mln::internal::piter_identity_< Pi_, dn_node_piter<T> > super_;
+
+ public:
+ dn_node_piter(const T& t)
{
- return f_(p);
+ this->change_target(t.nodes());
}
- protected:
+ dn_node_piter(const Pi_& pi)
+ : super_(pi)
+ {
+ }
+ };
- const I& f_;
- const S& s_;
- mln_ch_value(I, mln_psite(I)) parent_;
- leaves_t leaves_;
- p_array<mln_psite(I)> nodes_;
- unsigned nroots_;
+ template <typename T>
+ class preorder_piter
+ : public mln::internal::site_set_iterator_base< T, preorder_piter<T> >
+ {
+ typedef preorder_piter<T> self_;
+ typedef mln::internal::site_set_iterator_base<T, self_> super_;
+
+ public:
+
+ /// Constructor with no argument.
+ preorder_piter();
+
+ /// Constructor.
+ preorder_piter(const T& t);
+
+ /// Test if the iterator is valid.
+ bool is_valid_() const;
+
+ /// Invalidate the iterator.
+ void invalidate_();
+
+ /// Start an iteration.
+ void start_();
+
+ /// Go to the next point.
+ void next_();
+
+ protected:
+ using super_::p_;
+ using super_::s_;
+ std::deque<mln_psite(T)> stack_; // FIXME: implement p_stack.
};
@@ -208,6 +324,7 @@
// Compute parent image.
parent_ = morpho::tree::compute_parent(f_, nbh_, s_);
+ initialize(children_, f);
// Store tree nodes.
nroots_ = 0;
@@ -217,6 +334,7 @@
if (f_(parent_(p)) != f_(p))
{
nodes_.insert(p);
+ children_(parent_(p)).insert(p);
}
else
if (parent_(p) == p)
@@ -225,21 +343,183 @@
++nroots_;
}
}
+ }
+
+ template <typename I, typename S>
+ inline
+ const mln_psite(I)&
+ data<I,S>::parent(const mln_psite(I)& p) const
+ {
+ mln_precondition(is_valid());
+ mln_precondition(parent_.domain().has(p));
+ return parent_(p);
+ }
+
+ template <typename I, typename S>
+ inline
+ const mln_ch_value(I, mln_psite(I))&
+ data<I,S>::parent_image() const
+ {
+ mln_precondition(is_valid());
+ return parent_;
+ }
+
+ template <typename I, typename S>
+ inline
+ bool
+ data<I,S>::is_valid() const
+ {
+ return parent_.is_valid(); // FIXME: and... (?)
+ }
+
+ template <typename I, typename S>
+ inline
+ bool
+ data<I,S>::is_root(const mln_psite(I)& p) const
+ {
+ mln_precondition(is_valid());
+ mln_precondition(parent_.domain().has(p));
+ return parent_(p) == p;
+ }
+
+
+ template <typename I, typename S>
+ inline
+ bool
+ data<I,S>::is_a_node(const mln_psite(I)& p) const
+ {
+ mln_precondition(is_valid());
+ mln_precondition(parent_.domain().has(p));
+ return parent_(p) == p || f_(parent_(p)) != f_(p);
+ }
+
+ template <typename I, typename S>
+ inline
+ bool
+ data<I,S>::is_a_non_root_node(const mln_psite(I)& p) const
+ {
+ mln_precondition(is_valid());
+ mln_precondition(parent_.domain().has(p));
+ return f_(parent_(p)) != f_(p);
+ }
+
+
+ template <typename I, typename S>
+ inline
+ bool
+ data<I,S>::is_a_leaf(const mln_psite(I)& p) const
+ {
+ mln_precondition(is_valid());
+ mln_precondition(children_.domain().has(p));
+ return children_(p).nsites() == 0;
+ }
+
+ template <typename I, typename S>
+ inline
+ const p_array<mln_psite(I)>&
+ data<I,S>::nodes() const
+ {
+ mln_precondition(is_valid());
+ return nodes_;
+ }
+
+ template <typename I, typename S>
+ inline
+ const S&
+ data<I,S>::domain() const
+ {
+ return s_;
+ }
+
+ template <typename I, typename S>
+ inline
+ unsigned
+ data<I,S>::nroots() const
+ {
+ return nroots_;
+ }
+
+ template <typename I, typename S>
+ inline
+ const I&
+ data<I,S>::f() const
+ {
+ return f_;
+ }
+
+ template <typename I, typename S>
+ inline
+ mln_rvalue(I)
+ data<I,S>::f(const mln_psite(I)& p) const
+ {
+ return f_(p);
+ }
+
+
+
+ // Iterators.
+
+
+ template <typename T>
+ inline
+ preorder_piter<T>::preorder_piter()
+ {
+ }
+
+ template <typename T>
+ inline
+ preorder_piter<T>::preorder_piter(const T& t)
+ {
+ this->change_target(t);
+ }
- // Store leaves.
- mln_ch_value(I, bool) deja_vu;
- initialize(deja_vu, f);
- mln::data::fill(deja_vu, false);
-
- mln_fwd_piter(nodes_t) n(nodes_);
- for_all(n)
- {
- deja_vu(parent_(n)) = true;
- if (!deja_vu(n))
- leaves_.insert(n);
+ template <typename T>
+ inline
+ bool
+ preorder_piter<T>::is_valid_() const
+ {
+ return !stack_.empty();
}
+
+ template <typename T>
+ inline
+ void
+ preorder_piter<T>::invalidate_()
+ {
+ stack_.clear();
}
+ template <typename T>
+ inline
+ void
+ preorder_piter<T>::start_()
+ {
+ this->invalidate();
+ mln_dn_node_piter(T) n(s_->nodes());
+ int roots = 0;
+ for (n.start(); n.is_valid() && roots < s_->nroots(); n.next())
+ if (s_->is_root(n))
+ {
+ stack_.push_back(n);
+ roots++;
+ }
+
+ this->next();
+ }
+
+ template <typename T>
+ inline
+ void
+ preorder_piter<T>::next_()
+ {
+ p_ = stack_.back();
+ stack_.pop_back();
+ mln_fwd_piter(T::nodes_t) child(s_->children(p_));
+ for_all(child)
+ stack_.push_back(child);
+ }
+
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::morpho::tree
Index: trunk/milena/sandbox/edwin/tree/propagate_node.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate_node.hh (revision 3530)
+++ trunk/milena/sandbox/edwin/tree/propagate_node.hh (revision 3531)
@@ -51,7 +51,7 @@
*/
template <typename T, typename A>
void
- propagate_node_to_descendants(mln_bkd_piter(T::nodes_t)& n,
+ propagate_node_to_descendants(mln_dn_node_piter(T)& n,
const T& t,
Image<A>& a_,
mln_value(A) v);
@@ -65,7 +65,7 @@
*/
template <typename T, typename A>
void
- propagate_node_to_descendants(mln_bkd_piter(T::nodes_t)& n,
+ propagate_node_to_descendants(mln_dn_node_piter(T)& n,
const T& t,
Image<A>& a_);
@@ -135,7 +135,7 @@
template <typename T, typename A>
void
- propagate_node_to_descendants(mln_bkd_piter(T::nodes_t)& n,
+ propagate_node_to_descendants(mln_dn_node_piter(T)& n,
const T& t,
Image<A>& a_,
mln_value(A) v)
@@ -151,7 +151,7 @@
data::fill(ancestors, false);
ancestors(n) = true;
- mln_bkd_piter(T::nodes_t) it(n);
+ mln_dn_node_piter(T) it(n);
for (it.next(); it.is_valid(); it.next())
{
if (ancestors(t.parent(it)))
@@ -189,7 +189,7 @@
if (!t.is_a_node(n)) // Get the representant.
n = t.parent(n);
- mln_bkd_piter(T::nodes_t) it = find_bkd(t.nodes(), n);
+ mln_dn_node_piter(T) it(find_bkd(t.nodes(), n));
propagate_node_to_descendants(it, t, a, v);
}
Index: trunk/milena/sandbox/edwin/tree/propagation.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagation.cc (revision 3530)
+++ trunk/milena/sandbox/edwin/tree/propagation.cc (revision 3531)
@@ -32,6 +32,20 @@
<< "*********************" << std::endl;
}
+template <typename I>
+void print(I& img, mln_psite(I) p)
+{
+ using namespace mln;
+
+ std::cout << p << " -> ";
+ mln_fwd_piter(p_array<mln_psite(I)>) it(img(p));
+// for_all(it)
+// std::cout << it << " ";
+// std::cout << std::endl;
+ for_all(it)
+ print(img, it);
+}
+
int main(int argc, char* argv[])
{
using namespace mln;
@@ -109,9 +123,20 @@
dsp("Propagate value to descendants : (it_max, tree, dup, 69)");
display_tree_attributes(tree, dup);
-
-
-
+ mln_dn_node_piter_(tree_t) n(tree);
+ n.start();
+ print(tree.children_image(), n);
+
+ std::cout << "\n";
+ mln_preorder_piter_(tree_t) pit(tree);
+ mln_psite_(I) parent;
+ for_all(pit)
+ {
+ if (parent != tree.parent(pit))
+ std::cout << std::endl;
+ std::cout << pit << " -> ";
+ parent = pit;
+ }
}
Index: trunk/milena/sandbox/edwin/tree/propagate_value.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate_value.hh (revision 3530)
+++ trunk/milena/sandbox/edwin/tree/propagate_value.hh (revision 3531)
@@ -83,7 +83,7 @@
template <typename T, typename A>
bool check_propagate_ancestors(const T& t, const A& a, mln_value(A) v)
{
- mln_fwd_piter(T::nodes_t) n(t.nodes());
+ mln_up_node_piter(T) n(t.nodes());
for_all(n)
if (a(n) == v && a(t.parent(n)) != v)
return false;
@@ -93,7 +93,7 @@
template <typename T, typename A>
bool check_propagate_descendants(const T& t, const A& a, mln_value(A) v)
{
- mln_fwd_piter(T::nodes_t) n(t.nodes());
+ mln_up_node_piter(T) n(t.nodes());
for_all(n)
if (a(n) != v && a(t.parent(n)) == v)
return false;
@@ -123,7 +123,7 @@
initialize(deja_vu, a);
data::fill(deja_vu, false);
- mln_fwd_piter(T::nodes_t) n(t.nodes());
+ mln_up_node_piter(T) n(t.nodes());
for_all(n)
{
if (a(n) == v || deja_vu(n))
@@ -148,7 +148,7 @@
mln_precondition(a.is_valid());
mln_precondition(a.domain() == t.f().domain());
- mln_fwd_piter(T::nodes_t) n(t.nodes());
+ mln_up_node_piter(T) n(t.nodes());
for_all(n)
{
if (a(n) == v)
@@ -183,7 +183,7 @@
initialize(deja_vu, a);
data::fill(deja_vu, false);
- mln_bkd_piter(T::nodes_t) n(t.nodes());
+ mln_dn_node_piter(T) n(t.nodes());
for_all(n)
{
if (a(n) == v)
@@ -211,7 +211,7 @@
mln_precondition(a.is_valid());
mln_precondition(a.domain() == t.f().domain());
- mln_bkd_piter(T::nodes_t) n(t.nodes());
+ mln_dn_node_piter(T) n(t.nodes());
for_all(n)
{
if (a(t.parent(n)) == v)