public Pair<Symbol, SymbolString> getAmbiguousCore() {
		AmbNode amb = getMinimalParseTree();
		
		if (amb == null) {
			String s = "No ambiguity node found for " + top.getRootSymbol() + " : " + top.yield().prettyPrint();
			System.out.println(s);
			//throw new RuntimeException(s);
			return new Pair<Symbol, SymbolString>(top.getRootSymbol(), top.yield());
		}

		amb.removeNestedAmbiguities();
		amb.liftToCharacterClasses();
		amb.addPosInfo(0);
		
		// remove identical nodes from bottom of all alternatives
		boolean changed;
		do {
			changed = false;
			Queue<List<ParseTreeNode>> q = new Queue<List<ParseTreeNode>>();
			for (int i = 0; i < amb.children.size(); ++i) {
				List<ParseTreeNode> y = new ArrayList<ParseTreeNode>();
				amb.children.get(i).getBottom(y);
				q.add(y);
			}
			
 			Set<ParseTreeNode> remove = new ShareableHashSet<ParseTreeNode>();
 			List<ParseTreeNode> y = q.get(0);
 			for (ParseTreeNode n : y) {
 				Set<ParseTreeNode> equalNodes = new ShareableHashSet<ParseTreeNode>();
 				for (int i = 1; i < q.size(); ++i) {
 					for (ParseTreeNode n2 : q.get(i)) {
 						if (n.equalTo(n2) && !remove.contains(n2)) {
 							equalNodes.add(n2);
 							break;
 						}
 					}
 				}
 				if (equalNodes.size() == q.size() - 1) {
 					remove.addAll(equalNodes);
 					remove.add(n);
 				}
 			}
 			
			amb.removeNodes(remove);
			changed = remove.size() > 0;
		} while (changed);
		
		amb.reconstructChildren();
		
		return new Pair<Symbol, SymbolString>(amb.getRootSymbol(), amb.yield());
	}