DefaultLexicalChainList.java 7.85 KB
package LIA_topic_seg;

import java.util.*;

/**
 * Cette classe prend en charge le calcul des liens lexicaux du texte chargé dans un objet de type DefaultInputData
 * Les paramètres de calcul sont intégrés dans la configuration. Ils concernent le type de hiatus utilisé, et le
 * type de représentation  du texte.
 * l'accès aux éléments décisif du texte se fait pour chaque lemme par un tableau qui indique à chaque phrase si il est 
 * présent ou non, et le poids (ou la présence) d'un lien lexical.
 */
public class DefaultLexicalChainList implements LexicalChainList
{
  int                      sentenceCount;
  LemmaDict                dict;
  DefaultConfig                   config;
  DefaultInputData                input;

  private static final int NO_HIATUS = 100;
  private static final int ADAPTIVE_HIATUS = 101;
  private static final int FIXED_HIATUS = 102;
  private int              _hiatus;
  private int              _hiatusValue;
  private boolean          _useWeight;
  private boolean          _computeChains;
  private ArrayList<Lemma> _lemmaList = new ArrayList<Lemma>();
  //--------------------------------------------------------------------------
  /**
   * Un Lemma est indique la répartition d'un lemme dans le texte, ainsi que la répartition et les
   * éventuelles pondération de ses liens lexicaux.
   * C'est cette classe qui se charge en réalité du calcul des liens lexicaux.
   */
  private class Lemma
  {
    private LemmaDict.Lemma _ll;
    boolean[] presenceInSentenceVect; // = new boolean[sentenceCount];
    float[]   weightInSentenceVect; // = new float[sentenceCount];
    //------------------------------------------------------------------------
    Lemma(LemmaDict.Lemma ll)
    {
      _ll = ll;
      presenceInSentenceVect = new boolean[sentenceCount];
      weightInSentenceVect   = new float[sentenceCount];
      Arrays.fill(presenceInSentenceVect, false);
      Arrays.fill(weightInSentenceVect, 0.0f);
      if (_hiatus == ADAPTIVE_HIATUS)
        _hiatusValue = ll.localHiatus();
      int previousSentenceIdx = -1;
      int sentenceIdx = 0;
      int chainLength = 1;
      int lemmasInChainCount = 0;
      int lemmaSentenceCount = ll.sentenceCount();

      for (int i=0; i<lemmaSentenceCount; i++)
      {
        sentenceIdx = ll.sentenceIdx(i);
        presenceInSentenceVect[sentenceIdx] = true;
        if (_computeChains)
        {
          if (previousSentenceIdx == -1)
            previousSentenceIdx = sentenceIdx;
          if (_hiatus == NO_HIATUS ||
              sentenceIdx-previousSentenceIdx <= _hiatusValue)
          {
            chainLength += sentenceIdx-previousSentenceIdx;
            lemmasInChainCount++;
          }
          else
          {
            setWeight(previousSentenceIdx, chainLength, lemmasInChainCount);
            chainLength = 1;
            lemmasInChainCount = 1;
          }
          previousSentenceIdx = sentenceIdx;
        }
      }
      if (_computeChains)
        setWeight(previousSentenceIdx, chainLength, lemmasInChainCount);
    }
    //------------------------------------------------------------------------
   /**
    * Cette fonction permet de pondérer un lien lexical en fonction de la densité des occurrences
    * du lemme, et du poids du lemme.
    * @param lastSentenceIdx : numéro de la phrase dans laquelle apparait la dernière occurrence
    * @param chainLength : longueur totale du lien lexical
    * @param lemmasInChainCount : nombre d'occurrences du lemme dans le llien lexical
    */
    void setWeight(int lastSentenceIdx, int chainLength, int lemmasInChainCount)
    {
      if (chainLength > 1)
      {
        float w = 1.0f;
        if (_useWeight)
           w = _ll.maxWeight * lemmasInChainCount
               * (float)Math.log((float)sentenceCount/(float)chainLength);
        for (int j=0; j<chainLength; j++)
          weightInSentenceVect[lastSentenceIdx-j] = w;
      }
    }
  }
  //--------------------------------------------------------------------------
  public DefaultLexicalChainList(DefaultInputData in)
  {
  	input  = in;
  	dict   = in.lemmaDict;
  	config = in.config;
    String s = config.getParam("computeChains");
    _useWeight = (s.equals("weight"));
    _computeChains = (s.equals("yes") || s.equals("weight"));
    String chains = config.getParam("lexicalChainsHiatus");
    if (chains.equals(""))
      _hiatus = NO_HIATUS;
    else if (chains.equals("ADAPTIVE"))
      _hiatus = ADAPTIVE_HIATUS;
    else
    {
      _hiatus = FIXED_HIATUS;
      _hiatusValue = Integer.parseInt(chains);
    }
  	sentenceCount = input.sentenceCount();

  	for (int i=0; i<dict.lemmaCount(); i++)
  	{
      LemmaDict.Lemma ll = dict.lemmaObject(i);
  	  // si le lemme est unique dans l'ensemble des phrases, on ne le garde pas
      if (_computeChains && ll.occurences < 2)
        continue;
      Lemma lemma = new Lemma(ll);
      if (true) // test ‡ quelles conditions on ajoute le lemme
        _lemmaList.add(lemma);
    }
  }
  //--------------------------------------------------------------------------
  /**
   * Cette fonction renvoie le code d'un lemme ayant un index donné
   * @param lemmaIdx : index du lemme
   * @return : le code du lemme
   */
  public int lemmaCode(int lemmaIdx)
  {
    return _lemmaList.get(lemmaIdx)._ll.code;
  }
  //--------------------------------------------------------------------------
  /**
   * Cette fonction renvoie le nombre total de lemmes ayant un lien lexical
   * @return : un nombre de lemmes
   */
  public int lemmaCount()
  {
    return _lemmaList.size();
  }
  //--------------------------------------------------------------------------
  /**
   * Cette fonction indique si un lemme donné est présent dans le texte initial dans une phrase donnée
   * @param lemmaIdx : index du lemme à tester
   * @param sentenceIdx : numéro de la phrase
   * @return true si le lemme est présent dans la phrase 
   * 		false sinon
   * 
   */
  public boolean presence(int lemmaIdx, int sentenceIdx)
  {
    return _lemmaList.get(lemmaIdx).presenceInSentenceVect[sentenceIdx];
  }
  //--------------------------------------------------------------------------
 /**
  * Cette fonction permet d'accéder au poids du lien lexical d'un lemme dans une phrase
  * @param lemmaIdx : index du lemme 
  * @param sentenceIdx : numéro de la phrase
  * @return : valeur du lien lexical du lemme dans la phrase si il y a un lien actif, 0 sinon
  */
  public float weight(int lemmaIdx, int sentenceIdx)
  {
    return _lemmaList.get(lemmaIdx).weightInSentenceVect[sentenceIdx];
  }
  //--------------------------------------------------------------------------
  /**
   * Cette fonction permet d'appeller toString (false, false), une version par défaut de l'affichage.
   */
  public String toString()
  {
  	return toString(false, false);
  }
  //--------------------------------------------------------------------------
  /**
   * Cette fonction permet de tester et d'afficher les liens lexicaux calculés
   * @param displayWeightZero : true pour affichier les poids même quand les liens sont absents
   * @param displaySentenceContent : truc pour afficher le texte initial
   * 
   */
  public String toString(boolean displayWeightZero,
                         boolean displaySentenceContent)
  {
    java.io.StringWriter w = new java.io.StringWriter();
    w.write(super.toString()+"\n");
    for (int i=0; i<_lemmaList.size(); i++)
    {
      w.write("LEMMA #"+i
       +" code("+lemmaCode(i)+")"
       +" content("+dict.lemmaObject(lemmaCode(i)).content+")"
       +"\n");
      for (int sent=0; sent<sentenceCount; sent++)
        if (weight(i, sent) != 0.0f || displayWeightZero)
        {
          w.write("  SENTENCE #"+sent
           +" presence("+presence(i,sent)+")"
           +" weight("+weight(i, sent)+")");
          if (displaySentenceContent)
            w.write(" content("+input.sentence(sent).content+")");
          w.write("\n");
        }
   }
    return w.toString();
  }
}