Package translation.tag_parser

Source Code of translation.tag_parser.Item

package translation.tag_parser;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import translation.trees.AuxType;
import translation.trees.ElementaryTree;
import translation.trees.GornAddress;
import translation.trees.LexicalNode;
import translation.trees.Node;
import translation.trees.NodeType;

public class Item {

  private ElementaryTree tree;
  private GornAddress dot; // adresse du noeud où se trouve le point
  private DotPos pos; // position du point par rapport au noeud
  private int startState;
  private Set<Item> contextItems;
  // addresses où une adjonction est en cours
  private List<GornAddress> halfAdjoinedAddr;
  private List<Item> halfAdjoinedItems; // items en cours d'adjonction

  public Item (ElementaryTree tree, GornAddress dot,
      DotPos pos, int startState) {
    this.tree = tree;
    this.dot = dot;
    this.pos = pos;
    this.startState = startState;
    this.contextItems = new HashSet<Item>();
    this.halfAdjoinedAddr = new ArrayList<GornAddress>(1);
    this.halfAdjoinedItems = new ArrayList<Item>(1);
  }

  public Item (ElementaryTree tree, GornAddress dot, DotPos pos,
      int startState, Set<Item> contextItems,
      List<Item> halfAdjoined, List<GornAddress> halfAdjoinedAddr) {
    this(tree, dot, pos, startState);
    this.contextItems = contextItems;
    this.halfAdjoinedItems = halfAdjoined;
    this.halfAdjoinedAddr = halfAdjoinedAddr;
  }


  private boolean raRoot() {
    return (getPos() == DotPos.RIGHT_ABOVE &&
        getDottedNode().isRoot());
  }

  /*      Gardes des règles      */

  /*
   * Décrit un item potentiellement "acceptant", qui
   * sera effectivement "acceptant" s'il n'y a plus de
   * mot à reconnaître en entrée, et alors l'analyse
   * réussit.
   *
   * Seuls les arbres initiaux, pas auxiliaires,
   * peuvent donner lieu à l'acceptation.
   *
   * Pour accepter même des phrases plus ou moins incomplètes,
   * il suffira de donner en argument à buildInitialItems
   * (qui est chargée de construire les arbres de départ
   * de l'état initial, qui correspondent aux phrases qui
   * seront acceptées) la liste des catégories de noeuds
   * traités comme racines de départ.
   */
  public boolean potentialAcceptationItem() {
    return raRoot() &&
    // l'arbre n'a ni été adjoint ni substitué,
    // il existe donc donc depuis le tout début
    // et correspond donc à une possible acceptation.
    contextItems.isEmpty();
  }

  public boolean canMoveDown() {
    return ((! getDottedNode().getSons().isEmpty()) &&
        getPos() == DotPos.LEFT_ABOVE);
  }

  public boolean canMoveRight() {
    return (getDottedNode().nextBrother() != null &&
        getPos() == DotPos.RIGHT_ABOVE);
  }

  /*
   * D'abord tester avec canMoveRight
   * si on peut se déplacer à droite.
   */
  public boolean canMoveUp() {
    return (getDottedNode().getFather() != null &&
        getPos() == DotPos.RIGHT_ABOVE);
  }

  public boolean canPredictSubst() {
    return (getDottedNode().isSubst() &&
        getPos() == DotPos.LEFT_ABOVE);
  }

  public boolean canCompleteSubst() {
    return (raRoot() &&
        (! getTree().isAuxiliary()) &&
        // le différentie d'un item potentiellement
        // acceptant.
        (! contextItems.isEmpty()));
  }

  /*
   * Aux noeuds lexicalisés et de substitution
   * on ne doit pas pouvoir adjoindre mais on
   * peut aux racines, ce qui revient au même que
   * si c'était aux noeuds de substitution mais qui
   * enlève de l'ambiguïté et donc des items inutiles.
   */
  public boolean canPredictLeftAdj() {
    return (getPos() == DotPos.LEFT_ABOVE &&
        // peut être le lieu d'une adjonction
        // d'arbre auxiliaire gauche ou enveloppant
        getDottedNode().isAdjAllowed() &&
        (! getTree().isAuxiliary()));
  }

