/**
   * Writes the supplied learner evaluation configuration.
   *
   * @param cnf configuration to write
   * @return the recorded XML element
   */
  public Element writeLearnerEvaluationConfiguration(LearnerEvaluationConfiguration cnf) {
    Element evaluationData = doc.createElement(StatechumXML.ELEM_EVALUATIONDATA.name());
    evaluationData.appendChild(cnf.graph.storage.createGraphMLNode(doc));

    Element sequenceListElement =
        labelio.writeSequenceList(StatechumXML.ATTR_TESTSET.name(), cnf.testSet);
    evaluationData.appendChild(AbstractPersistence.endl(doc));
    evaluationData.appendChild(sequenceListElement);
    evaluationData.appendChild(AbstractPersistence.endl(doc));
    evaluationData.appendChild(cnf.config.writeXML(doc));
    evaluationData.appendChild(AbstractPersistence.endl(doc));
    if (cnf.ifthenSequences != null) {
      Element ltl = doc.createElement(StatechumXML.ELEM_CONSTRAINTS.name());
      StringBuffer ltlsequences = new StringBuffer();
      stringio.writeInputSequence(ltlsequences, cnf.ifthenSequences);
      ltl.setTextContent(ltlsequences.toString());
      evaluationData.appendChild(ltl);
      evaluationData.appendChild(AbstractPersistence.endl(doc));
    }
    if (cnf.labelDetails != null) {
      evaluationData.appendChild(cnf.labelDetails.storeToXML(doc, stringio));
      evaluationData.appendChild(AbstractPersistence.endl(doc));
    }
    if (cnf.graphNumber >= 0) {
      Element progressIndicatorElement =
          doc.createElement(StatechumXML.ELEM_PROGRESSINDICATOR.name());
      progressIndicatorElement.setAttribute(
          StatechumXML.ATTR_GRAPHNUMBER.name(), Integer.toString(cnf.graphNumber));
      evaluationData.appendChild(progressIndicatorElement);
    }
    return evaluationData;
  }
  /**
   * Data need to construct an experiment and evaluate the results. This is not a part of
   * <em>AbstractExperiment</em> because this is only for testing and hence one would only want to
   * record data from <b>some</b> experiments, not all of them.
   *
   * <p>If possible, this also loads the configuration and uses it for all methods requiring a
   * configuration. Unexpected elements are ignored.
   *
   * <p>{@link LearnerEvaluationConfiguration#labelConverter} is not assigned since it is a function
   * that is supposed to be set globally for an entire experiment.
   */
  public LearnerEvaluationConfiguration readLearnerEvaluationConfiguration(
      Element evaluationDataElement, Configuration defaultConfig) {
    if (!evaluationDataElement.getNodeName().equals(StatechumXML.ELEM_EVALUATIONDATA.name()))
      throw new IllegalArgumentException(
          "expecting to load learner evaluation data but found "
              + evaluationDataElement.getNodeName());
    NodeList
        nodesGraph =
            StatechumXML.getChildWithTag(
                evaluationDataElement, StatechumXML.graphmlNodeNameNS.toString()),
        nodesSequences =
            StatechumXML.getChildWithTag(evaluationDataElement, StatechumXML.ELEM_SEQ.name()),
        nodesLtl =
            StatechumXML.getChildWithTag(
                evaluationDataElement, StatechumXML.ELEM_CONSTRAINTS.name()),
        nodesConfigurations =
            StatechumXML.getChildWithTag(evaluationDataElement, Configuration.configXMLTag),
        graphNumberNodes =
            StatechumXML.getChildWithTag(
                evaluationDataElement, StatechumXML.ELEM_PROGRESSINDICATOR.name()),
        nodesLabelDetails =
            StatechumXML.getChildWithTag(
                evaluationDataElement, StatechumXML.ELEM_LABELDETAILS.name());
    if (nodesGraph.getLength() < 1) throw new IllegalArgumentException("missing graph");
    if (nodesGraph.getLength() > 1) throw new IllegalArgumentException("duplicate graph");
    if (nodesSequences.getLength() < 1) throw new IllegalArgumentException("missing test set");
    if (nodesSequences.getLength() > 1) throw new IllegalArgumentException("duplicate test set");
    if (nodesLtl.getLength() > 1) throw new IllegalArgumentException("duplicate ltl sets");
    if (nodesConfigurations.getLength() > 1)
      throw new IllegalArgumentException("duplicate configuration");
    if (nodesLabelDetails.getLength() > 1)
      throw new IllegalArgumentException("duplicate label details");
    int graphNumber = -1;
    if (graphNumberNodes.getLength() > 1)
      try {
        graphNumber =
            Integer.parseInt(
                ((Element) graphNumberNodes.item(0))
                    .getAttribute(StatechumXML.ATTR_GRAPHNUMBER.name()));
      } catch (Exception e) { // ignore - graphNumber is unchanged.
      }

    LearnerEvaluationConfiguration result = new LearnerEvaluationConfiguration(defaultConfig);
    if (nodesConfigurations.getLength() > 0) result.config.readXML(nodesConfigurations.item(0));

    initIO(evaluationDataElement.getOwnerDocument(), result.config);

    result.graph = new LearnerGraph(result.config);
    AbstractPersistence.loadGraph(
        (Element) nodesGraph.item(0), result.graph, decoratedLearner.getLabelConverter());

    result.testSet =
        labelio.readSequenceList(
            (Element) nodesSequences.item(0), StatechumXML.ATTR_TESTSET.name());
    if (nodesLtl.getLength() > 0)
      result.ifthenSequences = stringio.readInputSequence(nodesLtl.item(0).getTextContent());
    if (nodesLabelDetails.getLength() > 0) {
      result.labelDetails = new SmtLabelRepresentation(result.config, getLabelConverter());
      result.labelDetails.loadXML((Element) nodesLabelDetails.item(0), stringio);
    }
    result.graphNumber = graphNumber;
    return result;
  }