package statalign.postprocess.plugins.contree;
import java.util.ArrayList;
/**
* Paths of incompatible splits in the consensus network
*
* @author wood
*
*/
public class CNetworkPath {
public ArrayList<CNetworkEdge> pathOfEdges;
public ArrayList<CNetworkNode> pathOfNodes;
public CNetworkPath(){
pathOfEdges = new ArrayList<CNetworkEdge>();
pathOfNodes = new ArrayList<CNetworkNode>();
}
/**
* Returns the node at the start of the path
*/
public CNetworkNode startNode(){
return pathOfNodes.get(0);
}
/**
* Returns the node at the end of the path
*/
public CNetworkNode endNode(){
return pathOfNodes.get(pathOfNodes.size()-1);
}
/**
* Returns true if this path already contains an edge from the argument split, otherwise false.
*
* @param edgeToLookFor Edge from split we want to see is already present in path or not
*/
public boolean checkForSplit(CNetworkEdge edgeToLookFor){
for(CNetworkEdge currentEdge : pathOfEdges){
if(currentEdge.split == edgeToLookFor.split){
return true;
}
}
return false;
}
/**
* Combines this path with the argument path across the argument node
*
* @param toAdd Path to add to this one
* @param nodeToLinkOver Node over which to link (ensures non-duplication of this node)
*/
public CNetworkPath combineWith(CNetworkPath toAdd , CNetworkNode nodeToLinkOver){
// Path to Return (does what it says...)
CNetworkPath pathToReturn = new CNetworkPath();
//we'll always add to this one
if(pathOfNodes.get(0)== nodeToLinkOver){
CNetworkPath firstPath = reordered();
pathToReturn.pathOfEdges.addAll(firstPath.pathOfEdges);
pathToReturn.pathOfNodes.addAll(firstPath.pathOfNodes);
}
else{
pathToReturn.pathOfEdges.addAll(pathOfEdges);
pathToReturn.pathOfNodes.addAll(pathOfNodes);
}
// now we have the path with the node to link over at the end.
// and now add the second one given as an argument
// note we are careful not to modify the already existing paths as we want more paths.
if(toAdd.pathOfNodes.get(0) == nodeToLinkOver){
for(int j=1;j<toAdd.pathOfNodes.size();j++){
pathToReturn.pathOfNodes.add(toAdd.pathOfNodes.get(j));
}
pathToReturn.pathOfEdges.addAll(toAdd.pathOfEdges);
}
else{
CNetworkPath secondPath = toAdd.reordered();
secondPath.pathOfNodes.remove(0);
pathToReturn.pathOfEdges.addAll(secondPath.pathOfEdges);
pathToReturn.pathOfNodes.addAll(secondPath.pathOfNodes);
}
// add to all the nodes in the path this path!
for(CNetworkNode nodeToAddPathTo : pathOfNodes){
nodeToAddPathTo.paths.add(pathToReturn);
}
return pathToReturn;
}
/**
* Reorders this path
*/
public CNetworkPath reordered(){
CNetworkPath reorderedPath = new CNetworkPath();
for(int i=pathOfEdges.size() - 1;i>=0;i--){
reorderedPath.pathOfEdges.add(pathOfEdges.get(i));
}
for(int i=pathOfNodes.size() - 1;i>=0;i--){
reorderedPath.pathOfNodes.add(pathOfNodes.get(i));
}
return reorderedPath;
}
/**
* This function sees if adjoining splits at the nodes at the path ends create subsets on both sides of the input split...
* Is to see is path actually links two nodes from where the split occurs.
* Returns true if is a desired split path otherwise false.
*
* @param inputSplit Split that is being added and must create splits in some of the edges joining the end nodes
* @param noOfTaxa Standard request for number of taxa in the network
*/
//
public boolean isSplitSide(CNetworkSplit inputSplit, int noOfTaxa){
// booleans to store if we have edges with splits as subsets of zeroside and one side of the input split
boolean zeroSideSplit = false;
boolean oneSideSplit = false;
// look at both ends of the path (code hack...)
CNetworkNode[] nodesToCheck = new CNetworkNode[]{pathOfNodes.get(0),pathOfNodes.get(pathOfNodes.size()-1)};
for(int l=0;l<=1;l++){
// look at all joins...
for(CNetworkEdge currentEdge : nodesToCheck[l].joins){
// ignore incompatible splits in the path...
if(checkForSplit(currentEdge) == false){
// and now decide which side it is on
if(inputSplit.isSubset(currentEdge.split, true, noOfTaxa)){
zeroSideSplit = true;
}
else if(inputSplit.isSubset(currentEdge.split, false, noOfTaxa)){
oneSideSplit = true;
}
}
}
}
// Return true if is split path
if(zeroSideSplit==true && oneSideSplit==true){
return true;
}
// otherwise false!
else{
return false;
}
}
}