  public boolean canExploreUnderFoot() {
    return (getPos() == DotPos.LEFT_ABOVE &&
        getDottedNode().getType() == NodeType.FOOT_TYPE);
  }

  public boolean canPredictNoLeftAdjToComplete() {
    return (halfAdjoinedAddr.isEmpty() &&
        getPos() == DotPos.RIGHT_BELOW &&
        // diffère avec canMoveToRightSubst
        (! getDottedNode().isSubst()));
  }

  public boolean canResumeAdj() {
    return ((! halfAdjoinedAddr.isEmpty()) &&
        getPos() == DotPos.RIGHT_BELOW &&
        // diffère avec canMoveToRightSubst
        lastHalfAdjAddr().equals(getDot()));
  }

  public boolean canCompleteLeftAdj() {
    return (raRoot() &&
        // diffère d'un item acceptant
        (getTree().getAuxType() == AuxType.LEFT_ADJTYPE));
  }

  public boolean canPredictRightAdj() {
    return (getPos() == DotPos.RIGHT_ABOVE &&
        getDottedNode().isAdjAllowed() &&
        (! getTree().isAuxiliary()));
  }

  public boolean canCompleteRightAdj() {
    return (raRoot() &&
        // diffère d'un item acceptant
        getTree().getAuxType() == AuxType.RIGHT_ADJTYPE);
  }


  /*      Règles     */

  /*
   * Règle appliquée sur un item tel que le point
   * est en bas à gauche d'un noeud qui a un fils,
   * elle ajoute un item avec le point en haut
   * à gauche de ce fils.
   */
  public Item moveDown() {
    Item it = this.clone();
    it.dot = dot.getSon(); // addr du 1er fils
    it.pos = DotPos.LEFT_ABOVE;
    return it;
  }

  public Item moveRight() {
    Item it = this.clone();
    it.dot = dot.getBrother(); // addr du 1er frère
    it.pos = DotPos.LEFT_ABOVE;
    return it;
  }

  public Item moveUp() {
    Item it = this.clone();
    it.dot = dot.getFather();
    it.pos = DotPos.RIGHT_BELOW;
    return it;
  }

  /*
   * Règle appliquée sur un item dont le point
   * est en bas à gauche d'un noeud de substitution.
   */
  public Set<Item> predictSubstituable(Set<ElementaryTree> sourceTrees,
      int currentStateNum) {
    Set<Item> newItems = new HashSet<Item>();

    for (ElementaryTree tree : sourceTrees)
      if (tree.getRootCat().equals(getDottedNode().getCat()) &&
          (! tree.isAuxiliary())) {
        Item it =
          new Item(tree, new GornAddress(),
              DotPos.LEFT_ABOVE, currentStateNum);
        it.addContextItem(this);
        newItems.add(it);
      }
    return newItems;
  }

  /*
   * Règle appliquée sur un item non acceptant dont
   * le point est en haut à droite de la racine d'un
   * arbre non auxiliaire. On remonte dans l'arbre
   * où a eu lieu la substitution.
   */
  public Set<Item> completeSubstitution() {
    Set<Item> newItems = new HashSet<Item>();

    for (Item parent : contextItems) { // un seul élément
      Item newItem = parent.clone();
      newItem.setPos(DotPos.RIGHT_ABOVE);
      newItems.add(newItem);

      //derivationTree.addToLeaf(it, newIt, DerivationType.SUBST);
      // DerivationNode n = new DerivationNode(newIt, ...);
      // chercher
      // ga : it.getDot(), tree : it.getTree()
      //
      //derivationTree.pruneDescendantsOf();
    }
    return newItems;
  }

