// Path: src/main/java/cl/uchile/dcc/blabel/label/util/Orbits.java
// public class Orbits {
// 	
// 	// only non-trivial ones
// 	Partition<Node> orbits = new Partition<Node>();
// 	
// 	public Orbits(){
// 		super();
// 	}
// 	
// 	public int countOrbits(){
// 		return orbits.partitions;
// 	}
// 	
// 	public int maxOrbit(){
// 		int max = 0;
// 		for(TreeSet<Node> o:orbits.values()){
// 			if(o.size()>max)
// 				max = o.size();
// 		}
// 		return max;
// 	}
// 	
// 	public boolean addAndCompose(HashMap<Node,Node> auto){
// 		return updateOrbits(auto, this.orbits);
// 	}
// 	
// 	public TreeSet<Node> getNonTrivialOrbit(Node n){
// 		return orbits.getPartition(n);
// 	}
// 	
// 	private boolean updateOrbits(HashMap<Node,Node> auto, Partition<Node> orbits){
// 		boolean add = false;
// 		for(Map.Entry<Node, Node> e:auto.entrySet()){
// 			if(!e.getKey().equals(e.getValue())){
// 				add |= orbits.addPair(e.getKey(), e.getValue());
// 			}
// 		}
// 		return add;
// 	}
// 	
// 	/**
// 	 * See if the given nodes form an orbit in the known automorphisms.
// 	 * 
// 	 * @param nodes
// 	 * @return
// 	 */
// 	public boolean isOrbit(Collection<Node> nodes){
// 		if(nodes==null || nodes.isEmpty()){
// 			throw new IllegalArgumentException("Expecting non-null, non-empty input for orbit detection");
// 		}
// 		Iterator<Node> i = nodes.iterator();
// 		
// 		TreeSet<Node> o = orbits.get(i.next());
// 		if(o==null)
// 			return false;
// 		return o.containsAll(nodes);
// 	}
// 	
// 	
// 	public static HashMap<Node,Node> inverse(HashMap<Node,Node> auto){
// 		 HashMap<Node,Node> inv = new HashMap<Node,Node>(auto.size());
// 		 for(Map.Entry<Node, Node> e : auto.entrySet()){
// 			 inv.put(e.getValue(), e.getKey());
// 		 }
// 		 return inv;
// 	}
// 	
// 	public static HashMap<Node,Node> comp(HashMap<Node,Node> a1, HashMap<Node,Node> a2){
// 		HashMap<Node,Node> comp = new HashMap<Node,Node>(a1.size());
// 		for(Map.Entry<Node, Node> e : a1.entrySet()){
// 			 Node c = a2.get(e.getValue());
// 			 if(c==null){
// 				 throw new IllegalArgumentException("Not an automorphism");
// 			 }
// 			 comp.put(e.getKey(), c);
// 		}
// 		return comp;
// 	}
// }
// 
// Path: src/main/java/cl/uchile/dcc/blabel/lean/util/Bindings.java
// public class Bindings {
// 	private final ArrayList<BNode> output;
// 	private final ArrayList<Node[]> bindings;
// 	
// 	public Bindings(ArrayList<BNode> output, ArrayList<Node[]> bindings){
// 		this.output = output;
// 		this.bindings = bindings;
// 	}
// 
// 	public ArrayList<BNode> getOutput() {
// 		return output;
// 	}
// 
// 	public ArrayList<Node[]> getBindings() {
// 		return bindings;
// 	}
// }


import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeSet;
import java.util.logging.Logger;
import org.semanticweb.yars.nx.BNode;
import org.semanticweb.yars.nx.Node;
import org.semanticweb.yars.nx.NodeComparator;
import org.semanticweb.yars.nx.Nodes;
import org.semanticweb.yars.nx.parser.NxParser;
import org.semanticweb.yars.stats.Count;
import cl.uchile.dcc.blabel.label.util.Orbits;
import cl.uchile.dcc.blabel.lean.util.Bindings;

					
					boolean trivial = true;
					ArrayList<Node> automorphism = new ArrayList<Node>();
					for(BNode b: automorphismMask){
						Node val = partialSol.get(b);
						automorphism.add(val);
						if(!b.equals(val)){
							trivial = false;
						}
					}
					
					// don't want to add the trivial automorphism twice
					if(!trivial){
						automorphisms.add(automorphism);
					}
				}
			}
			
			// if solution is no good, we need to
			// return the object state to where it was
			for(int i=0; i<bindings.getOutput().size(); i++){
				partialSol.remove(bindings.getOutput().get(i));
				timesBound.put(bind[i],timesBound.get(bind[i])-1);
			}
		}
			
		// no homomorphism found
		return null;
	}	
	

