code: static <S, I, O> Optional<ADSNode<S, I, O>> compute(final MealyMachine<S, I, ?, O> automaton,
                                                          final Alphabet<I> input,
                                                          final SplitTree<S, I, O> node) {
  
          final Iterator<S> targetStateIterator = node.getPartition().iterator();
          final S s1 = targetStateIterator.next();
          final S s2 = targetStateIterator.next();
  
          final Word<I> separatingWord = Automata.findSeparatingWord(automaton, s1, s2, input);
  
          // sep word may be non existent, if current hypothesis is not consistent
          if (separatingWord == null) {
              return Optional.empty();
          }
  
          final Word<O> s1Output = automaton.computeStateOutput(s1, separatingWord);
          final Word<O> s2Output = automaton.computeStateOutput(s2, separatingWord);
          final Word<O> sharedOutput = s1Output.longestCommonPrefix(s2Output);
          final Word<I> trace = separatingWord.prefix(sharedOutput.length() + 1);
  
          final Pair<ADSNode<S, I, O>, ADSNode<S, I, O>> ads = ADSUtil.buildFromTrace(automaton, trace, s1);
  
          final ADSNode<S, I, O> head = ads.getFirst();
          final ADSNode<S, I, O> tail = ads.getSecond();
  
          final ADSNode<S, I, O> s1FinalNode = new ADSLeafNode<>(tail, node.getMapping().get(s1));
          final ADSNode<S, I, O> s2FinalNode = new ADSLeafNode<>(tail, node.getMapping().get(s2));
  
          tail.getChildren().put(s1Output.getSymbol(sharedOutput.length()), s1FinalNode);
          tail.getChildren().put(s2Output.getSymbol(sharedOutput.length()), s2FinalNode);
  
          return Optional.of(head);
      }
docs: See {@link #compute(MealyMachine, Alphabet, Set)}. Internal version, that uses the {@link SplitTree}
  representation.