docs: public Set<Explanation<OWLAxiom>> getExplanations(OWLAxiom entailment, int limit) throws ExplanationException {
  
          final Set<Explanation<OWLAxiom>> preferredLaconicExplanations = new HashSet<Explanation<OWLAxiom>>();
  
          TelemetryTimer computeOplusTimer = new TelemetryTimer();
          TelemetryTimer computeOplusJustificationsTimer = new TelemetryTimer();
          TelemetryTimer islaconicTimer = new TelemetryTimer();
          TelemetryTimer reconstituteTimer = new TelemetryTimer();
          TelemetryTimer ispreferredCheckTimer = new TelemetryTimer();
          TelemetryTimer regularJustificationsTimer = new TelemetryTimer();
  
          TelemetryInfo info = new DefaultTelemetryInfo(getClass().getSimpleName(), computeOplusTimer, computeOplusJustificationsTimer, islaconicTimer, reconstituteTimer, ispreferredCheckTimer);
          TelemetryTransmitter transmitter = TelemetryTransmitter.getTransmitter();
  
          Set<Explanation<OWLAxiom>> regularJustifications = new HashSet<Explanation<OWLAxiom>>();
  
          try {
              transmitter.beginTransmission(info);
  
              Set<Explanation<OWLAxiom>> computedExplanations = new HashSet<Explanation<OWLAxiom>>();
              Set<Explanation<OWLAxiom>> tmp = new HashSet<Explanation<OWLAxiom>>();
              OPlusGenerator transformation = new OPlusGenerator(dataFactory, OPlusSplitting.TOP_LEVEL);
  
  
              computeOplusJustificationsTimer.start();
              int rounds = 0;
  
              boolean foundNew;
              boolean foundExternal;
              boolean foundExternallyMaskedJustifications = false;
  
              do {
                  if (progressMonitor.isCancelled()) {
                      throw new ExplanationGeneratorInterruptedException();
                  }
                  rounds++;
  
                  Set<OWLAxiom> lastRoundAxioms = new HashSet<OWLAxiom>();
                  for (Explanation<OWLAxiom> expl : computedExplanations) {
                      for(OWLAxiom ax : expl.getAxioms()) {
                          if(inputAxioms.contains(ax)) {
                              lastRoundAxioms.add(ax);
                          }
                      }
                  }
  
                  Set<OWLAxiom> workingAxioms = new HashSet<OWLAxiom>(inputAxioms);
                  Set<OWLAxiom> oplusedAxioms = transformation.transform(lastRoundAxioms);
                  for (OWLAxiom ax : lastRoundAxioms) {
                      if (!oplusedAxioms.contains(ax)) {
                          workingAxioms.remove(ax);
                      }
                  }
                  workingAxioms.addAll(oplusedAxioms);
                  ExplanationGenerator<OWLAxiom> gen = delegate.createExplanationGenerator(workingAxioms, new MediatingProgresssMonitor());
                  if (rounds == 1) {
                      regularJustificationsTimer.start();
                  }
                  tmp = gen.getExplanations(entailment);
                  if (rounds == 1) {
                      regularJustificationsTimer.stop();
                  }
                  if(rounds == 1) {
                      System.out.println("Found " + tmp.size() + " regular justifications");
                      transmitter.recordMeasurement(info, "number of regular justifications", tmp.size());
                      regularJustifications.addAll(tmp);
                      transmitter.recordTiming(info, "time to find regular justifications", regularJustificationsTimer);
                  }
                  foundNew = computedExplanations.addAll(tmp);
                  foundExternal = false;
                  foundExternallyMaskedJustifications = false;
                  if(foundNew) {
                      for(Explanation<OWLAxiom> expl : computedExplanations) {
                          for(OWLAxiom ax : expl.getAxioms()) {
                              if(inputAxioms.contains(ax) && !lastRoundAxioms.contains(ax)) {
                                  foundExternal = true;
                                  if(rounds > 1) {
                                      foundExternallyMaskedJustifications = true;
                                  }
                                  break;
                              }
                          }
                          if(foundExternal) {
                              break;
                          }
                      }
                  }
                  if(foundNew && !foundExternal) {
                      System.out.println("Early termination.");
                      transmitter.recordMeasurement(info, "early round termination", true);
                      transmitter.recordMeasurement(info, "found externally masked justifications", foundExternallyMaskedJustifications);
                  }
              } while (foundNew && foundExternal);
  
  
              transmitter.recordMeasurement(info, "number of compute oplus justifications rounds", rounds);
              computeOplusJustificationsTimer.stop();
              transmitter.recordTiming(info, "time to compute oplus justifications", computeOplusJustificationsTimer);
  
              Set<Explanation<OWLAxiom>> oplusExpls = new HashSet<Explanation<OWLAxiom>>(computedExplanations);
              IsLaconicChecker checker = new IsLaconicChecker(dataFactory, entailmentCheckerFactory, LaconicCheckerMode.EARLY_TERMINATING);
              Set<Explanation<OWLAxiom>> laconicExplanations = new HashSet<Explanation<OWLAxiom>>();
  
              islaconicTimer.start();
              for (Explanation<OWLAxiom> expl : oplusExpls) {
                  if (progressMonitor.isCancelled()) {
                      throw new ExplanationGeneratorInterruptedException();
                  }
                  if (checker.isLaconic(expl)) {
                      laconicExplanations.add(expl);
                  }
              }
              islaconicTimer.stop();
              transmitter.recordTiming(info, "time to check laconic oplus justifications", islaconicTimer);
  
              transmitter.recordMeasurement(info, "number of laconic oplus justifications", laconicExplanations.size());
  
              if (laconicExplanations.isEmpty()) {
                  System.out.println("I didn't find any oplus explanations that were laconic!!!");
                  System.out.println("Here's what I found:");
                  ToStringRenderer.getInstance().setRenderer(new DLSyntaxObjectRenderer());
                  for (Explanation<OWLAxiom> expl : oplusExpls) {
                      System.out.println(expl);
                  }
  
                  ToStringRenderer.getInstance().setRenderer(new SimpleRenderer());
              }
  
              reconstituteTimer.start();
              Set<Explanation<OWLAxiom>> reconstitutedLaconicExpls = getReconstitutedExplanations(dataFactory, transformation, laconicExplanations);
              reconstituteTimer.stop();
              transmitter.recordTiming(info, "time to reconstitute justifications", reconstituteTimer);
  
              transmitter.recordMeasurement(info, "number of reconstituted justifications", reconstitutedLaconicExpls.size());
  
  
              Map<Explanation<OWLAxiom>, Set<OWLAxiom>> oplusCache = new HashMap<Explanation<OWLAxiom>, Set<OWLAxiom>>();
  
  
              ispreferredCheckTimer.start();
              Set<Explanation<OWLAxiom>> toFilter = new HashSet<Explanation<OWLAxiom>>();
              List<Explanation<OWLAxiom>> explsList = new ArrayList<Explanation<OWLAxiom>>(reconstitutedLaconicExpls);
              for (int i = 0; i < explsList.size(); i++) {
                  for (int j = i + 1; j < explsList.size(); j++) {
                      Explanation<OWLAxiom> explI = explsList.get(i);
                      Explanation<OWLAxiom> explJ = explsList.get(j);
                      Set<OWLAxiom> oplusI = oplusCache.get(explI);
                      if (oplusI == null) {
                          OPlusGenerator generator = new OPlusGenerator(dataFactory, OPlusSplitting.NONE);
                          oplusI = generator.transform(explI.getAxioms());
                          oplusCache.put(explI, oplusI);
                      }
                      Set<OWLAxiom> oplusJ = oplusCache.get(explJ);
                      if (oplusJ == null) {
                          OPlusGenerator generator = new OPlusGenerator(dataFactory, OPlusSplitting.NONE);
                          oplusJ = generator.transform(explJ.getAxioms());
                          oplusCache.put(explJ, oplusJ);
                      }
                      if (!oplusI.equals(oplusJ)) {
                          if (oplusI.containsAll(oplusJ) || oplusJ.containsAll(oplusI)) {
                              toFilter.add(explI);
                              toFilter.add(explJ);
                          }
                      }
                  }
              }
  
              preferredLaconicExplanations.addAll(reconstitutedLaconicExpls);
              preferredLaconicExplanations.removeAll(toFilter);
  
              transmitter.recordMeasurement(info, "number of non-check preferred laconic justifications", preferredLaconicExplanations.size());
              transmitter.recordMeasurement(info, "number of check laconic justifications", toFilter.size());
  
  //        System.out.println("I have found " + toFilter.size() + " explanations that require filtering");
  //        System.out.println("This means that I already know that there are " + preferredLaconicExplanations.size() + " preferred laconic explanations");
  
  
              for (final Explanation<OWLAxiom> laconicExpl : toFilter) {
                  Set<OWLAxiom> sources = getSourceAxioms(laconicExpl, transformation);
                  ExplanationGenerator<OWLAxiom> explanationGenerator = delegate.createExplanationGenerator(sources);
                  Set<Explanation<OWLAxiom>> regularExpls = explanationGenerator.getExplanations(laconicExpl.getEntailment());
                  //            System.out.println("From the axiom sources I have found " + regularExpls.size() + " regular justifications");
                  try {
                      for (Explanation<OWLAxiom> regularExpl : regularExpls) {
  
                          int size = preferredLaconicExplanations.size();
                          LaconicExplanationGeneratorBasedOnDeltaPlus lacGen = new LaconicExplanationGeneratorBasedOnDeltaPlus(regularExpl.getAxioms(), entailmentCheckerFactory, delegate, new ExplanationProgressMonitor<OWLAxiom>() {
  
                              private boolean cancelled = false;
  
                              public void foundExplanation(ExplanationGenerator<OWLAxiom> owlAxiomExplanationGenerator, Explanation<OWLAxiom> owlAxiomExplanation, Set<Explanation<OWLAxiom>> allFoundExplanations) {
                                  System.out.println(owlAxiomExplanation);
                                  if (owlAxiomExplanation.equals(laconicExpl)) {
                                      preferredLaconicExplanations.add(laconicExpl);
                                      cancelled = true;
                                  }
                              }
  
                              public boolean isCancelled() {
                                  return cancelled;
                              }
                          });
                          Set<Explanation<OWLAxiom>> deltaPlusGeneratedExpls = lacGen.getExplanations(laconicExpl.getEntailment());
  
  
                          if (preferredLaconicExplanations.size() != size) {
                              break;
                          }
                      }
                  }
                  catch (ExplanationGeneratorInterruptedException e) {
                      System.out.println("Early termination");
                  }
              }
              ispreferredCheckTimer.stop();
  
              final Set<Explanation<OWLAxiom>> progressFound = new HashSet<Explanation<OWLAxiom>>();
              for (Explanation<OWLAxiom> expl : preferredLaconicExplanations) {
                  progressFound.add(expl);
                  progressMonitor.foundExplanation(this, expl, progressFound);
              }
  
  
              transmitter.recordTiming(info, "time to check preferred laconic justifications", ispreferredCheckTimer);
  
              transmitter.recordMeasurement(info, "number of preferred laconic justifications", preferredLaconicExplanations.size());
  
          }
          finally {
              transmitter.recordMeasurement(info, "number of oplus justifications", numberOfOPlusJustificationsFound);
              transmitter.endTransmission(info);
          }
          recordJustifications(regularJustifications, "regularjustifications");
          return preferredLaconicExplanations;
  
      }