private boolean nodesCanBeMapped(
     IsomorphismCalculator rhs,
     Map<Integer, Integer> mapping,
     Set<Integer> mappedLhsNodes,
     Set<Integer> mappedRhsNodes,
     Set<Integer> leadingEdgeNodes) {
   assert mapping.size() == mappedLhsNodes.size() && mapping.size() == mappedRhsNodes.size()
       : String.format(
           "Mapping sizes are different: %s, %s, %s",
           mapping.size(), mappedLhsNodes.size(), mappedRhsNodes.size());
   assert mappingInvariantsSatisfied() : "Bug detected.  Should never happen";
   if (mapping.size() == size) return true;
   Integer node = chooseNode(mappedLhsNodes, leadingEdgeNodes);
   mappedLhsNodes.add(node);
   Set<Integer> newLeadingEdgeNodes = new HashSet<Integer>(leadingEdgeNodes);
   newLeadingEdgeNodes.addAll(qecGraph.neighbours(node));
   newLeadingEdgeNodes.removeAll(mappedLhsNodes);
   Iterable<Integer> rhsCandidates = findCandidateMappings(node, rhs, mapping, mappedRhsNodes);
   for (Integer rhsNode : rhsCandidates) {
     mapping.put(node, rhsNode);
     mappedRhsNodes.add(rhsNode);
     if (nodesCanBeMapped(rhs, mapping, mappedLhsNodes, mappedRhsNodes, newLeadingEdgeNodes)) {
       assert mappingInvariantsSatisfied() : "Bug detected.  Should never happen";
       return true;
     }
     mapping.remove(node);
     mappedRhsNodes.remove(rhsNode);
   }
   mappedLhsNodes.remove(node);
   assert mappingInvariantsSatisfied() : "Bug detected.  Should never happen";
   return false;
 }
 private Map<NodeCharacterisation, Set<Integer>> createCharacterisationMappings() {
   Map<NodeCharacterisation, Set<Integer>> mapping =
       new HashMap<NodeCharacterisation, Set<Integer>>();
   for (int node = 0; node < size; node++) {
     int blackNeighbourCount = 0;
     int whiteNeighbourCount = 0;
     for (int possibleNeighbour = 0; possibleNeighbour < size; possibleNeighbour++) {
       if (qecGraph.edge(node, possibleNeighbour)) {
         if (qecGraph.isBlack(possibleNeighbour)) {
           blackNeighbourCount++;
         } else {
           whiteNeighbourCount++;
         }
       }
     }
     addToCharacterisationMappings(
         mapping, node, qecGraph.isBlack(node), blackNeighbourCount, whiteNeighbourCount);
   }
   return mapping;
 }
 private Set<Integer> filterAgainstExistingMappings(
     Integer node,
     IsomorphismCalculator rhs,
     Map<Integer, Integer> mapping,
     Set<Integer> candidateMappings) {
   Collection<Integer> neighbours = qecGraph.neighbours(node);
   Set<Integer> filteredCandidates = new HashSet<Integer>();
   for (Integer candidate : candidateMappings) {
     if (agreesWithExistingMappings(candidate, neighbours, rhs, mapping)) {
       filteredCandidates.add(candidate);
     }
   }
   return filteredCandidates;
 }
 private int getNumberOfBlackNodes() {
   if (numberOfBlackNodes < 0) numberOfBlackNodes = qecGraph.getNumberOfBlackNodes();
   return numberOfBlackNodes;
 }
 public IsomorphismCalculator(QecGraph qecGraph) {
   this.qecGraph = qecGraph;
   size = qecGraph.getSize();
 }