code: package caevo.sieves;
  
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.List;
  
  import caevo.SieveDocument;
  import caevo.SieveDocuments;
  import caevo.TextEvent;
  import caevo.tlink.EventEventLink;
  import caevo.tlink.TLink;
  import caevo.util.CaevoProperties;
  
  /**
   * EventEventVagueSieve labels pairs of events as vague based on their tenses,
   * aspects, and classes.
   * 
   * It optionally does the following: - Label pairs of events vague if they both
   * have a class in {REPORTING, I_ACTION, I_STATE, PERCEPTION} - Or only look at
   * a subset of this set of classes - Label pairs of events vague if they have
   * the same tense - Label pairs of events vague if they have the same aspect -
   * Label pairs of events vague if they are in different sentences
   * 
   * The following table contains results considering subsets of these rules. A
   * row of this table corresponds to only considering some of the rules listed
   * above. ~X in the table means don't consider X (e.g. ~Aspect means Aspect
   * wasn't considered in labelling things vague). Class(X) means that the pair is
   * labelled vague if both events have class in X.
   * 
   * The default setting is to label pairs vague if they both have classes in
   * {REPORTING, I_STATE, PERCEPTION} and they share tense and aspect and are in
   * different sentences. The result for this setting is in the first row of the
   * table below. It gives decent precision and recall compared to other settings.
   * 
   * train-set dev-set Tense Aspect Sentence Class(All-I_ACTION) 0.74 (111 of 151)
   * 0.36 (16 of 44) Tense Aspect Sentence Class(I_ACTION) 0.55 (32 of 58) Tense
   * Aspect Sentence Class(I_STATE) 0.75 (27 of 36) Tense Aspect Sentence
   * Class(REPORTING) 0.71 (77 of 108) 0.29 (10 of 35) Tense Aspect Sentence
   * Class(PERCEPTION) 1.00 (7 of 7) Tense Aspect Sentence Class(All) 0.68 (143 of
   * 209) Tense Aspect ~Sentence Class(I_ACTION) 0.48 (45 of 94) Tense Aspect
   * ~Sentence Class(I_STATE) 0.72 (41 of 57) Tense Aspect ~Sentence
   * Class(REPORTING) 0.58 (87 of 149) Tense Aspect ~Sentence Class(PERCEPTION)
   * 0.88 (7 of 8) Tense Aspect ~Sentence Class(All) 0.58 (180 of 308) ~Tense
   * ~Aspect Sentence Class(I_ACTION) 0.61 (207 of 338) ~Tense ~Aspect Sentence
   * Class(I_STATE) 0.63 (105 of 167) ~Tense ~Aspect Sentence Class(REPORTING)
   * 0.57 (204 of 360) ~Tense ~Aspect Sentence Class(PERCEPTION) 0.79 (15 of 19)
   * ~Tense ~Aspect Sentence Class(All) 0.60 (531 of 884)
   * 
   * The change in precision from the train to the dev set suggests that at least
   * reporting verb pairs are labelled somewhat differently in the dev set.
   * 
   * @author Bill McDowell
   */
  public class EventEventVagueSieve implements Sieve {
    private List<TextEvent.Class> vagueClasses;
    private boolean considerTense;
    private boolean considerAspect;
    private boolean considerSentence;
  
    public EventEventVagueSieve() {
      this.vagueClasses = new ArrayList<TextEvent.Class>();
  
      try {
        if (CaevoProperties
            .getBoolean("EventEventVagueSieve.considerClassREPORTING", true))
          this.vagueClasses.add(TextEvent.Class.REPORTING);
        if (CaevoProperties
            .getBoolean("EventEventVagueSieve.considerClassI_STATE", true))
          this.vagueClasses.add(TextEvent.Class.I_STATE);
        if (CaevoProperties
            .getBoolean("EventEventVagueSieve.considerClassI_ACTION", false))
          this.vagueClasses.add(TextEvent.Class.I_ACTION);
        if (CaevoProperties
            .getBoolean("EventEventVagueSieve.considerClassPERCEPTION", true))
          this.vagueClasses.add(TextEvent.Class.PERCEPTION);
  
        this.considerTense = CaevoProperties
            .getBoolean("EventEventVagueSieve.considerTense", true);
        this.considerAspect = CaevoProperties
            .getBoolean("EventEventVagueSieve.considerAspect", true);
        this.considerSentence = CaevoProperties
            .getBoolean("EventEventVagueSieve.considerSentence", true);
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  
    public List<TLink> annotate(SieveDocument doc, List<TLink> currentTLinks) {
      List<TLink> proposed = new ArrayList<TLink>();
  
      List<TLink> sentencePairLinks = annotateBySentencePair(doc);
  
      if (sentencePairLinks != null)
        proposed.addAll(sentencePairLinks);
  
      return proposed;
    }
  
    public List<TLink> annotateBySentencePair(SieveDocument doc) {
      List<List<TextEvent>> sentenceEvents = doc.getEventsBySentence();
      List<TLink> proposed = new ArrayList<TLink>();
  
      for (int s = 0; s < sentenceEvents.size(); s++) {
        for (int e1 = 0; e1 < sentenceEvents.get(s).size(); e1++) {
          for (int e2 = e1 + 1; e2 < sentenceEvents.get(s).size(); e2++) {
            TLink link = this.orderEvents(sentenceEvents.get(s).get(e1),
                sentenceEvents.get(s).get(e2));
            if (link != null)
              proposed.add(link);
          }
  
          if (s + 1 < sentenceEvents.size()) {
            for (int t2 = 0; t2 < sentenceEvents.get(s + 1).size(); t2++) {
              TLink link = this.orderEvents(sentenceEvents.get(s).get(e1),
                  sentenceEvents.get(s + 1).get(t2));
              if (link != null)
                proposed.add(link);
            }
          }
        }
      }
  
      return proposed;
    }
  
    private TLink orderEvents(TextEvent event1, TextEvent event2) {
      if (this.vagueClasses.contains(event1.getTheClass())
          && this.vagueClasses.contains(event1.getTheClass())
          && (!this.considerTense || event1.getTense() == event2.getTense())
          && (!this.considerAspect || event1.getAspect() == event2.getAspect())
          && (!this.considerSentence || event1.getSid() != event2.getSid())) {
        return new EventEventLink(event1.getEiid(), event2.getEiid(),
            TLink.Type.VAGUE);
      } else {
        return null;
      }
    }
  
    /**
     * No training. Just rule-based.
     */
    public void train(SieveDocuments trainingInfo) {
      // no training
    }
  
  }