// Path: src/treecmp/common/TreeCmpException.java
// public class TreeCmpException extends Exception {
// 
//   private String errMsg;
// //----------------------------------------------
// // Default constructor - initializes instance variable to unknown
//   public TreeCmpException()
//   {
//     super();             // call superclass constructor
//     errMsg = "unknown";
//   }
// 
// //-----------------------------------------------
// // Constructor receives some kind of message that is saved in an instance variable.
//   public TreeCmpException(String errMsg)
//   {
//     super(errMsg);     // call super class constructor
//     this.errMsg = errMsg;  // save message
//   }
// 
// //------------------------------------------------
// // public method, callable by exception catcher. It returns the error message.
//   public String getError()
//   {
//     return errMsg;
//   }
// }
// 
// Path: src/treecmp/metric/RFMetric.java
// public class RFMetric extends BaseMetric implements Metric{
// 
//     public static double getRFDistance(Tree t1, Tree t2) {
// 
//         int n = t1.getExternalNodeCount();
//         if (n <= 3)
//             return 0;
// 
//         IdGroup idGroup = TreeUtils.getLeafIdGroup(t1);
//         BitSet[] s_t1=SplitDist.getSplits(t1, idGroup);
//         BitSet[] s_t2=SplitDist.getSplits(t2, idGroup);
//         int N1=s_t1.length;
//         int N2=s_t2.length;
//         int hashSetSize=(4*(N1+1))/3;
// 
//         HashSet<BitSet> s_t1_hs=new HashSet<BitSet>(hashSetSize);
// 
//         int i;
//         for(i=0;i<N1;i++){
//             s_t1_hs.add(s_t1[i]);
//         }
// 
//         int common=0;
//         for(i=0;i<N2;i++){
//              if (s_t1_hs.contains(s_t2[i])){
//                 common++;
//             }
//         }
// 
//         double dist=((double)N1+(double)N2)*0.5-(double)common;
//         return dist;
// 
//     }
// 
//     
// 
//     public double getDistance(Tree t1, Tree t2, int... indexes) {
// 
//         return RFMetric.getRFDistance(t1, t2);
// 
//     }
// }


