/* * This file is part of the program ltl2dstar (http://www.ltl2dstar.de/). * Copyright (C) 2005-2007 Joachim Klein * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SAFRATREE_H #define SAFRATREE_H /** @file * Provides class SafraTree. */ #include "common/BitSet.hpp" #include "SafraTreeNode.hpp" #include "RabinAcceptance.hpp" #include #include #include #include #include #include // forward declaration template class SafraTreeWalker; /** * A Safra tree, an ordered tree of SafraTreeNodes. */ class SafraTree { public: /** * Constructor. * @param N the maximum number of nodes. */ SafraTree(unsigned int N) { if (N==0) {N=1;} MAX_NODES=N; _nodes=new SafraTreeNode*[MAX_NODES]; for (unsigned int i=0;igetLabeling()=other._nodes[i]->getLabeling(); _nodes[i]->setFinalFlag(other._nodes[i]->hasFinalFlag()); } } copySubTree(_nodes[0], other._nodes[0]); } /** Destructor. */ ~SafraTree() { for (unsigned int i=0;iid. */ SafraTreeNode* newNode(unsigned int id) { assert(idgetID()]==node); remove(node->getID()); } /** * Remove the SafraTreeNode id from the tree, * the node can have no children. */ void remove(unsigned int id) { assert(idremoveFromTree(); delete _nodes[id]; _nodes[id]=0; } /** * Remove all children of the SafraTreeNode id. */ void removeAllChildren(unsigned int id) { assert(idgetOldestChild())!=0) { removeAllChildren(child->getID()); remove(child->getID()); } } /** * Walk the tree post-order, calling the function * void visit(SafraTree& tree, SafraTreeNode *node) * in the SafraTreeVisitor on each node. */ template void walkTreePostOrder(SafraTreeVisitor& visitor) { std::auto_ptr > stw(new SafraTreeWalker(visitor)); stw->walkTreePostOrder(*this); } /** * Walk the subtree rooted under node *top post-order, * calling the function void visit(SafraTree& tree, SafraTreeNode *node) * in the SafraTreeVisitor on each node. */ template void walkSubTreePostOrder(SafraTreeVisitor& visitor, SafraTreeNode *top) { std::auto_ptr > stw(new SafraTreeWalker(visitor)); stw->walkSubTreePostOrder(*this, top); } /** * Walk the subtree rooted under node *top (only the children, not *top itself) * post-order, calling the function void visit(SafraTree& tree, SafraTreeNode *node) * in the SafraTreeVisitor on each node. */ template void walkChildrenPostOrder(SafraTreeVisitor& visitor, SafraTreeNode *top) { std::auto_ptr > stw(new SafraTreeWalker(visitor)); stw->walkSubTreePostOrder(*this, top, false // = don't visit top ); } /** * Calculate the height of the tree. */ unsigned int treeHeight() { if (getRootNode()!=0) { return getRootNode()->treeHeight(); } return 0; } /** * Calculate the width of the tree. */ unsigned int treeWidth() { if (getRootNode()!=0) { return getRootNode()->treeWidth(); } return 0; } /** * Equality operator. */ bool operator==(const SafraTree& other) const{ if (other.MAX_NODES!=MAX_NODES) {return false;} for (unsigned int i=0;igetRootNode(); const SafraTreeNode* other_root=other.getRootNode(); if (this_root==0 || other_root==0) { // return true if both are 0 return (this_root==other_root); } return this_root->structural_equal_to(*other_root); } /** * Less-than operator when ignoring the node names. */ bool structural_less_than(const SafraTree& other) const { if (other.MAX_NODESgetRootNode(); const SafraTreeNode* other_root=other.getRootNode(); if (this_root==0) { if (other_root!=0) { return true; } else { return false; } } else { // this_root !=0 if (other_root==0) {return false;} return this_root->structural_less_than(*other_root); } } /** * Less-than operator */ bool operator<(const SafraTree& other) const{ if (MAX_NODES < other.MAX_NODES) {return true;} for (unsigned int i=0;ii*/ SafraTreeNode* operator[](unsigned int i) { return _nodes[i]; } const SafraTreeNode* operator[](unsigned int i) const { return _nodes[i]; } /** Print the SafraTree on an output stream. */ friend std::ostream& operator<<(std::ostream& out, SafraTree& st) { if (st.getRootNode()==0) { out << "" << std::endl; } else { st.printSubTree(out, 0, st.getRootNode()); } return out; } /** Returns a string representation of the SafraTree */ std::string toString() { std::ostringstream buf; buf << *this; return buf.str(); } /** Returns a string representation in HTML of the SafraTree */ std::string toHTML() { if (getRootNode()==0) { return std::string("
[empty]
"); } else { std::ostringstream buf; getRootNode()->toHTML(buf); return buf.str(); } } /** * Calculate a hash value using HashFunction * @param hashfunction the HashFunction * @param only_structure ignore the nameing of the nodes */ template void hashCode(HashFunction& hashfunction, bool only_structure=false) { SafraTreeNode* root=getRootNode(); if (root!=0) { root->hashCode(hashfunction, only_structure); } } /** * Generate the appropriate acceptance signature for Rabin Acceptance for this tree */ void generateAcceptance(RabinAcceptance::AcceptanceForState acceptance) const { for (unsigned int i=0;ihasFinalFlag()) { acceptance.addTo_L(i); } } } } void generateAcceptance(RabinAcceptance::RabinSignature& acceptance) const { acceptance.setSize(getNodeMax()); for (unsigned int i=0;ihasFinalFlag()) { acceptance.setColor(i, RabinAcceptance::RABIN_GREEN); } else { acceptance.setColor(i, RabinAcceptance::RABIN_WHITE); } } } } RabinAcceptance::RabinSignature generateAcceptance() const { RabinAcceptance::RabinSignature s(getNodeMax()); generateAcceptance(s); return s; } private: /** The maximum number of nodex */ unsigned int MAX_NODES; /** An array to store the nodes */ SafraTreeNode **_nodes; /** * Copy the subtree (the children) of *other * to *top, becoming the children of *top */ void copySubTree(SafraTreeNode *top, SafraTreeNode *other) { if (other==0) {return;} for (SafraTreeNode::child_iterator it=other->children_begin(); it!=other->children_end(); ++it) { SafraTreeNode *n=_nodes[(*it)->getID()], *n_o=*it; top->addAsYoungestChild(n); copySubTree(n, n_o); } } /** * Print the subtree rooted at node *top to the output stream * @param out the output stream * @param prefix the number of spaces ' ' in front of each node * @param top the current tree sub root */ void printSubTree(std::ostream& out, unsigned int prefix, SafraTreeNode* top) { for (unsigned int i=0;ichildren_begin(); it!=top->children_end(); ++it) { printSubTree(out, prefix+1, *it); } } }; /** a boost::shared_ptr for SafraTree */ typedef boost::shared_ptr SafraTree_ptr; namespace std { /** overload equal_to for SafraTree_ptr to compare the actual trees */ template <> inline bool std::equal_to::operator() (SafraTree_ptr const& x, SafraTree_ptr const& y) const { return (*x)==(*y); } /** overload less for SafraTree_ptr to compare the actual trees */ template <> inline bool std::less::operator() (SafraTree_ptr const& x, SafraTree_ptr const& y) const { return (*x)<(*y); } }; // include SafraTreeWalker after declaration, because it // depends on SafraTree... #include "SafraTreeWalker.hpp" #endif