Package synalp.generation.jeni.semantics

Source Code of synalp.generation.jeni.semantics.SemanticsBuilder

package synalp.generation.jeni.semantics;

import java.util.*;

import synalp.commons.grammar.*;
import synalp.commons.input.Lemma;
import synalp.commons.lexicon.*;
import synalp.commons.semantics.Semantics;
import synalp.commons.unification.*;


/**
* Creates automatically the semantics of a grammar according to trace semantics, which are a way to
* associate a semantics to a given trace. The association is based on a naming convention for
* variables, ?F is the foot, ?R is the root, ?A is the anchor, ?S0..?Sn are substitutions.
* @author Alexandre Denis
*/
public class SemanticsBuilder
{
  private FamiliesSemantics familiesSemantics;


  /**
   * Creates a new SemanticsBuilder based on given FamilySemantics.
   * @param familiesSemantics
   */
  public SemanticsBuilder(FamiliesSemantics familiesSemantics)
  {
    this.familiesSemantics = familiesSemantics;
  }


  /**
   * Sets the semantics of all the entries of the given grammar.
   * @param grammar
   */
  public void setSemantics(Grammar grammar)
  {
    for(GrammarEntry entry : grammar.values())
      setSemantics(entry);
  }


  /**
   * Creates a SyntacticLexicon from families semantics and given Grammar.
   * It iterates through families, and for each pair lemma/tree, creates a lexicon entry.
   * @param grammar
   * @return a new SyntacticLexicon
   */
  public SyntacticLexicon createLexicon(Grammar grammar)
  {
    SyntacticLexicon ret = new SyntacticLexicon();
    for(FamilySemantics famSem : familiesSemantics)
    {
      if (famSem.getLemmas().isEmpty())
        continue;

      for(GrammarEntry entry : grammar.getEntriesContainingTrace(famSem.getTrace()))
      {
        // this is necessary to retrieve family-wide anchoring equations on families without explicit lemmas
        Equations familyWideEquations = new Equations();
        for(FamilySemantics otherSem : familiesSemantics)
          if (otherSem.getTrace().isSubTrace(entry.getTrace()))
            familyWideEquations.addAll(otherSem.getFamilyEquations());
       
        for(Lemma lemma : famSem.getLemmas().keySet())
        {
          // filter out entries with mismatching coanchors
          if (entry.getTree().getUninstantiatedCoanchors().size() != famSem.getCoanchors(lemma).size())
            continue;

          SyntacticLexiconEntry lexEntry = new SyntacticLexiconEntry();
          lexEntry.setFamilies(entry.getFamily());
          lexEntry.setLemma(lemma);

          // set filter
          FeatureStructure filter = new FeatureStructure();
          filter.addConstantFeature("family", new FeatureConstant(entry.getTrace()));
          lexEntry.setFilter(new Filter(filter));

          /*
           * set instantiated semantics, if the fam sem is a pattern use this semantics
           * else use normally the semantics of the entry
           */
          Semantics lexSemantics = new Semantics(famSem.isPattern() ? famSem.getSemantics() : entry.getSemantics());
          lexSemantics.instantiate(famSem.getLemmas().get(lemma));
          lexEntry.setSemantics(lexSemantics);

          /*
           * set all equations: the family-wide equations, the equations for the particular lemma and the co-anchor equations.
           * Note that the family equations are only set for famSem that have lemmas!
           */
          lexEntry.getEquations().addAll(familyWideEquations);
          lexEntry.getEquations().addAll(famSem.getEquations(lemma));
          setCoanchorEquations(lexEntry, entry, famSem, lemma);

          ret.add(lexEntry);
        }
      }
    }

    return ret;
  }