// Path: src/main/java/cl/uchile/dcc/blabel/label/util/Orbits.java
// public class Orbits {
// 	
// 	// only non-trivial ones
// 	Partition<Node> orbits = new Partition<Node>();
// 	
// 	public Orbits(){
// 		super();
// 	}
// 	
// 	public int countOrbits(){
// 		return orbits.partitions;
// 	}
// 	
// 	public int maxOrbit(){
// 		int max = 0;
// 		for(TreeSet<Node> o:orbits.values()){
// 			if(o.size()>max)
// 				max = o.size();
// 		}
// 		return max;
// 	}
// 	
// 	public boolean addAndCompose(HashMap<Node,Node> auto){
// 		return updateOrbits(auto, this.orbits);
// 	}
// 	
// 	public TreeSet<Node> getNonTrivialOrbit(Node n){
// 		return orbits.getPartition(n);
// 	}
// 	
// 	private boolean updateOrbits(HashMap<Node,Node> auto, Partition<Node> orbits){
// 		boolean add = false;
// 		for(Map.Entry<Node, Node> e:auto.entrySet()){
// 			if(!e.getKey().equals(e.getValue())){
// 				add |= orbits.addPair(e.getKey(), e.getValue());
// 			}
// 		}
// 		return add;
// 	}
// 	
// 	/**
// 	 * See if the given nodes form an orbit in the known automorphisms.
// 	 * 
// 	 * @param nodes
// 	 * @return
// 	 */
// 	public boolean isOrbit(Collection<Node> nodes){
// 		if(nodes==null || nodes.isEmpty()){
// 			throw new IllegalArgumentException("Expecting non-null, non-empty input for orbit detection");
// 		}
// 		Iterator<Node> i = nodes.iterator();
// 		
// 		TreeSet<Node> o = orbits.get(i.next());
// 		if(o==null)
// 			return false;
// 		return o.containsAll(nodes);
// 	}
// 	
// 	
// 	public static HashMap<Node,Node> inverse(HashMap<Node,Node> auto){
// 		 HashMap<Node,Node> inv = new HashMap<Node,Node>(auto.size());
// 		 for(Map.Entry<Node, Node> e : auto.entrySet()){
// 			 inv.put(e.getValue(), e.getKey());
// 		 }
// 		 return inv;
// 	}
// 	
// 	public static HashMap<Node,Node> comp(HashMap<Node,Node> a1, HashMap<Node,Node> a2){
// 		HashMap<Node,Node> comp = new HashMap<Node,Node>(a1.size());
// 		for(Map.Entry<Node, Node> e : a1.entrySet()){
// 			 Node c = a2.get(e.getValue());
// 			 if(c==null){
// 				 throw new IllegalArgumentException("Not an automorphism");
// 			 }
// 			 comp.put(e.getKey(), c);
// 		}
// 		return comp;
// 	}
// }
// 
// Path: src/main/java/cl/uchile/dcc/blabel/lean/util/Bindings.java
// public class Bindings {
// 	private final ArrayList<BNode> output;
// 	private final ArrayList<Node[]> bindings;
// 	
// 	public Bindings(ArrayList<BNode> output, ArrayList<Node[]> bindings){
// 		this.output = output;
// 		this.bindings = bindings;
// 	}
// 
// 	public ArrayList<BNode> getOutput() {
// 		return output;
// 	}
// 
// 	public ArrayList<Node[]> getBindings() {
// 		return bindings;
// 	}
// }


// Path: src/main/java/cl/uchile/dcc/blabel/lean/DFSGraphLeaning.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeSet;
import java.util.logging.Logger;
import org.semanticweb.yars.nx.BNode;
import org.semanticweb.yars.nx.Node;
import org.semanticweb.yars.nx.NodeComparator;
import org.semanticweb.yars.nx.Nodes;
import org.semanticweb.yars.nx.parser.NxParser;
import org.semanticweb.yars.stats.Count;
import cl.uchile.dcc.blabel.label.util.Orbits;
import cl.uchile.dcc.blabel.lean.util.Bindings;

					
					boolean trivial = true;
					ArrayList<Node> automorphism = new ArrayList<Node>();
					for(BNode b: automorphismMask){
						Node val = partialSol.get(b);
						automorphism.add(val);
						if(!b.equals(val)){
							trivial = false;
						}
					}
					
					// don't want to add the trivial automorphism twice
					if(!trivial){
						automorphisms.add(automorphism);
					}
				}
			}
			
			// if solution is no good, we need to
			// return the object state to where it was
			for(int i=0; i<bindings.getOutput().size(); i++){
				partialSol.remove(bindings.getOutput().get(i));
				timesBound.put(bind[i],timesBound.get(bind[i])-1);
			}
		}
			
		// no homomorphism found
		return null;
	}	
	

	private static boolean prune(Node next, Orbits o, TreeSet<Node> visited){
