예제 #1
0
  private double getScoreBM25(RetrievalModel r) throws IOException {
    if (!this.docIteratorHasMatchCache()) {
      return 0d;
    } else {
      Map<Qry, Integer> queryMap = new HashMap<>();
      for (Qry arg : this.args) {
        int num = queryMap.getOrDefault(arg, 0) + 1;
        queryMap.put(arg, num);
      }

      countingSetup();

      double totalScore = 0d;
      for (Qry curArg : queryMap.keySet()) {
        int curQryFreq = queryMap.get(curArg);
        int docid = this.docIteratorGetMatch();
        if (!curArg.docIteratorHasMatch(r) || docid != curArg.docIteratorGetMatch()) {
          // nothing match , curscore = 0;
          continue;
        } else {
          totalScore += ((QrySop) curArg).getScore(r);
        } // end of else
      } // end of for loop
      return totalScore;
    }
  }
예제 #2
0
  /**
   * Advance the internal document iterator to the specified document, or beyond if it doesn't.
   *
   * @param docid An internal document id.
   */
  public void docIteratorAdvanceTo(int docid) {

    for (Qry q_i : this.args) {
      q_i.docIteratorAdvanceTo(docid);
    }

    this.docIteratorClearMatchCache();
  }
예제 #3
0
  /**
   * An instantiation of docIteratorHasMatch that is true if the query has a document that matches
   * the first query argument; some subclasses may choose to use this implementation.
   *
   * @param r The retrieval model that determines what is a match
   * @return True if the query matches, otherwise false.
   */
  protected boolean docIteratorHasMatchFirst(RetrievalModel r) {

    Qry q_0 = this.args.get(0);

    if (q_0.docIteratorHasMatch(r)) {
      int docid = q_0.docIteratorGetMatch();
      this.docIteratorSetMatchCache(docid);
      return true;
    } else {
      return false;
    }
  }
예제 #4
0
  /**
   * An instantiation of docIteratorHasMatch that is true if the query has a document that matches
   * all query arguments; some subclasses may choose to use this implementation.
   *
   * @param r The retrieval model that determines what is a match
   * @return True if the query matches, otherwise false.
   */
  protected boolean docIteratorHasMatchAll(RetrievalModel r) {

    boolean matchFound = false;

    // Keep trying until a match is found or no match is possible.

    while (!matchFound) {

      // Get the docid of the first query argument.

      Qry q_0 = this.args.get(0);

      if (!q_0.docIteratorHasMatch(r)) {
        return false;
      }

      int docid_0 = q_0.docIteratorGetMatch();

      // Other query arguments must match the docid of the first query
      // argument.

      matchFound = true;

      for (int i = 1; i < this.args.size(); i++) {
        Qry q_i = this.args.get(i);

        q_i.docIteratorAdvanceTo(docid_0);

        if (!q_i.docIteratorHasMatch(r)) { // If any argument is exhausted
          return false; // there are no more matches.
        }

        int docid_i = q_i.docIteratorGetMatch();

        if (docid_0 != docid_i) { // docid_0 can't match.  Try again.
          q_0.docIteratorAdvanceTo(docid_i);
          matchFound = false;
          break;
        }
      }

      if (matchFound) {
        docIteratorSetMatchCache(docid_0);
      }
    }

    return true;
  }
예제 #5
0
  /**
   * An instantiation of docIteratorHasMatch that is true if the query has a document that matches
   * at least one query argument; the match is the smallest docid to match; some subclasses may
   * choose to use this implementation.
   *
   * @param r The retrieval model that determines what is a match
   * @return True if the query matches, otherwise false.
   */
  protected boolean docIteratorHasMatchMin(RetrievalModel r) {

    int minDocid = Qry.INVALID_DOCID;

    for (int i = 0; i < this.args.size(); i++) {
      Qry q_i = this.args.get(i);

      if (q_i.docIteratorHasMatch(r)) {
        int q_iDocid = q_i.docIteratorGetMatch();

        if ((minDocid > q_iDocid) || (minDocid == Qry.INVALID_DOCID)) {
          minDocid = q_iDocid;
        }
      }
    }

    if (minDocid != Qry.INVALID_DOCID) {
      docIteratorSetMatchCache(minDocid);
      return true;
    } else {
      return false;
    }
  }
예제 #6
0
 /**
  * Initialize the query operator (and its arguments), including any internal iterators. If the
  * query operator is of type QryIop, it is fully evaluated, and the results are stored in an
  * internal inverted list that may be accessed via the internal iterator.
  *
  * @param r A retrieval model that guides initialization
  * @throws IOException Error accessing the Lucene index.
  */
 public void initialize(RetrievalModel r) throws IOException {
   for (Qry q_i : this.args) {
     q_i.initialize(r);
   }
 }