  /**
   * Adds co-anchor equations to the given lexicon entry. It retrieves the node id according to
   * the order in which they appear. Maybe here we have to take the canonical tree to assign the
   * coanchors. Or it is possible specify that in the input format.
   * @param lexEntry
   * @param entry
   * @param famSem
   * @param lemma
   */
  private void setCoanchorEquations(SyntacticLexiconEntry lexEntry, GrammarEntry entry, FamilySemantics famSem, Lemma lemma)
  {
    List<Lemma> coanchors = famSem.getCoanchors(lemma);
    if (!coanchors.isEmpty())
    {
      List<Node> coanchorNodes = entry.getTree().getNodesByType(NodeType.COANCHOR);
      for(int i = 0; i < coanchors.size(); i++)
      {
        Lemma coanchor = coanchors.get(i);
        Node coanchorNode = coanchorNodes.get(i);
        FeatureStructure fs = new FeatureStructure().addConstantFeature("lemma", coanchor.getValue());
        lexEntry.getEquations().add(new Equation(coanchorNode.getId(), FeatureStructureType.TOP, fs, true));
      }
    }
  }


  /**
   * Sets the semantics of the given entry automatically. This method clears the semantics of the
   * entry, sets its identifiers and defines its semantics by the most specific families semantics
   * whose trace match the entry trace.
   * @param entry
   */
  private void setSemantics(GrammarEntry entry)
  {
    clearSemantics(entry);
    setIdentifiers(entry);

    // first get all fam sem that are contained in the entry trace except for patterns
    List<FamilySemantics> matched = new ArrayList<FamilySemantics>();
    for(FamilySemantics famSem : familiesSemantics)
      if (!famSem.isPattern() && famSem.getTrace().isSubTrace(entry.getTrace()))
        matched.add(famSem);

    // removed fam sems that are subtraces of each other (keep the most specific)
    List<FamilySemantics> kept = new ArrayList<FamilySemantics>();
    for(FamilySemantics famSem1 : matched)
    {
      boolean found = false;
      for(FamilySemantics famSem2 : matched)
        if (famSem1 != famSem2 && famSem1.getTrace().isSubTrace(famSem2.getTrace()))
        {
          found = true;
          break;
        }
      if (!found)
        kept.add(famSem1);
    }

    // now gathers all kept trace sem in the semantics
    Semantics semantics = new Semantics();
    for(FamilySemantics famSem : kept)
      semantics.addAll(famSem.getSemantics());

    entry.setSemantics(semantics);
  }


  /**
   * Sets the identifiers of the given entry.
   * @param entry
   */
  public static void setIdentifiers(GrammarEntry entry)
  {
    int n = 0;
    boolean isAuxiliary = entry.getTree().isAuxiliary();
    for(Node node : entry.getTree().getNodes())
      if (node.isRoot())
      {
        if (isAuxiliary)
          setIdentifier(node, "?F"); // by default the root idx is the foot idx
        else setIdentifier(node, "?A"); // by default the root idx is the anchor idx
      }
      else if (node.isAnchor())
      {
        setIdentifier(node, "?A");
        setLemma(node);
      }
      else if (node.isFoot())
        setIdentifier(node, "?F");
      else if (node.isSubst())
        setIdentifier(node, "?S" + (n++));
  }


  /**
   * Sets a feature lemma=?L
   * @param node
   */
  private static void setLemma(Node node)
  {
    node.getFsTop().addVariableFeature("lemma", "?L");
    node.getFsBot().addVariableFeature("lemma", "?L");
  }


  private static void setIdentifier(Node node, String var)
  {
    node.getFsTop().addVariableFeature("idx", var);
    node.getFsBot().addVariableFeature("idx", var);
  }


  /**
   * Clears the semantics field of the given entry and all features in all nodes whose name is
   * "idx".
   * @param entry
   */
  public static void clearSemantics(GrammarEntry entry)
  {
    entry.setSemantics(new Semantics());
    for(Node node : entry.getTree().getNodes())
    {
      node.getFsTop().removeFeature("idx");
      node.getFsBot().removeFeature("idx");
    }
  }
}
TOP

Related Classes of synalp.generation.jeni.semantics.SemanticsBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.