/**
   * Define a classification structure of the form P(A|B) = P(C)
   *
   * @param line
   */
  public void defineClassificationStructure(String line) {
    List<ParsedProbability> list = ParseProbability.parseProbabilityList(this, line);

    if (list.size() > 1) {
      throw new BayesianError("Must only define a single probability, not a chain.");
    }

    if (list.size() == 0) {
      throw new BayesianError("Must define at least one probability.");
    }

    // first define everything to be hidden
    for (BayesianEvent event : this.events) {
      this.query.defineEventType(event, EventType.Hidden);
    }

    // define the base event
    ParsedProbability prob = list.get(0);

    if (prob.getBaseEvents().size() == 0) {
      return;
    }

    BayesianEvent be = this.getEvent(prob.getChildEvent().getLabel());
    this.classificationTarget = this.events.indexOf(be);
    this.query.defineEventType(be, EventType.Outcome);

    // define the given events
    for (ParsedEvent parsedGiven : prob.getGivenEvents()) {
      BayesianEvent given = this.getEvent(parsedGiven.getLabel());
      this.query.defineEventType(given, EventType.Evidence);
    }

    this.query.locateEventTypes();

    // set the values
    for (ParsedEvent parsedGiven : prob.getGivenEvents()) {
      BayesianEvent event = this.getEvent(parsedGiven.getLabel());
      this.query.setEventValue(event, parseInt(parsedGiven.getValue()));
    }

    this.query.setEventValue(be, parseInt(prob.getBaseEvents().get(0).getValue()));
  }
  /**
   * Define the structure of the Bayesian network as a string.
   *
   * @param line The string to define events and relations.
   */
  public void setContents(String line) {
    List<ParsedProbability> list = ParseProbability.parseProbabilityList(this, line);
    List<String> labelList = new ArrayList<String>();

    // ensure that all events are there
    for (ParsedProbability prob : list) {
      ParsedEvent parsedEvent = prob.getChildEvent();
      String eventLabel = parsedEvent.getLabel();
      labelList.add(eventLabel);

      // create event, if not already here
      BayesianEvent e = getEvent(eventLabel);
      if (e == null) {
        List<BayesianChoice> cl = new ArrayList<BayesianChoice>();

        for (ParsedChoice c : parsedEvent.getList()) {
          cl.add(new BayesianChoice(c.getLabel(), c.getMin(), c.getMax()));
        }

        createEvent(eventLabel, cl);
      }
    }

    // now remove all events that were not covered
    for (int i = 0; i < events.size(); i++) {
      BayesianEvent event = this.events.get(i);
      if (!labelList.contains(event.getLabel())) {
        removeEvent(event);
      }
    }

    // handle dependencies
    for (ParsedProbability prob : list) {
      ParsedEvent parsedEvent = prob.getChildEvent();
      String eventLabel = parsedEvent.getLabel();

      BayesianEvent event = requireEvent(eventLabel);

      // ensure that all "givens" are present
      List<String> givenList = new ArrayList<String>();
      for (ParsedEvent given : prob.getGivenEvents()) {
        if (!event.hasGiven(given.getLabel())) {
          BayesianEvent givenEvent = requireEvent(given.getLabel());
          this.createDependency(givenEvent, event);
        }
        givenList.add(given.getLabel());
      }

      // now remove givens that were not covered
      for (int i = 0; i < event.getParents().size(); i++) {
        BayesianEvent event2 = event.getParents().get(i);
        if (!givenList.contains(event2.getLabel())) {
          removeDependency(event2, event);
        }
      }
    }

    // finalize the structure
    finalizeStructure();
    if (this.query != null) {
      this.query.finalizeStructure();
    }
  }