docs: public Set<OWLClass> getRootUnsatisfiableClasses() throws ExplanationException {
          StructuralRootDerivedReasoner srd = new StructuralRootDerivedReasoner(manager, baseReasoner, reasonerFactory);
          Set<OWLClass> estimatedRoots = srd.getRootUnsatisfiableClasses();
          cls2JustificationMap = new HashMap<OWLClass, Set<Explanation<OWLAxiom>>>();
          Set<OWLAxiom> allAxioms = new HashSet<OWLAxiom>();
          for (OWLOntology ont : baseReasoner.getRootOntology().getImportsClosure()) {
              allAxioms.addAll(ont.getLogicalAxioms());
          }
  
          for (OWLClass cls : estimatedRoots) {
              cls2JustificationMap.put(cls, new HashSet<Explanation<OWLAxiom>>());
              System.out.println("POTENTIAL ROOT: " + cls);
          }
          System.out.println("Finding real roots from " + estimatedRoots.size() + " estimated roots");
  
          int done = 0;
          roots.addAll(estimatedRoots);
          for (final OWLClass estimatedRoot : estimatedRoots) {
              ExplanationGeneratorFactory<OWLAxiom> genFac = ExplanationManager.createExplanationGeneratorFactory(reasonerFactory);
              ExplanationGenerator<OWLAxiom> gen = genFac.createExplanationGenerator(allAxioms);
              OWLDataFactory df = manager.getOWLDataFactory();
              Set<Explanation<OWLAxiom>> expls = gen.getExplanations(df.getOWLSubClassOfAxiom(estimatedRoot, df.getOWLNothing()));
              cls2JustificationMap.get(estimatedRoot).addAll(expls);
              done++;
              System.out.println("Done " + done);
          }
          for(OWLClass clsA : estimatedRoots) {
              for(OWLClass clsB : estimatedRoots) {
                  if (!clsA.equals(clsB)) {
                      Set<Explanation<OWLAxiom>> clsAExpls = cls2JustificationMap.get(clsA);
                      Set<Explanation<OWLAxiom>> clsBExpls = cls2JustificationMap.get(clsB);
                      boolean clsARootForClsB = false;
                      boolean clsBRootForClsA = false;
                      // Be careful of cyclic dependencies!
                      for(Explanation<OWLAxiom> clsAExpl : clsAExpls) {
                          for(Explanation<OWLAxiom> clsBExpl : clsBExpls) {
                              if(isRootFor(clsAExpl, clsBExpl)) {
                                  // A is a root of B
                                  clsARootForClsB = true;
  //                                System.out.println(clsB + "  --- depends --->  " + clsA);
                              }
                              else if(isRootFor(clsBExpl, clsAExpl)) {
                                  // B is a root of A
                                  clsBRootForClsA = true;
  //                                System.out.println(clsA + "  --- depends --->  " + clsB);
                              }
                          }
                      }
                      if (!clsARootForClsB || !clsBRootForClsA) {
                          if(clsARootForClsB) {
                              roots.remove(clsB);
                          }
                          else if(clsBRootForClsA) {
                              roots.remove(clsA);
                          }
                      }
                  }
              }
          }
          return roots;
      }