  /*
   * Règle appliquée sur un item dont le point
   * est en haut à gauche d'un noeud où peut se
   * produire une adjonction, c-à-d. qui n'est
   * pas un noeud de substitution ni un noeud
   * lexical, et n'est pas d'un arbre auxiliaire.
   *
   * Quand cette règle est appliquée, moveDown
   * doit aussi l'être sur le même item, elle
   * représente le cas où aucune adjonction ne
   * se produit.
   *
   * On cherche les arbres auxiliaires dont la
   * racine est de même catégorie que le nœud
   * où peut avoir lieu l'adjonction.
   */
  public Set<Item> predictLeftAdjoinable(Set<ElementaryTree> sourceTrees,
      int currentStateNum) {
    Set<Item> newItems = new HashSet<Item>();

    for (ElementaryTree tree : sourceTrees)
      if (tree.getRootCat().equals(getDottedNode().getCat())
          && getTree().getAuxType() == AuxType.LEFT_ADJTYPE) {
        Item adjoinable =
          new Item(tree, new GornAddress(),
              DotPos.LEFT_ABOVE, currentStateNum);

        adjoinable.addContextItem(this);
        newItems.add(adjoinable);
      }
    return newItems;
  }

  /*
   * Règle appliquée sur un item dont le point
   * est en haut à gauche d'un noeud pied (dans
   * un arbre auxiliaire donc), lors d'une
   * adjonction gauche ou enveloppante.
   *
   * On revient dans l'arbre pointé où a commencé
   * l'adjonction de l'arbre auxiliaire, pour parcourir
   * ce qui se trouve sous son pied (jusqu'à revenir
   * au noeud pied pour repasser dans l'arbre adjoint).
   */
  public Set<Item> exploreUnderFoot() {
    Set<Item> newItems = new HashSet<Item>();

    for (Item parent : contextItems) {
      Item belowFoot = parent.clone();
      // On conserve dans les piles l'item où il
      // faudra revenir pour terminer l'adjonction
      // en cours et à quelle addresse elle a lieu.
      belowFoot.halfAdjoinedItems.add(this);
      belowFoot.halfAdjoinedAddr.add(belowFoot.getDot());
      // On ne modifie pas belowFoot.dot car on veut
      // rester en haut à gauche.
      newItems.add(belowFoot);
    }
    //TODO: peut-être le changer de place,
    //mettre dans resumeAdj juste avant addContextItem
    contextItems.clear();
    return newItems;
  }

  /*
   * Reprise de l'exploration de l'arbre auxiliaire
   * gauche (ou enveloppant) en cours d'adjonction,
   * plus précisément de sa partie droite.
   *
   * Règle appliquée quand on se trouve en bas à droite
   * d'un noeud dont l'adresse est en haut de la pile
   * halfAdjoinedAddr (indiquant qu'il reste au moins
   * une adjonction à terminer à ce noeud).
   *
   * Tout comme exploreUnderFoot, une telle règle
   * n'est pas nécessaire pour les adjonctions d'arbres
   * auxiliaires droits, en raison du sens d'exploration
   * des arbres (de gauche à droite).
   */
  public Item resumeAdj() {
    Item adjRightPart = lastHalfAdjItem().clone();
    adjRightPart.setPos(DotPos.RIGHT_ABOVE);
    // contextItems a été vidé au préalable
    // dans exploreUnderFoot
    adjRightPart.addContextItem(this);
    return adjRightPart;
  }

  /*
   * Règle appliquée quand le point est en haut à
   * droite de la racine dans un arbre auxiliaire
   * non accceptant.
   *
   * Deux cas sont possibles :
   * - soit il reste des adjonctions gauches à compléter
   * en ce noeud, auquel cas on reste en bas à droite du
   * noeud (dans l'arbre en-dessous du pied). C'est ce que
   * fait cette règle ;
   * - soit il n'y en a plus à ce noeud, et on met le
   * point en haut à droite (où peuvent se produire des
   * adjonctions d'arbres auxiliaires droits).
   *
   * Dans tous les cas on supprime de la pile des
   * adjonctions en cours celle que l'on vient de
   * terminer.
   */
  public Item completeLeftAdjunction() {
    Item newItem = null;

    for (Item context : contextItems) { // il n'y a qu'un élément
      newItem = context.clone();
      newItem.removeLastAdjRef();
    }
    return newItem;
  }

  /*
   * Règle appliquée quand il n'y a plus
   * d'adjonctions gauches à achever au
   * noeud auquel on est (positionné
   * en bas à droite).
   */
  public Item predictNoLeftAdjToComplete() {
    Item newItem = clone();
    newItem.pos = DotPos.RIGHT_ABOVE;
    return newItem;
  }

