}
}
}
}
ClusterHead newTree = new ClusterHead();
Map<Integer,ClusterNode> treenodes = new HashMap<Integer,ClusterNode>();
treenodes.put(0,newTree);
//allocate each node to its parent:
for(int i = 0; i<originalTree.getNodes().size(); i++){
int parent = assignments.get(i);
ClusterNode parentNode = treenodes.get(parent);
if(parentNode == null){
parentNode = new ClusterNode();
treenodes.put(parent, parentNode);
}
parentNode.addNode(nodenumbers.get(i+1));
}
//state is now that there are loads of clusters with the children they need.
//build the tree:
int treeSize = originalTree.getNodes().size();
for(int i = 0; i<assignments.size() - treeSize; i++){
int parent = assignments.get(i + treeSize); //pull parent id for child i from the array.
if(parent == i+1){
//Logger.getLogger(TreeTranslator.class.getName()).log(Level.INFO, "Attempted to make a child a parent of itself {0} from {1}",new Object[]{parent,i});
parent = 0;
}
ClusterNode parentNode = treenodes.get(parent); //parent is whatever that value was
if(parentNode == null){
//add intermediate parent that didn't have any nodes in it:
parentNode = new ClusterNode();
treenodes.put(parent,parentNode);
}
ClusterNode childNode = treenodes.get(i + 1); //i starts 0..n-1, they're numbered 1..n (0 is always reserved for the child).
if(childNode == null){
childNode = new ClusterNode();
treenodes.put(i+1, childNode);
}
parentNode.addChild(childNode);
if(ClusterUtils.isCyclic(parentNode)){
parentNode.deleteChild(childNode);
//Logger.getLogger(TreeTranslator.class.getName()).log(Level.INFO, "{0} was cyclic so the child {1} was removed", new Object[]{parentNode, childNode});
}
}
Set<ClusterNode> orphans = new HashSet<ClusterNode>();
for(ClusterNode n : treenodes.values()){
if(n != newTree && ClusterUtils.findParent(n, newTree) == null){
orphans.add(n);
}
}
for (Iterator<ClusterNode> it = orphans.iterator(); it.hasNext();) {
ClusterNode clusterNode = it.next();
boolean remove = false;
for(ClusterNode cn : orphans){
if(cn != clusterNode && ClusterUtils.findParent(clusterNode, cn) != null){
//if the current clusterNode can be found in any of the "trees" of the orphans
//then it isn't an orphan proper, just an orphan of the main ClusterHead - we can
//fix this problem by adopting its parent, so we remove it from our fixups.
remove = true;
break;
}
}
if(remove) it.remove();
}
//orphans should now contain all clusters that need to be adopted:
for(ClusterNode cn : orphans){
if(ClusterUtils.isCyclic(cn)){
throw new RuntimeException("A cyclic orphan was detected.");
}
newTree.addChild(cn);
}
if(ClusterUtils.isCyclic(newTree)){
Logger.getLogger(TreeTranslator.class.getName()).log(Level.WARNING, "Cyclic tree detected!");
throw new RuntimeException("There was a cyclic tree so I stopped.");
}
//ClusterUtils.prettyPrintTree(newTree);
Set<Node> oNodes = originalTree.getNodes();
Set<Node> tNodes = newTree.getNodes();
if(!oNodes.containsAll(tNodes) || !tNodes.containsAll(oNodes)){
Logger.getLogger(TreeTranslator.class.getName()).log(Level.INFO, "Converting a HCLUST: not all nodes were copied, Have {0} nodes but needed {1}.", new Object[]{tNodes.size(), oNodes.size()});
oNodes.removeAll(tNodes);