I have the following classes I used to define a tree structure with a number of specific nodes
class TreeNode
{
std::vector<TreeNode*> children;
}
class BTNode: public virtual TreeNode
{
virtual bool loadAttributes(XML) = 0;
virtual BTState tick() = 0;
void otherFunction1() { used by all the different nodes}
void otherFunction2() { also used by all the node types }
}
There are a couple of specific implementations of the BTNode class that can be saved and loaded from XML files:
class BTSpecificNodeOne: public BTNode
{
bool loadAttributes(XML) { load node specific data from XML }
BTState tick() { specific implementation goes here }
}
class BTSpecificNodeTwo: public BTNode
{
bool loadAttributes(XML) { load node specific data from XML }
BTState tick() { specific implementation goes here }
}
etc.
I also have a genetic algorithm that optimises this tree structure based on a common tree node genome type:
class TreeNodeGenome: public virtual TreeNode
{
bool load(XML);
TreeNodeGenome* crossover(TreeNodeGenome* other);
virtual void mutate() = 0;
}
Furthermore, to have the node specific implementation used within the genome
class BTSpecificNodeGenomeOne: public BTSpecificNode, public TreeNodeGenome
{
void mutate() { node specific implementation }
}
class BTSpecificNodeGenomeTwo: public BTSpecificNode, public TreeNodeGenome
{
void mutate() { node specific implementation }
}
etc.
I'd like to be able to save and load the results of the optimisation to/from an XML file.
The implementations of BTSpecificNodeOne, BTSpecificNodeTwo, etc. already have a save/load function that I use for saving the results, but loading them is a bit more tricky.
The load function of the BTNode class rebuilds the tree (from XML) based on the BTNode class (nodes may create children that are also loaded recursively). In order to use it again in the genetic algorithm, I need the nodes to derive from the TreeNodeGenome class as well.
I can rebuild a TreeNodeGenome structure based only on the information contained in TreeNode, but I'm not sure how to "merge" these two trees together.
I know that I could pretty much copy the load functions into the BTSpecificNodeGenomeOne, BTSpecificNodeGenomeTwo, etc. classes but I was wondering if there is a simpler/cleaner way to do it?
EDIT: Apparently what I'd like to do is a bit unclear from my previous post.
I have implemented a Behaviour Tree(BT) class, which uses a number of different nodes deriving from BTNode: Selector, Sequence, different condition and action nodes. The BT itself is saved in an XML format and can be loaded via BTNode::loadAttributes().
In addition to this, I have a genetic algorithm that can optimise tree structures. TreeNodeGenome implements the genetic operators of the different nodes to be used during evolution.
During evolution I use BTSpecificNodeGenomeOne, BTSpecificNodeGenomeTwo nodes that implement both the different BT nodes and the genetic operators from TreeNodeGenome. TreeNodeGenome requires only the structure of the tree already encoded in the TreeNode base class and the node specific implementations of the mutation operator. As the BT and an evolvable tree structure are two conceptually different things, I'd like to keep them separate.
My question is: I have the BTNode::loadAttributes() function implemented for all BTNodes already, which load the BT from an XML file. This function creates its children as BTNodes, which are not evolvable. If I want to use the loaded tree in evolution, I need to somehow "merge" it with a TreeNodeGenome object.
I can do this by reimplementing the loadAttributes function in each derived BTSpecificNodeGenome, but I was wondering if there was a cleaner/simpler way to do this?
Related
I want to build a n-arry tree from a document. For that i have 3 different types of elements for the tree:
Struct Nodes
Have a name
can contain other Nodes
Depth
Element Node (Leaf of the tree)
Have a Key
Have a value
Depth
Element Template Node (Leaf of the tree)
Have a placeholder which should be resolved later in the program
Depth
At the moment i think about something like this:
class Node {
public:
Node(int depth);
int depth() const;
private:
int depth_;
};
class StructNode : public Node {
...
private:
std::vector<std::unique_ptr<Node>> children;
};
class ElementNode : public Node {
...
};
class ElementTemplateNode : public Node {
...
};
The Tree will be generated from an File on Startup and reused to create an output string like this:
Structname:
key = value
key = value
Structname:
key = value
Structname:
key = value
...
Where the Key and value where directly read from the ElementNode or read from another file with the value of the placeholder inside the ElementTemplateNode
Is there maybe a better Structure for the Tree? Because with the current one i have to check first if its a StructNode, ElementNode or ElementTemplateNode
This is a typical structure for implementing a tree with different kind of nodes. Another variant would be the composite pattern.
The problem that you describe, is usually caused by asking the nodes about what they know, instead of telling them what to do. If you'd do it the other way round (tell, don't ask), you could get rid of those checks and benefit from polymorphism.
The different kind of nodes inherit from Node. You could design your tree using a uniform interface, with virtual functions defined for Node which then can be overridden for the different types of nodes. Calling the method would then do the right things, without need for a manual type check. For generating the output string, you'd tell the root node to generate a string. If it's a structure, it would add the heading and tell its children to generate a string, but if it's a leaf it would just add the key/value pair to the string. No need from outside to know anything about each node.
If the operation of exploring the tree shall not be implemented by the tree itself, the usual approach is to use a visitor pattern. The big advantage is that you write the vistor once, and it's then easy to specialize a new kind of visitor for different algorithms. Again, no need to check the type of the nodes. The pattern makes sure that the right elementary function is called for the right type of node.
I want to create a Binary search tree which has special Nodes. There should be three classes of Nodes, Internal Node, External Node and Root node, each inheriting a common parent Node and each type of node will have some unique function. Is it possible to create such a BST. The problem I am facing is suppose the first node I insert into the tree becomes the root node. The next node I insert will become External Node. Now if I insert another node then the external node has to become a internal node and the new node will become the external node. Also I cannot find a way to navigate through the tree from one node to another as the nodes will be of different types. Can a tree of this type be created. If yes then give me some suggestions of how this can be done.
If I understand correctly, you're worried about how objects in one class - External - need to become objects of another class - Internal. This, when C++ is a statically-typed language: Types (including the classes of objects) are determined at compile-time. Right?
Well, you can achieve this in at least one of two ways:
When an External node becomes Internal, delete the External node and replace it with an Internal node, properly initialized (e.g. to point at the new External node).
Give up on External and Internal being discrete types, and just check for children and parents to determine the node type dynamically.
Some more relevant reading material on these matters:
(Programming language) type systems in this Wikipedia page.
This SO question: What is duck typing?
The Circle-vs-Eclipse problem, and specifically the desire to stretch circles into ellipses.
You could use basic inheritance some type enum and recursive calls.
This could be a starting point:
enum NodeType
{
eRoot,
eInternal,
eExternal
};
class BinaryNode
{
public:
virtual NodeType GetType() = 0;
virtual void UpdateTree() = 0;
protected:
BinaryNode* ChildLeft;
BinaryNode* ChildRight;
BinaryNode* Parent;
};
class ExternalNode : public BinaryNode
{
NodeType GetType() override { return eExternal; }
void UpdateTree() override
{
//... Replace node instances here(e.g. delete this node and construct the correct new one given this sub tree. call new InternalNode(this) for example)
// Call this towards the parent node so the tree will be transformed accordingly
}
}
class InternalNode : public BinaryNode
{
NodeType GetType() override { return eInternal; }
void UpdateTree() override { //... }
}
class RootNode : public BinaryNode
{
NodeType GetType() override { return eRoot; }
void UpdateTree() override { //... }
}
This is just to give you an idea where to start. You can check the node type at runtime via GetType() and do some checks based on that.
Be aware that this kind of transformation is not particularly fast.
If you want this to be fast, don't use different types and virtual function calls and pointers.
Place your binary tree inside an array and use binary indexing, so at a given index "n" use 2*n+1 to get the left child and 2*n+2 to get the right child. Then use some flags (root, external, internal etc.) to determine which functions you want to call on the binary node. I wouldn't use inheritance like in my code example to be fast or more readable. In fact, deciding externally what functions to call on a node can be much more readable and less error-prone.
I'm creating a simple game for programming practice on bigger projects and am currently stuck at a crossroad.
The game uses a treegraph structure to store all the entities of the game, all extending from the base class called TreeNode that implements some basic functions such as attaching and detaching children from themselves as well as their position in the 2D world.
My problem is that I want to create a sort of "Action Node" that upon collision with the player allows various events to take place, such as changing the song being played, trigger a pause with subsequent dialogue, ending the stage etc etc.
My question is, how would i implement this in a decent way that doesn't beat my efforts of code isolation to a bloody pulp? I was thinking of making a new class with a std::function member that i can program to do what i want it to do, but that way would mean completely breaking code encapsulation by handing it a reference to my master class that contains ALL data in the entire game.
Collision is currently implemented something like this:
std::vector<std::pair<&TreeNode, &TreeNode>> vCollision;
MasterNode.checkCollision(vCollision);
checkCollision gets called with a reference to the vector, invokes collision checks recursively on the rest of the graph and fills the vector with pairs of different entities that have collided. (this is in the update loop.)
I also need to figure out a way to be able to call said std::function from this list since pointers to the base class wont have access to members of derived classes.
A tree structure is a container that can be used with different data types. Because of this, it is a good candidate for templates.
Since you have your tree working, factor out the data type to a template parameter.
For example, given a node:
struct Tree_Node
{
struct Tree_Node * left_subtree;
struct Tree_Node * right_subtree;
Some_Data_Type node_data;
};
You can factor out the data type using templates:
template <class Node_Data_Type>
struct Tree_Node
{
struct Tree_Node * left_subtree;
struct Tree_Node * right_subtree;
Node_Data_Type node_data;
};
You would declare a tree node as:
struct Player_Data;
Struct Moves_Data;
struct Tree_Node<Player_Data>; // For a tree of Player_Data
struct Tree_Node<Moves_Data>; // For a tree of Moves_Data
An alternative is to use inheritance for the node data.
struct Node_Data_Base
{
virtual bool is_equal(Node_Data_Base * p_node) const = 0;
virtual bool is_less(Node_Data_Base * p_node) const = 0;
bool operator==(Node_Data_Base * p_node) const
{
return is_equal(p_node); // Dispatch to child.
}
bool operator<(Node_Data_Base * p_node) const
{
return is_less(p_node); // dispatch to child.
}
};
struct Tree_Node_Inheritance
{
struct Tree_Node * left_subtree;
struct Tree_Node * right_subtree;
Node_Data_Base * p_data;
};
Also, review the std::map data type.
As we all know, C++ allows multiple inheritance.
Context
I'm implementing a processing network where some processing nodes are link between each other to exchange different data with a sort of modified Observer pattern.
A node which can send a certain type of data is a "DataSender" and then extends this abstract class.
A node which can receive a certain type of data is a "DataReceiver" and then extends this abstract class.
Here is my piece of code :
DataReceiver.h
template <typename TReceivedData>
class DataReceiver {
public:
void receiveData(TReceivedData* receivedData)
{
m_receivedData = receivedData;
}
TReceivedData* getReceivedData()
{
return(m_receivedData);
}
private:
TReceivedData* m_receivedData;
DataSender.h
template <typename TSentData>
class DataSender {
public:
void sendData(TSentData* sentData)
{
set<DataReceiver<TSentData>*>::const_iterator it;
for(it = m_receiverList.begin(); it != m_receiverList.end(); ++it)
(*it)->receiveData(sentData);
}
void addDataReceiver(DataReceiver<TSentData>* dataReceiver)
{
m_receiverList.insert(dataReceiver);
}
void removeDataReceiver(DataReceiver<TSentData>* dataReceiver)
{
m_receiverList.erase(dataReceiver);
}
private:
set<DataReceiver<TSentData>*> m_receiverList;
};
Then a new node is simply implemented by extending one or both of these abstract classes.
Question
I want a node which sends a data of type "Image" and "Text" : then I have a node :
with:
class Node : public DataSender<Image>, DataSender<Text>
Well, i guess you've already seen my problem, the compilation won't allow this as there's an ambiguity if I launch :
Node* node;
node->sendData(<my argument>);
because it has no way to distinguish which sendData() from the parents classes (from inheritance) should be used (that's a common problem of multiple inheritance).
1) Is there a way to use sendData() with something to solve the ambiguity (i am not sure there is one ?
2) Is there another way to solve my problem of communication ? (I absolutely want to have the opportunity that the final user which wants to create a node which sends/receives data can do it easily simply by extending something like an interface, and datas should be on different "channels": a node for instance could be able to process text and image, but will only send image...
Thanks for your help,
Julien,
It's not pretty, but you can tell which base class' function you intend to call
node->DataSender<Text>::sendData(<my argument>);
I don't think you have an ambiguity problem, because the two sendData member functions take different arguments. The problem is more likely caused by the fact that when determining which function to call C++ checks base classes in a specific order, but stops in the first one that has a member function of the correct name. Then, if it has found one that can take the argument you supplied it calls it, otherwise it issues the error you probably saw.
What you can do to overcome this problem is to add the following lines to your Node class definition:
using DataSender<Image>::sendData;
using DataSender<Text>::sendData;
My question is: (is the above|what is) the right way to create a non intrusive front-end?
I am explaining my problem with a simplified example.
I have a back-end implementing a binary tree:
// Back-end
struct Node
{
Label label;
Node* r, l;
};
I would like now to implement the front-end to print the tree graphically. So my idea is to extend the back-end with graphical properties by wrapping it :
// Front-end
struct Drawable
{
uint x, y;
};
class Visitor;
template <class T> struct GNode : public Drawable
{
T* wrapped;
template <class V> void accept(V& v); // v.visit(*this);
}
There is a problem now to create a visitor printing the binary tree:
struct Visitor
{
void visit(GNode<Node>& n)
{
// print the label and a circle around it: ok.
if (n.wrapped.l) // l is a Node, not a GNode, I can't use the visitor on it
// Problem: how to call this visitor on the node's left child?
// the same with n.wrapped.r
};
};
As explained in comments, the back-end does not use my extended class.
Writing GNode "is-a" Node is not a solution neither since I would have to put the accept() method in the Node class as virtual and override it in GNode but I can't modify the back-end. Then, someone could say too that there is no need to declare accept() in the back-end, downcasting Node* to GNode* would work. Yes it works, but it downcasts...
In my case, I have ~10 kinds of nodes (it is a graph), so I am looking for something elegant, flexible, with as few lines of code as possible (hence the wrapper template idea) :)
Thank you very much.
To absolutely disassociate code is impossible. They have to talk. If you really want to enforce decoupling to the maximal extent, some sort of IPC/RPC mechanism should be used and have two different programs.
That said -- I don't like visitor patterns.
You have a Graphical object, which is linked against a Behaving object. Maybe there are rules between behavior and the graphics, e.g., boundaries can't overlap.
You can do your entity relationship whatevers between the Graphicals and the Behaves, that's a biz logic question...
You will need some thungus that holds your drawing context (img, screen, buffer).
class DrawingThungus {
void queue_for_render(Graphical*);
void render();
};
Your Graphical will have either an inheritance or a composition relationship with behaves.
At any rate, they will have the interface needed to do Drawing.
//abstract base class class Graphical {
get_x();
get_y();
get_icon();
get_whatever();
};
If you are finding that your Render is becoming case-based depending on the kind of Graphical, I suggest pushing the cases over to the Graphical, and refactoring to have a get_primitives_list(), wherein the needed primitives are returned for Graphical to return (I am presuming that at some level, you have core primitives, lines, circles, arcs, labels, etc).
I have always found that OO analysis lends itself to wasting mental energy and should be done only enough for the task at hand. YAGNI is a tremendous principle.
If your wrapper class (GNode) didn't have to maintain any state across visits (i.e., it only had one field - the wrapped Node object), you could use a pointer or a reference to the wrapped object instead of a copy, and then you would be able to wrap any node at runtime.
But even if you do maintain state (the x,y coordinates), don't you really just infer it from the wrapped object? In that case, wouldn't it be better to separate your visited class from the inferred data? For instance, consider this implementation:
// This is an adapter pattern, so you might want to call it VisitorAdapter if you
// like naming classes after patterns.
template typename<T>
class VisitorAcceptor
{
private:
T& wrapped;
public:
VisitorAcceptor(T& obj)
{
wrapped = obj;
}
template <typename VisitorT>
void accept(VisitorT& v)
{
v.visit(wrapped);
}
};
struct GNode
{
uint x, y;
shared_ptr<GNode> l,r; // use your favourite smart pointer here
template <typename VisitorT>
void accept(VisitorT& v)
}
// You don't have to call a visitor implementation 'Visitor'. It's better to name
// it according to its function, which is, I guess, calculating X,Y coordinates.
{
shared_ptr<GNode> visit(Node& n)
{
shared_ptr<GNode> gnode = new GNode;
// calculate x,y
gnode->x = ...
gnode->y = ...
if (n.l)
gnode->l = VisitorAdapter(n.r).accept(*this);
if (n.r)
gnode->r = VisitorAdapter(n.l).accept(*this);
};
};
Now you can have a different visitor for drawing:
struct GNodeDrawer
{
void visit(GNode& gnode)
{
// print the label and a circle around it: ok.
if (n.r)
visit(n.l);
if (n.r)
visit(n.r);
};
};
Of course, if you don't need all the extensibility the visitor pattern offers, you can throw it away altogether and just walk the the tree recursively with XYCalculator.visit calling itself.
Personally, I would make a drawing class with overloaded functions (one for each node type) rather than trying to hook into the existing structure with some sort of complicated inheritance solution.
I finally found an "elegant" solution with the decorator design pattern.
This pattern is used to extend an object without changing its interface.
GNode decorates/extends Node:
template <class T> struct GNode : public T, public Drawable
{
virtual void accept(Visitor& v); // override Node::accept()
}
As you can see, it requires a little change in the back-end structure:
struct Node
{
Label label;
Node* r, l;
virtual void accept(Visitor& v);
};
That's it ! GNode is-a Node. We can now create a binary tree of GNodes and visit it thanks to the virtual method accept() in the back-end structure.
In the case when we absolutely follow my question, i.e. we can't modify the back-end and it doesn't have the virtual entry point presented above, we can add features to GNode mapping the Node it wraps to itself. So that a visitor visiting GNodes (that can only have access to its sons) can find the GNodes of its sons. Yes, this is the virtual keyword job with the above solution! But we never know if someone would be in this case for real.
As a conclusion to all this: the way you express a problem always influences the way to resolve it.