  /*
   * Les deux règles suivantes suffisent pour
   * les adjonctions droites. Pour remonter dans
   * l'arbre sans tenter d'autres adjonctions,
   * les méthodes moveRight et moveUp font
   * l'affaire.
   */
  public Set<Item> predictRightAdjoinable(Set<ElementaryTree> sourceTrees,
      int currentStateNum) {
    Set<Item> newItems = new HashSet<Item>();

    for (ElementaryTree tree : sourceTrees)
      if (tree.getRootCat().equals(getDottedNode().getCat())
          && tree.isAuxiliary()) {
        Item adjoinable =
          new Item(tree, tree.getFootAddr(),
              DotPos.RIGHT_ABOVE, currentStateNum);

        adjoinable.addContextItem(this);
        newItems.add(adjoinable);
      }
    return newItems;
  }

  public Item completeRightAdjunction() {
    Item newItem = null;
    for (Item context : contextItems) // il n'y a qu'un élément
      newItem = context.clone();
    return newItem;
  }


  /*
   * On ne peut remettre deux items égaux dans un
   * même état. En définissant l'égalité pour les
   * items, la méthode equals permet d'éviter
   * certaines boucles infinies d'opérations sur
   * les arbres ainsi que de ne pouvoir remonter
   * dans le contexte de l'opération dans certains
   * cas (comme les substitutions gauches en chaîne).
   */
  public boolean equals(Item it) {
    return (tree == it.tree  &&
        dot.equals(it.dot) &&
        pos == it.pos &&
        startState == it.startState &&
        contextItems.equals(it.contextItems) &&
        halfAdjoinedItems.equals(it.halfAdjoinedItems) &&
        halfAdjoinedAddr.equals(it.halfAdjoinedAddr));
  }

  /*
   * On utilise le même arbre et le même objet
   * GornAddress, pas besoin d'en instancier des clones.
   */
  public Item clone() {
    return new Item(tree, dot, pos, startState,
        contextItems, halfAdjoinedItems, halfAdjoinedAddr);
  }



  public Node getDottedNode() {
    return tree.findNode(dot);
  }

  public boolean dotAtLexNode() {
    return getDottedNode().isLex();
  }

  public String getWordAtDottedNode() {
    if (this.dotAtLexNode())
      return ((LexicalNode)getDottedNode()).getWord();
    else
      return null;
  }

  public void addContextItem(Item item) {
    contextItems.add(item);
  }

  public GornAddress lastHalfAdjAddr() {
    int lastIdx = halfAdjoinedAddr.size()-1;
    return halfAdjoinedAddr.get(lastIdx);
  }

  public Item lastHalfAdjItem() {
    int lastIdx = halfAdjoinedAddr.size()-1;
    return halfAdjoinedItems.get(lastIdx);
  }

  public void removeLastAdjRef() {
    int lastIdx = halfAdjoinedAddr.size()-1;
    halfAdjoinedItems.remove(lastIdx);
    halfAdjoinedAddr.remove(lastIdx);

  }


  public String toString() {
    String res =
      "[" + tree.getName() + ", "
      + dot.toString() + ", "
      + pos + ", "
      + startState + "]";
    return res;
  }

  public void print() {
    System.out.println(toString());
  }



  public ElementaryTree getTree() {
    return tree;
  }

  public GornAddress getDot() {
    return dot;
  }

  public DotPos getPos() {
    return pos;
  }

  public int getStartState() {
    return startState;
  }

  public void setTree(ElementaryTree newTree) {
    tree = newTree;
  }

  public void setDot(GornAddress newDot) {
    dot = newDot;
  }

  public void setPos(DotPos newPos) {
    pos = newPos;
  }

  public void setStartState(int startState) {
    this.startState = startState;
  }

  public void setContextItems(Set<Item> contextItems) {
    this.contextItems = contextItems;
  }

  public Set<Item> getContextItems() {
    return contextItems;
  }

  public void setHalfAdjoinedItems(List<Item> halfAdjoinedItems) {
    this.halfAdjoinedItems = halfAdjoinedItems;
  }

  public List<Item> getHalfAdjoinedItems() {
    return halfAdjoinedItems;
  }

}//class
TOP

Related Classes of translation.tag_parser.Item

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.