You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

382 lines
9.6 KiB

/*
* This file is part of a Java port of the program ltl2dstar
* (http://www.ltl2dstar.de/) for PRISM (http://www.prismmodelchecker.org/)
* Copyright (C) 2005-2007 Joachim Klein <j.klein@ltl2dstar.de>
* Copyright (c) 2007 Carlos Bederian
*
* 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
*/
package jltl2dstar;
import java.util.Vector;
import java.io.PrintStream;
import jltl2ba.MyBitSet;
/**
* A Safra tree, an ordered tree of SafraTreeNodes.
*/
public class SafraTree implements NBA2DAState {
/** The maximum number of nodes */
private int MAX_NODES;
/** An array to store the nodes */
private Vector<SafraTreeNode> _nodes;
/**
* Constructor.
* @param N the maximum number of nodes.
*/
public SafraTree(int N) {
MAX_NODES = (N == 0 ? 1 : N);
_nodes = new Vector<SafraTreeNode>(MAX_NODES);
_nodes.setSize(MAX_NODES);
// create root-node
newNode(0);
}
/** Copy constructor. */
public SafraTree(SafraTree other) {
MAX_NODES = other.MAX_NODES;
_nodes = new Vector<SafraTreeNode>(MAX_NODES);
_nodes.setSize(MAX_NODES);
for (int i = 0; i < MAX_NODES; i++) {
if (other._nodes.get(i) != null) {
newNode(i);
_nodes.get(i).setLabeling((MyBitSet) other._nodes.get(i).getLabeling().clone());
_nodes.get(i).setFinalFlag(other._nodes.get(i).hasFinalFlag());
}
}
copySubTree(_nodes.get(0), other._nodes.get(0));
}
/** Get the root node of the tree. */
public SafraTreeNode getRootNode() {return _nodes.get(0);}
/** Create a new node. The name is the next free node name. */
public SafraTreeNode newNode() {
if (_nodes.indexOf(null) != -1)
return newNode(_nodes.indexOf(null)); // FIXME: hmm, inconsistent with newNode(int)
else return null;
}
/** Create a new node with name <i>id</i>. */
public SafraTreeNode newNode(int id) {
assert(id < MAX_NODES);
assert(_nodes.get(id) == null);
_nodes.set(id,new SafraTreeNode(id));
return _nodes.get(id);
}
/**
* Remove a SafraTreeNode from the tree,
* the node can have no children.
*/
public void remove(SafraTreeNode node) {
assert(_nodes.get(node.getID()) == node);
remove(node.getID());
}
/**
* Remove the SafraTreeNode <i>id</i> from the tree,
* the node can have no children.
*/
public void remove(int id) {
assert(id >= 0 && id < MAX_NODES);
_nodes.get(id).removeFromTree();
_nodes.set(id, null);
}
/**
* Remove all children of the SafraTreeNode <i>id</i>.
*/
public void removeAllChildren(int id) {
assert(id < MAX_NODES);
SafraTreeNode n = _nodes.get(id);
SafraTreeNode child;
while ((child = n.getOldestChild()) != null) {
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.
*/
public <V extends SafrasAlgorithm.SafraTreeVisitor> void walkTreePostOrder(V visitor) {
SafraTreeWalker<V> stw = new SafraTreeWalker<V>(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.
*/
public <V extends SafrasAlgorithm.SafraTreeVisitor> void walkSubTreePostOrder(V visitor, SafraTreeNode top) {
SafraTreeWalker<V> stw = new SafraTreeWalker<V>(visitor);
stw.walkSubTreePostOrder(this, top, true);
}
/**
* 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.
*/
public <V extends SafrasAlgorithm.SafraTreeVisitor> void walkChildrenPostOrder(V visitor, SafraTreeNode top) {
SafraTreeWalker<V> stw = new SafraTreeWalker<V>(visitor);
stw.walkSubTreePostOrder(this, top, false); // = don't visit top
}
/**
* Calculate the height of the tree.
*/
public int treeHeight() {
if (getRootNode() != null) {
return getRootNode().treeHeight();
}
return 0;
}
/**
* Calculate the width of the tree.
*/
public int treeWidth() {
if (getRootNode() != null) {
return getRootNode().treeWidth();
}
return 0;
}
/**
* Equality operator.
*/
public boolean equals(SafraTree other) {
if (other.MAX_NODES != MAX_NODES) {return false;}
return _nodes.equals(other._nodes);
}
public boolean equals(Object other) {
if (other instanceof SafraTree)
return this.equals((SafraTree) other);
else return false;
}
/**
* Checks equality when ignoring the node names.
*/
public boolean structural_equal_to(SafraTree other) {
if (other.MAX_NODES!=MAX_NODES) {return false;}
SafraTreeNode this_root = this.getRootNode();
SafraTreeNode other_root = other.getRootNode();
if (this_root == null || other_root == null) {
// return true if both are 0
return (this_root==other_root);
}
return this_root.structuralEquals(other_root);
}
/**
* Less-than operator when ignoring the node names.
*/
public boolean structural_less_than(SafraTree other) {
if (other.MAX_NODES<MAX_NODES) {return true;}
SafraTreeNode this_root = this.getRootNode();
SafraTreeNode other_root = other.getRootNode();
if (this_root == null) {
if (other_root!= null) {
return true;
} else {
return false;
}
} else { // this_root !=0
if (other_root == null) {return false;}
return this_root.structuralLessThan(other_root);
}
}
/**
* Less-than operator
*/
public boolean lessThan(SafraTree other) {
if (MAX_NODES < other.MAX_NODES) {return true;}
for (int i = 0; i < MAX_NODES; i++) {
if (_nodes.get(i) == null && other._nodes.get(i) == null) {
;
} else if (_nodes.get(i) == null) {
return true;
} else if (other._nodes.get(i) == null) {
return false;
} else {
if (_nodes.get(i).lessThan(other._nodes.get(i))) {
return true;
} else if (_nodes.get(i).equals(other._nodes.get(i))) {
;
} else {
return false;
}
}
}
return false;
}
/** Get the maximum number of nodes. */
public int getNodeMax() {return MAX_NODES;}
/** Get SafraTreeNode with index <i>i</i>*/
public SafraTreeNode get(int i) {
return _nodes.get(i);
}
public void set(int i, SafraTreeNode node) {
_nodes.set(i, node);
}
/** Print the SafraTree on an output stream. */
public void print(PrintStream out) {
if (getRootNode() == null) {
out.println("<empty>");
} else {
printSubTree(out, 0, getRootNode());
}
}
/** Returns a string representation of the SafraTree */
// public String toString() {
// std::ostringstream buf;
// buf << *this;
// return buf.str();
// }
/** Returns a string representation in HTML of the SafraTree */
public String toHTML() {
if (getRootNode() == null) {
return "<TABLE><TR><TD>[empty]</TD></TR></TABLE>";
} else {
return getRootNode().toHTMLString();
}
}
/**
* Calculate a hash value using HashFunction
* @param hashfunction the HashFunction
* @param only_structure ignore the nameing of the nodes
*/
// template <class HashFunction>
// public void hashCode(HashFunction& hashfunction,
// bool only_structure=false) {
// SafraTreeNode* root=getRootNode();
//
// if (root!=0) {
// root->hashCode(hashfunction, only_structure);
// }
// }
public int hashCode() {
if (getRootNode() != null)
return getRootNode().hashCode();
else return 0;
}
/**
* Generate the appropriate acceptance signature for Rabin Acceptance for this tree
*/
public void generateAcceptance(AcceptanceForState acceptance) {
for (int i = 0; i < getNodeMax(); i++) {
SafraTreeNode stn = this.get(i);
if (stn == null) {
acceptance.addTo_U(i);
} else {
if (stn.hasFinalFlag()) {
acceptance.addTo_L(i);
}
}
}
}
public void generateAcceptance(RabinSignature acceptance) {
acceptance.setSize(getNodeMax());
for (int i = 0; i < getNodeMax(); i++) {
SafraTreeNode stn = this.get(i);
if (stn == null) {
acceptance.setColor(i, RabinAcceptance.RabinColor.RABIN_RED);
} else {
if (stn.hasFinalFlag()) {
acceptance.setColor(i, RabinAcceptance.RabinColor.RABIN_GREEN);
} else {
acceptance.setColor(i, RabinAcceptance.RabinColor.RABIN_WHITE);
}
}
}
}
public RabinSignature generateAcceptance() {
RabinSignature s = new RabinSignature(getNodeMax());
generateAcceptance(s);
return s;
}
/**
* Copy the subtree (the children) of *other
* to *top, becoming the children of *top
*/
private void copySubTree(SafraTreeNode top, SafraTreeNode other) {
if (other == null) {return;}
for (SafraTreeNode child : other) {
SafraTreeNode n = _nodes.get(child.getID());
top.addAsYoungestChild(n);
copySubTree(n, child);
}
}
/**
* 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
*/
private void printSubTree(PrintStream out, int prefix, SafraTreeNode top) {
for (int i = 0; i < prefix; i++) {
out.print(" ");
}
top.print(out);
out.println();
for (SafraTreeNode child : top) {
printSubTree(out, prefix+1, child);
}
}
}