Alf P. Steinbach wrote:
Quote:
Not quite. With the above structure you'd have to tentatively downcast
(via Boost's dynamic cast) each TreeNode-pointer to see what actual type
it is, i.e. to determine the type T in TreeNode<T>. Unless all nodes in
a tree have the same T, in which case TreeNodeBase doesn't make sense.
>
The question for a proper design is essentially: can a tree have nodes
with different item types?
I see. Actually, there is no general way to find out the type T from a
node pointer: it has to be implemented in some way for some particular
types T. And I suppose I can also drop the possibility to have different
types T as now... I just split the methods related to the tree
operations from the methods related to the items. But you're right, at
the moment I don't need the base class.
Quote:
If the nodes in a given tree can have different item types, I'd suggest
as best solution to require them to be derived from some common abstract
class (an interface class would be best)
that would be NodeBase. It's abstract (of course you couldn't know, I'm
sorry I forgot to say it), having defined:
virtual ~TreeNodeBase() = 0;
(the destructor is implemented as well, it's that funny trick...)
The virtual member allows me to use the dynamic cast functions on the
TreeNode.
Quote:
>, and otherwise, completely
unrelated types, using boost::any (if I recall the name correctly).
>
I can't understand you. If the nodes are all the same, I would just have
the template class TreeNode. Why boost::any?
Quote:
>
Presumably this means that your Items are really graph nodes.
well, they are all the information the node contain, so, mathematically
speaking, they are the graph nodes. In this code, Item is just the
container of the information that I want to associate to a node.
Quote:
If so, then I suggest moving that factory function out of TreeNode.
>
It doesn't generate a TreeNode, it generates a Tree.
Good advice. Conceptually much better. Unfortunately I've written this
code for research purposes and I haven't still had the time to make some
slight improvement in the consistency of every concept.
Quote:
Quote:
>In order to generate the MinimumSanningTree, the
>GenerateMinimumSpanningTree function will use the Tree constructor, in a
>piece of code like:
> std::vector<std::pair<TreeNodePtr, ItemIt trees;
> for(ItemIt item = begin; item != end; ++item)
> trees.push_back(std::make_pair(TreeNodePtr(new
>TreeNode<Item>(*item)),
>item));
>>
>(the vector is used in the algorithm for the minimum spanning tree).
>
Presumably you mean "the TreeNode constructor".
Sorry, of course I did.
Quote:
Quote:
>Then, after I generate like this a tree, in a particular problem I need
>a tree of Descriptors.
>>
>Once I generate this tree of descriptors passing the appropriate forward
>iterators to the GenerateMinimumSpannigTree algorithm, I can give it to
>a class that will perform some classification of this tree. Ok?
>
Not sure exactly what you mean.
>
Is it correct that you mean to generate a /corresponding/ tree of
descriptors?
>
Why not just put the descriptors in the TreeNodes, or if that is frozen
code, use a std::map to associate a descriptor with each TreeNode?
That is, more or less. Actually, I have different possible types of
descriptors, and all of them, for the sake of the graph, resolve to a
simple vector of doubles (with an additional ID that I need for an
algorithm). In order to generate the tree, however, I need more
information, related to the particular kind of descriptor that I'm
using. That's why in the definition of the GenerateMinimuSpanningTree
there is also the template DistanceMeasure function... this will depend
on the type pointed by the iterators given as argument to that function,
and calculate the appropriate distance.
Quote:
Quote:
>And I'm really fine with that function signature, because actually the
>FactorGraphSolver needs just a Tree of Descriptors, nothing more,
>nothing less.
>>
>Ok?
>
Seems OK. A separate tree of descriptors, describing the nodes of a
TreeNode tree, which itself is a minimum spanning tree for the Item
nodes in some graph.
Well, it seems mostly ok. In the following I'll explain you with more
detail.
Quote:
>
Quote:
>Let's say that now I want to add a particular additional information
>to that tree node, for example a reference to the real descriptor that
>generated it, and a label. Then I'll pass to the classification class,
>and this class will call the same usual subclasses to perform the
>calculations and, once done, will label every node properly. At the end
>of the function, I could explore the tree and, being composed of
>descriptor that have a reference of the elements that have generated
>them, I can label the original elements.
>
Huh? "real descriptor that generated it", what's that? You lost me.
The initial iterators.. let me show you a more concrete example.
I have an Image (I'm starting from quite far, to let you understand
eveything). From the image I can extract some set of descriptors, that
can be of different types. For example, let's say, ColourDescriptor and
EdgeDescriptor, ok? I want to obtain a tree in which the nodes are
generic Descriptors, made by an ID and a vector of doubles generated by
each different descriptor type (i.e., ColourDescriptor and EdgeDescriptor).
So, each Descriptor implements a method to generate this vector of
double. Now, the tree I want has to connect all the Descriptors.
Considering the set of all the particular type descriptor (for example,
the set of ColourDescriptor) as a fully connected graph, I want the
minimum spanning tree of this graph, in which every node doesn't need to
contain the specific type of descriptor, but just the vector of doubles
and the ID (so, each node it's the associated generic Descriptor).
Here we come: the iterators that are input for the
GenerateMinimumSpanningTree function are iterators to a set of, for
example, ColourDescriptor. The DistanceMeasure function takes two
ColourDescriptor. The generated tree contain general Descriptor
generated by the ColourDescriptor.
Everything now works well. But let's say that at a certain point I my
want to come back from a general Descriptor to the particular
ColourDescriptor that has generated it. It would be good to derive a
DescriptorWithReference, that behaves exaclty as a normal descriptor,
but has got a refernece to the originator, as well. I'd like to apply
all the code I've written without any major change, because it's good
like this.
Quote:
>
Quote:
>Ok, the problem is this one. It seems to me that I've said enough to
>understand it. I won't post the real code because it's long and mostly
>unrelated to the problem.
>
As I understand it, just generate a parallel tree of descriptors.
So, you are suggesting me to generate a tree of the original particular
descriptors (let's say, ColourDescriptor). Then, generate a tree with
the same structure but of general Descriptor. While generating the
second tree, I build a map to memorize all the correspondences. Then I
use the original tree (that fortunately won't be modified in the
structure). And, at the end, I recover the information from the map and
the two tree combined?
Do you know what? probably it's not the cleanest solution ever, but
considering that the memory for the duplication of the tree and the map
shouldn't be a problem, it can be the clearest way to proceed, also
because the code structure stays quite plain and the old code will keep
working.
Quote:
I don't see how this ties in to having the factory function generate
nodes of some derived class.
>
I hope it's clear now that I given you more details! :)
Thank you!
Zeppe