|
@@ -1,7 +1,9 @@
|
|
package com.pact;
|
|
package com.pact;
|
|
|
|
|
|
|
|
+import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.Iterator;
|
|
|
|
+import java.util.List;
|
|
|
|
|
|
public class Node {
|
|
public class Node {
|
|
Node parent;
|
|
Node parent;
|
|
@@ -127,17 +129,32 @@ public class Node {
|
|
//
|
|
//
|
|
// }
|
|
// }
|
|
|
|
|
|
- public void deepSearch(Node node, HashSet<NodePair> h) {
|
|
|
|
- HashSet<NodePair> first_result = searchBothNodePair(node);
|
|
|
|
- for(NodePair res : first_result) {
|
|
|
|
- h.add(res);
|
|
|
|
|
|
+ public void _deepSearch(Node node, List<NodePair> h) {
|
|
|
|
+ // res1: Occurrences of node in this tree
|
|
|
|
+ List<NodePair> res1 = this.search(node);
|
|
|
|
+
|
|
|
|
+ // res2: Occurrences of this tree in node
|
|
|
|
+ List<NodePair> res2 = node.search(this);
|
|
|
|
+
|
|
|
|
+ assert(res1.size() == 0 || res2.size() == 0 || res1.equals(res2));
|
|
|
|
+
|
|
|
|
+ if(!res1.isEmpty()){
|
|
|
|
+ h.addAll(res1);
|
|
|
|
+ } else if(!res2.isEmpty()){
|
|
|
|
+ h.addAll(res2);
|
|
}
|
|
}
|
|
|
|
|
|
for(Node child : node.children) {
|
|
for(Node child : node.children) {
|
|
- deepSearch(child, h);
|
|
|
|
|
|
+ _deepSearch(child, h);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public List<NodePair> deepSearch(Node node) {
|
|
|
|
+ List<NodePair> result = new ArrayList<>();
|
|
|
|
+ _deepSearch(node, result);
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
public Node root() {
|
|
public Node root() {
|
|
if (getSiblings().isEmpty()) {
|
|
if (getSiblings().isEmpty()) {
|
|
return this;
|
|
return this;
|
|
@@ -155,41 +172,27 @@ public class Node {
|
|
return count;
|
|
return count;
|
|
}
|
|
}
|
|
|
|
|
|
- private void search(Node node, HashSet<NodePair> h) {
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Search this tree for the subtree with given root
|
|
|
|
+ * @param node the root of the subtree to search for
|
|
|
|
+ * @param l
|
|
|
|
+ */
|
|
|
|
+ private void _search(Node node, List<NodePair> l) {
|
|
if (equals(node)) {
|
|
if (equals(node)) {
|
|
this.linkNodes.add(node);
|
|
this.linkNodes.add(node);
|
|
node.linkNodes.add(this);
|
|
node.linkNodes.add(this);
|
|
- h.add(new NodePair(this, node));
|
|
|
|
|
|
+ l.add(new NodePair(this, node));
|
|
} else {
|
|
} else {
|
|
for(Node child : children) {
|
|
for(Node child : children) {
|
|
- child.search(node, h);
|
|
|
|
|
|
+ child._search(node, l);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private HashSet<NodePair> searchBothNodePair(Node node) {
|
|
|
|
- HashSet<NodePair> sResult = new HashSet<>();
|
|
|
|
- search(node, sResult);
|
|
|
|
-
|
|
|
|
- HashSet<NodePair> nsResult = new HashSet<>();
|
|
|
|
- node.search(this, nsResult);
|
|
|
|
-
|
|
|
|
- for (NodePair curr : nsResult) {
|
|
|
|
- boolean inSet = inSet(curr, sResult);
|
|
|
|
- if (!inSet) {
|
|
|
|
- sResult.add(curr);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return sResult;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private boolean inSet(NodePair n, Iterable<NodePair> it) {
|
|
|
|
- for (NodePair nodes : it) {
|
|
|
|
- if (n.equals(nodes)) {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
|
|
+ private List<NodePair> search(Node node) {
|
|
|
|
+ List<NodePair> result = new ArrayList<>();
|
|
|
|
+ _search(node, result);
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
|
|
|
|
private boolean isIn(Node node) {
|
|
private boolean isIn(Node node) {
|
|
@@ -240,7 +243,7 @@ public class Node {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private HashSet<Node> getDuplicates(HashSet<NodePair> h) {
|
|
|
|
|
|
+ private HashSet<Node> getDuplicates(List<NodePair> h) {
|
|
HashSet<Node> result = new HashSet<>();
|
|
HashSet<Node> result = new HashSet<>();
|
|
for (NodePair curr : h) {
|
|
for (NodePair curr : h) {
|
|
if (curr.node1 == this)
|
|
if (curr.node1 == this)
|
|
@@ -311,15 +314,13 @@ public class Node {
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
- HashSet sResult = new HashSet();
|
|
|
|
- node2.deepSearch(node1, sResult);
|
|
|
|
|
|
+ List<NodePair> sResult = node2.deepSearch(node1);
|
|
|
|
|
|
if (sResult.isEmpty()) {
|
|
if (sResult.isEmpty()) {
|
|
result.add(combineAtRoot(node2, node1));
|
|
result.add(combineAtRoot(node2, node1));
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
- HashSet<NodePair> largest = getLNodePair(sResult);
|
|
|
|
|
|
|
|
HashSet<Node> unsharedNodePair = new HashSet<>();
|
|
HashSet<Node> unsharedNodePair = new HashSet<>();
|
|
node2.collectUnshared(unsharedNodePair);
|
|
node2.collectUnshared(unsharedNodePair);
|
|
@@ -338,6 +339,7 @@ public class Node {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ List<NodePair> largest = getLargestNodePairs(sResult);
|
|
if (!largest.isEmpty()) {
|
|
if (!largest.isEmpty()) {
|
|
Iterator itLargest = largest.iterator();
|
|
Iterator itLargest = largest.iterator();
|
|
|
|
|
|
@@ -416,7 +418,7 @@ public class Node {
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
- if (NodePair.getNodesSize(largest) == 1) {
|
|
|
|
|
|
+ if (largest.get(0).nodesSize() == 1) { // Shares only leaves
|
|
HashSet unique = getUniqueNodePair(sResult);
|
|
HashSet unique = getUniqueNodePair(sResult);
|
|
Iterator uIt = unique.iterator();
|
|
Iterator uIt = unique.iterator();
|
|
|
|
|
|
@@ -445,8 +447,7 @@ public class Node {
|
|
}
|
|
}
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
-
|
|
|
|
- if (NodePair.getNodesSize(largest) > 1) {
|
|
|
|
|
|
+ else { // shares sub-trees
|
|
for (Object aLargest : largest) {
|
|
for (Object aLargest : largest) {
|
|
NodePair currL = (NodePair) aLargest;
|
|
NodePair currL = (NodePair) aLargest;
|
|
HashSet largeResult = subTrees(currL);
|
|
HashSet largeResult = subTrees(currL);
|
|
@@ -457,8 +458,6 @@ public class Node {
|
|
}
|
|
}
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
-
|
|
|
|
- return result;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
public static HashSet<Node> reducedCombine(Node node1, Node node2) {
|
|
public static HashSet<Node> reducedCombine(Node node1, Node node2) {
|
|
@@ -497,13 +496,13 @@ public class Node {
|
|
}
|
|
}
|
|
|
|
|
|
private static boolean oneAreaShared(Node node1, Node node2) {
|
|
private static boolean oneAreaShared(Node node1, Node node2) {
|
|
- HashSet<NodePair> result = new HashSet<>();
|
|
|
|
- node2.deepSearch(node1, result);
|
|
|
|
- HashSet<NodePair> largest = getLNodePair(result);
|
|
|
|
- if (largest.isEmpty()) {
|
|
|
|
|
|
+ List<NodePair> result = node2.deepSearch(node1);
|
|
|
|
+ if (result.isEmpty()) {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
- return (NodePair.getNodesSize(largest) == 1) && (largest.size() == 1);
|
|
|
|
|
|
+ List<NodePair> largest = getLargestNodePairs(result);
|
|
|
|
+ return largest.size() == 1 && largest.get(0).nodesSize() == 1;
|
|
|
|
+// return (NodePair.getNodesSize(largest) == 1) && (largest.size() == 1);
|
|
}
|
|
}
|
|
|
|
|
|
private static void sortLargestSibs(Iterator<Node> lgsibs, Node lg, HashSet<Node> ns, HashSet<Node> os) {
|
|
private static void sortLargestSibs(Iterator<Node> lgsibs, Node lg, HashSet<Node> ns, HashSet<Node> os) {
|
|
@@ -576,8 +575,8 @@ public class Node {
|
|
* @param h HashSet
|
|
* @param h HashSet
|
|
* @return The largest NodePair in h, based on the length of n1's Venn diagram
|
|
* @return The largest NodePair in h, based on the length of n1's Venn diagram
|
|
*/
|
|
*/
|
|
- private static HashSet<NodePair> getLNodePair(HashSet<NodePair> h) {
|
|
|
|
- HashSet<NodePair> result = new HashSet<>();
|
|
|
|
|
|
+ private static List<NodePair> getLargestNodePairs(List<NodePair> h) {
|
|
|
|
+ List<NodePair> result = new ArrayList<>();
|
|
int size = -1;
|
|
int size = -1;
|
|
|
|
|
|
for(NodePair curr : h){
|
|
for(NodePair curr : h){
|
|
@@ -593,31 +592,24 @@ public class Node {
|
|
}
|
|
}
|
|
|
|
|
|
private static Node combineAtRoot(Node node1, Node node2) {
|
|
private static Node combineAtRoot(Node node1, Node node2) {
|
|
- HashSet<Node> uniqueNodePair = new HashSet<>();
|
|
|
|
- boolean reduced = false;
|
|
|
|
|
|
+ HashSet<Node> uniqueNodes = new HashSet<>();
|
|
for(Node curr : node1.children) {
|
|
for(Node curr : node1.children) {
|
|
- if (!curr.inSet(uniqueNodePair))
|
|
|
|
- uniqueNodePair.add(curr);
|
|
|
|
- else {
|
|
|
|
- reduced = true;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!curr.inSet(uniqueNodes))
|
|
|
|
+ uniqueNodes.add(curr);
|
|
}
|
|
}
|
|
for(Node curr : node2.children) {
|
|
for(Node curr : node2.children) {
|
|
- if (!curr.inSet(uniqueNodePair))
|
|
|
|
- uniqueNodePair.add(curr);
|
|
|
|
- else {
|
|
|
|
- reduced = true;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!curr.inSet(uniqueNodes))
|
|
|
|
+ uniqueNodes.add(curr);
|
|
}
|
|
}
|
|
- if (!reduced) {
|
|
|
|
- return new Node(null, "(" + node1.venn + node2.getVenn() + ")");
|
|
|
|
- } else {
|
|
|
|
|
|
+ if (uniqueNodes.size() < (node1.children.size() + node2.children.size())) {
|
|
String result_venn = "(";
|
|
String result_venn = "(";
|
|
- for (Node unique : uniqueNodePair) {
|
|
|
|
|
|
+ for (Node unique : uniqueNodes) {
|
|
result_venn = result_venn + unique;
|
|
result_venn = result_venn + unique;
|
|
}
|
|
}
|
|
result_venn = result_venn + ")";
|
|
result_venn = result_venn + ")";
|
|
return new Node(null, result_venn);
|
|
return new Node(null, result_venn);
|
|
|
|
+ } else {
|
|
|
|
+ return new Node(null, "(" + node1.venn + node2.getVenn() + ")");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -692,7 +684,7 @@ public class Node {
|
|
return setResult;
|
|
return setResult;
|
|
}
|
|
}
|
|
|
|
|
|
- private static HashSet<Node> getUniqueNodePair(HashSet<NodePair> h) {
|
|
|
|
|
|
+ private static HashSet<Node> getUniqueNodePair(List<NodePair> h) {
|
|
HashSet<Node> result = new HashSet<>();
|
|
HashSet<Node> result = new HashSet<>();
|
|
for (NodePair curr : h) {
|
|
for (NodePair curr : h) {
|
|
if (!result.contains(curr.node1)) {
|
|
if (!result.contains(curr.node1)) {
|
|
@@ -704,5 +696,4 @@ public class Node {
|
|
}
|
|
}
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
-
|
|
|
|
}
|
|
}
|