예제 #7
0
  /**
   * Append an argument to the list of query operator arguments.
   *
   * @param q The query argument (query operator) to append.
   * @throws IllegalArgumentException q is an invalid argument
   */
  public void appendArg(Qry q) throws IllegalArgumentException {

    //  The query parser and query operator type system are too simple
    //  to detect some kinds of query syntax errors.  appendArg does
    //  additional syntax checking while creating the query tree.  It
    //  also inserts SCORE operators between QrySop operators and QryIop
    //  arguments, and propagates field information from QryIop
    //  children to parents.  Basically, it creates a well-formed
    //  query tree.

    if (this instanceof QryIopTerm) {
      throw new IllegalArgumentException("The TERM operator has no arguments.");
    }

    //  SCORE operators can have only a single argument of type QryIop.

    if (this instanceof QrySopScore) {
      if (this.args.size() > 0) {
        throw new IllegalArgumentException("Score operators can have only one argument");
      } else if (!(q instanceof QryIop)) {
        throw new IllegalArgumentException(
            "The argument to a SCORE operator must be of type QryIop.");
      } else {
        this.args.add(q);
        return;
      }
    }

    //  Check whether it is necessary to insert an implied SCORE
    //  operator between a QrySop operator and a QryIop argument.

    if ((this instanceof QrySop) && (q instanceof QryIop)) {
      Qry impliedOp = new QrySopScore();
      impliedOp.setDisplayName("#SCORE");
      impliedOp.appendArg(q);
      this.args.add(impliedOp);
      return;
    }

    //  QryIop operators must have QryIop arguments in the same field.

    if ((this instanceof QryIop) && (q instanceof QryIop)) {

      if (this.args.size() == 0) {
        ((QryIop) this).field = new String(((QryIop) q).getField());
      } else {
        if (!((QryIop) this).field.equals(((QryIop) q).getField())) {
          throw new IllegalArgumentException(
              "Arguments to QryIop operators must be in the same field.");
        }
      }

      this.args.add(q);
      return;
    }

    //  QrySop operators and their arguments must be of the same type.

    if ((this instanceof QrySop) && (q instanceof QrySop)) {
      this.args.add(q);
      return;
    }

    throw new IllegalArgumentException(
        "Objects of type "
            + q.getClass().getName()
            + " cannot be an argument to a query operator of type "
            + this.getClass().getName());
  }
예제 #8
0
  /**
   * Initialize the query operator (and its arguments), including any internal iterators. If the
   * query operator is of type QryIop, it is fully evaluated, and the results are stored in an
   * internal inverted list that may be accessed via the internal iterator.
   *
   * @param r A retrieval model that guides initialization
   * @throws IOException Error accessing the Lucene index.
   */
  public void initialize(RetrievalModel r) throws IOException {

    Qry q = this.args.get(0);
    q.initialize(r);
  }
예제 #9
0
  @Override
  protected void evaluate() throws IOException {

    this.invertedList = new InvList(this.getField());
    // no argument
    if (args.size() == 0) return;
    if (args.size() == 1) {
      this.invertedList = ((QryIop) this.args.get(0)).invertedList;
      return;
    }

    // iterate each doc, greedy algorithms
    while (true) {
      //  init doc_id
      int doc_id = Qry.INVALID_DOCID;

      if (this.docIteratorHasMatchAll(null)) doc_id = this.args.get(0).docIteratorGetMatch();
      // fail to find a match all
      if (doc_id == Qry.INVALID_DOCID) break;
      // the last argument's position in doc
      List<Integer> positions = new ArrayList<Integer>();

      // iterate each location
      while (true) {
        boolean success = false;
        int position = 0;

        // index from 1 to n-1
        for (int i = 1; i < this.args.size(); i++) {
          // get previous pos
          if (!((QryIop) this.args.get(i - 1)).locIteratorHasMatch()) break;
          int position1 = ((QryIop) this.args.get(i - 1)).locIteratorGetMatch();

          // go beyond pre pos
          ((QryIop) this.args.get(i)).locIteratorAdvancePast(position1);
          if (!((QryIop) this.args.get(i)).locIteratorHasMatch()) break;
          int position2 = ((QryIop) this.args.get(i)).locIteratorGetMatch();

          // near condition satisfied?
          if (position2 > position1 && position2 - position1 <= this.dist) {
            position = position2;
            if (i == this.args.size() - 1) success = true;
          } else {
            success = false;
            break;
          }
        }

        // find a legal position
        if (success) {
          positions.add(position);
          // move each loc pointer
          for (Qry q_i : this.args) {
            ((QryIop) q_i).locIteratorAdvance();
          }
        } else {
          // move first arg
          ((QryIop) this.args.get(0)).locIteratorAdvance();
          // if no more match position for the first arg
          if (!((QryIop) this.args.get(0)).locIteratorHasMatch()) break;
          // reset other pointers to beginning
          for (int i = 1; i < this.args.size(); i++) {
            ((QryIop) this.args.get(i)).locIteratorReset();
            int preposition = ((QryIop) this.args.get(0)).locIteratorGetMatch();
            ((QryIop) this.args.get(i)).locIteratorAdvancePast(preposition);
          }
        }
      }

      // move doc pointer
      for (Qry q_i : this.args) q_i.docIteratorAdvancePast(doc_id);
      // success
      if (positions.size() > 0) this.invertedList.appendPosting(doc_id, positions);
    }
  }