import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import pal.misc.IdGroup;
import pal.tree.Node;
import pal.tree.Tree;
import pal.tree.TreeUtils;
import treecmp.common.TreeCmpException;
import treecmp.metric.Metric;
import treecmp.metric.RFMetric;
import treecmp.test.util.TreeCreator;
import java.util.HashSet;
import java.util.Set;
        Tree expTree = TreeCreator.getTreeFromString("(0,1,(5,(2,(3,4))));");
        Tree result = SprUtils.createUsprTree(baseTree, s, t);
        Metric rf = new RFMetric();
        try {
            assertEquals(0.0, rf.getDistance(expTree, result));
        } catch (TreeCmpException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testCreateUsprTree_CreateByNonRootNonLeaf_0_toNonRootNonLeaf_2_exchange_on_6_labels_tree() {
        Tree baseTree = TreeCreator.getTreeFromString("(0,1,(2,(3,(4,5))));");
        Node s = baseTree.getInternalNode(0);
        Node t = baseTree.getInternalNode(2);
        Tree expTree = TreeCreator.getTreeFromString("(0,1,((2,3),(4,5)));");
        Tree result = SprUtils.createUsprTree(baseTree, s, t);
        Metric rf = new RFMetric();
        try {
            assertEquals(0.0, rf.getDistance(expTree, result));
        } catch (TreeCmpException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testCreateUsprTree_LookingForSomeUnwantedTrees() throws TreeCmpException {
        Tree baseTree = TreeCreator.getTreeFromString("(0,1,(2,(3,(4,5))));");
        Tree unwantedTree = TreeCreator.getTreeFromString("(0,1,(2,(3,(4,5))));");
        Tree[] treeList;
// Path: src/treecmp/common/TreeCmpException.java
// public class TreeCmpException extends Exception {
// 
//   private String errMsg;
// //----------------------------------------------
// // Default constructor - initializes instance variable to unknown
//   public TreeCmpException()
//   {
//     super();             // call superclass constructor
//     errMsg = "unknown";
//   }
// 
// //-----------------------------------------------
// // Constructor receives some kind of message that is saved in an instance variable.
//   public TreeCmpException(String errMsg)
//   {
//     super(errMsg);     // call super class constructor
//     this.errMsg = errMsg;  // save message
//   }
// 
// //------------------------------------------------
// // public method, callable by exception catcher. It returns the error message.
//   public String getError()
//   {
//     return errMsg;
//   }
// }
// 
// Path: src/treecmp/metric/RFMetric.java
// public class RFMetric extends BaseMetric implements Metric{
// 
//     public static double getRFDistance(Tree t1, Tree t2) {
// 
//         int n = t1.getExternalNodeCount();
//         if (n <= 3)
//             return 0;
// 
//         IdGroup idGroup = TreeUtils.getLeafIdGroup(t1);
//         BitSet[] s_t1=SplitDist.getSplits(t1, idGroup);
//         BitSet[] s_t2=SplitDist.getSplits(t2, idGroup);
//         int N1=s_t1.length;
//         int N2=s_t2.length;
//         int hashSetSize=(4*(N1+1))/3;
// 
//         HashSet<BitSet> s_t1_hs=new HashSet<BitSet>(hashSetSize);
// 
//         int i;
//         for(i=0;i<N1;i++){
//             s_t1_hs.add(s_t1[i]);
//         }
// 
//         int common=0;
//         for(i=0;i<N2;i++){
//              if (s_t1_hs.contains(s_t2[i])){
//                 common++;
//             }
//         }
// 
//         double dist=((double)N1+(double)N2)*0.5-(double)common;
//         return dist;
// 
//     }
// 
//     
// 
//     public double getDistance(Tree t1, Tree t2, int... indexes) {
// 
//         return RFMetric.getRFDistance(t1, t2);
// 
//     }
// }


// Path: test/treecmp/spr/SprUtilsTest.java
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import pal.misc.IdGroup;
import pal.tree.Node;
import pal.tree.Tree;
import pal.tree.TreeUtils;
import treecmp.common.TreeCmpException;
import treecmp.metric.Metric;
import treecmp.metric.RFMetric;
import treecmp.test.util.TreeCreator;
import java.util.HashSet;
import java.util.Set;

        Tree expTree = TreeCreator.getTreeFromString("(0,1,(5,(2,(3,4))));");
        Tree result = SprUtils.createUsprTree(baseTree, s, t);
        Metric rf = new RFMetric();
        try {
            assertEquals(0.0, rf.getDistance(expTree, result));
        } catch (TreeCmpException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testCreateUsprTree_CreateByNonRootNonLeaf_0_toNonRootNonLeaf_2_exchange_on_6_labels_tree() {
        Tree baseTree = TreeCreator.getTreeFromString("(0,1,(2,(3,(4,5))));");
        Node s = baseTree.getInternalNode(0);
        Node t = baseTree.getInternalNode(2);
        Tree expTree = TreeCreator.getTreeFromString("(0,1,((2,3),(4,5)));");
        Tree result = SprUtils.createUsprTree(baseTree, s, t);
        Metric rf = new RFMetric();
        try {
            assertEquals(0.0, rf.getDistance(expTree, result));
        } catch (TreeCmpException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testCreateUsprTree_LookingForSomeUnwantedTrees() throws TreeCmpException {
        Tree baseTree = TreeCreator.getTreeFromString("(0,1,(2,(3,(4,5))));");
        Tree unwantedTree = TreeCreator.getTreeFromString("(0,1,(2,(3,(4,5))));");
        Tree[] treeList;
        treeList = SprUtils.generateUSprNeighbours(baseTree);