Logo Search packages:      
Sourcecode: beagle version File versions  Download package

BooleanScorer2.cs

/*
 * Copyright 2005 The Apache Software Foundation
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;

namespace Lucene.Net.Search
{
      
      /// <summary>An alternative to BooleanScorer.
      /// <br>Uses ConjunctionScorer, DisjunctionScorer, ReqOptScorer and ReqExclScorer.
      /// <br>Implements skipTo(), and has no limitations on the numbers of added scorers.
      /// </summary>
00026       class BooleanScorer2 : Scorer
      {
            private class AnonymousClassDisjunctionSumScorer : DisjunctionSumScorer
            {
                  private void  InitBlock(BooleanScorer2 enclosingInstance)
                  {
                        this.enclosingInstance = enclosingInstance;
                  }
                  private BooleanScorer2 enclosingInstance;
                  public BooleanScorer2 Enclosing_Instance
                  {
                        get
                        {
                              return enclosingInstance;
                        }
                        
                  }
                  internal AnonymousClassDisjunctionSumScorer(BooleanScorer2 enclosingInstance, System.Collections.IList Param1, int Param2):base(Param1, Param2)
                  {
                        InitBlock(enclosingInstance);
                  }
                  private int lastScoredDoc = - 1;
                  public override float Score()
                  {
                        if (Doc() > lastScoredDoc)
                        {
                              lastScoredDoc = Doc();
                              Enclosing_Instance.coordinator.nrMatchers += base.nrMatchers;
                        }
                        return base.Score();
                  }
            }

        private class AnonymousClassConjunctionScorer : ConjunctionScorer
            {
                  private void  InitBlock(int requiredNrMatchers, BooleanScorer2 enclosingInstance)
                  {
                        this.requiredNrMatchers = requiredNrMatchers;
                        this.enclosingInstance = enclosingInstance;
                  }
                  private int requiredNrMatchers;
                  private BooleanScorer2 enclosingInstance;

                  public BooleanScorer2 Enclosing_Instance
                  {
                        get
                        {
                              return enclosingInstance;
                        }
                        
                  }
                  internal AnonymousClassConjunctionScorer(int requiredNrMatchers, BooleanScorer2 enclosingInstance, Lucene.Net.Search.Similarity Param1):base(Param1)
                  {
                        InitBlock(requiredNrMatchers, enclosingInstance);
                  }
                  private int lastScoredDoc = - 1;
                  
                  public override float Score()
                  {
                        if (Doc() > lastScoredDoc)
                        {
                              lastScoredDoc = Doc();
                              Enclosing_Instance.coordinator.nrMatchers += requiredNrMatchers;
                        }
                        // All scorers match, so defaultSimilarity super.score() always has 1 as
                        // the coordination factor.
                        // Therefore the sum of the scores of the requiredScorers
                        // is used as score.
                        return base.Score();
                  }
            }
            private System.Collections.ArrayList requiredScorers = new System.Collections.ArrayList();
            private System.Collections.ArrayList optionalScorers = new System.Collections.ArrayList();
            private System.Collections.ArrayList prohibitedScorers = new System.Collections.ArrayList();
            
            
            private class Coordinator
            {
                  public Coordinator(BooleanScorer2 enclosingInstance)
                  {
                        InitBlock(enclosingInstance);
                  }
                  private void  InitBlock(BooleanScorer2 enclosingInstance)
                  {
                        this.enclosingInstance = enclosingInstance;
                  }
                  private BooleanScorer2 enclosingInstance;
                  public BooleanScorer2 Enclosing_Instance
                  {
                        get
                        {
                              return enclosingInstance;
                        }
                        
                  }
                  internal int maxCoord = 0; // to be increased for each non prohibited scorer
                  
                  private float[] coordFactors = null;
                  
                  internal virtual void  Init()
                  {
                        // use after all scorers have been added.
                        coordFactors = new float[maxCoord + 1];
                        Similarity sim = Enclosing_Instance.GetSimilarity();
                        for (int i = 0; i <= maxCoord; i++)
                        {
                              coordFactors[i] = sim.Coord(i, maxCoord);
                        }
                  }
                  
                  internal int nrMatchers; // to be increased by score() of match counting scorers.
                  
                  internal virtual void  InitDoc()
                  {
                        nrMatchers = 0;
                  }
                  
                  internal virtual float CoordFactor()
                  {
                        return coordFactors[nrMatchers];
                  }
            }
            
            private Coordinator coordinator;
            
            /// <summary>The scorer to which all scoring will be delegated,
            /// except for computing and using the coordination factor.
            /// </summary>
00154             private Scorer countingSumScorer = null;
            
            /// <summary>The number of optionalScorers that need to match (if there are any) </summary>
00157             private int minNrShouldMatch;
            
            /// <summary>Create a BooleanScorer2.</summary>
            /// <param name="similarity">The similarity to be used.
            /// </param>
            /// <param name="minNrShouldMatch">The minimum number of optional added scorers
            /// that should match during the search.
            /// In case no required scorers are added,
            /// at least one of the optional scorers will have to
            /// match during the search.
            /// </param>
00168             public BooleanScorer2(Similarity similarity, int minNrShouldMatch):base(similarity)
            {
                  if (minNrShouldMatch < 0)
                  {
                        throw new System.ArgumentException("Minimum number of optional scorers should not be negative");
                  }
                  coordinator = new Coordinator(this);
                  this.minNrShouldMatch = minNrShouldMatch;
            }
            
            /// <summary>Create a BooleanScorer2.
            /// In no required scorers are added,
            /// at least one of the optional scorers will have to match during the search.
            /// </summary>
            /// <param name="similarity">The similarity to be used.
            /// </param>
00184             public BooleanScorer2(Similarity similarity) : this(similarity, 0)
            {
            }
            
            public virtual void  Add(Scorer scorer, bool required, bool prohibited)
            {
                  if (!prohibited)
                  {
                        coordinator.maxCoord++;
                  }
                  
                  if (required)
                  {
                        if (prohibited)
                        {
                              throw new System.ArgumentException("scorer cannot be required and prohibited");
                        }
                        requiredScorers.Add(scorer);
                  }
                  else if (prohibited)
                  {
                        prohibitedScorers.Add(scorer);
                  }
                  else
                  {
                        optionalScorers.Add(scorer);
                  }
            }
            
            /// <summary>Initialize the match counting scorer that sums all the
            /// scores. <p>
            /// When "counting" is used in a name it means counting the number
            /// of matching scorers.<br>
            /// When "sum" is used in a name it means score value summing
            /// over the matching scorers
            /// </summary>
00220             private void  InitCountingSumScorer()
            {
                  coordinator.Init();
                  countingSumScorer = MakeCountingSumScorer();
            }
            
            /// <summary>Count a scorer as a single match. </summary>
00227             private class SingleMatchScorer : Scorer
            {
                  private void  InitBlock(BooleanScorer2 enclosingInstance)
                  {
                        this.enclosingInstance = enclosingInstance;
                  }
                  private BooleanScorer2 enclosingInstance;
                  public BooleanScorer2 Enclosing_Instance
                  {
                        get
                        {
                              return enclosingInstance;
                        }
                        
                  }
                  private Scorer scorer;
                  private int lastScoredDoc = - 1;
                  
                  internal SingleMatchScorer(BooleanScorer2 enclosingInstance, Scorer scorer) : base(scorer.GetSimilarity())
                  {
                        InitBlock(enclosingInstance);
                        this.scorer = scorer;
                  }
00250                   public override float Score()
                  {
                        if (Doc() > lastScoredDoc)
                        {
                              lastScoredDoc = Doc();
                              Enclosing_Instance.coordinator.nrMatchers++;
                        }
                        return scorer.Score();
                  }
00259                   public override int Doc()
                  {
                        return scorer.Doc();
                  }
00263                   public override bool Next()
                  {
                        return scorer.Next();
                  }
00267                   public override bool SkipTo(int docNr)
                  {
                        return scorer.SkipTo(docNr);
                  }
00271                   public override Explanation Explain(int docNr)
                  {
                        return scorer.Explain(docNr);
                  }
            }
            
            private Scorer CountingDisjunctionSumScorer(System.Collections.IList scorers, int minMrShouldMatch)
            // each scorer from the list counted as a single matcher
            {
                  return new AnonymousClassDisjunctionSumScorer(this, scorers, minMrShouldMatch);
            }
            
            private static Similarity defaultSimilarity = new DefaultSimilarity();
            
            private Scorer CountingConjunctionSumScorer(System.Collections.IList requiredScorers)
            {
                  // each scorer from the list counted as a single matcher
                  int requiredNrMatchers = requiredScorers.Count;
                  ConjunctionScorer cs = new AnonymousClassConjunctionScorer(requiredNrMatchers, this, defaultSimilarity);
                  System.Collections.IEnumerator rsi = requiredScorers.GetEnumerator();
                  while (rsi.MoveNext())
                  {
                        cs.Add((Scorer) rsi.Current);
                  }
                  return cs;
            }
            
            private Scorer DualConjunctionSumScorer(Scorer req1, Scorer req2)
            {
                  // non counting. 
                  //UPGRADE_NOTE: Final was removed from the declaration of 'requiredNrMatchers '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                  int requiredNrMatchers = requiredScorers.Count;
                  ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity);
                  // All scorers match, so defaultSimilarity super.score() always has 1 as
                  // the coordination factor.
                  // Therefore the sum of the scores of two scorers
                  // is used as score.
                  cs.Add(req1);
                  cs.Add(req2);
                  return cs;
            }
            
            /// <summary>Returns the scorer to be used for match counting and score summing.
            /// Uses requiredScorers, optionalScorers and prohibitedScorers.
            /// </summary>
00316             private Scorer MakeCountingSumScorer()
            {
                  // each scorer counted as a single matcher
                  return (requiredScorers.Count == 0)?MakeCountingSumScorerNoReq():MakeCountingSumScorerSomeReq();
            }
            
            private Scorer MakeCountingSumScorerNoReq()
            {
                  // No required scorers
                  if (optionalScorers.Count == 0)
                  {
                        return new NonMatchingScorer(); // no clauses or only prohibited clauses
                  }
                  else
                  {
                        // No required scorers. At least one optional scorer.
                        // minNrShouldMatch optional scorers are required, but at least 1
                        int nrOptRequired = (minNrShouldMatch < 1)?1:minNrShouldMatch;
                        if (optionalScorers.Count < nrOptRequired)
                        {
                              return new NonMatchingScorer(); // fewer optional clauses than minimum (at least 1) that should match
                        }
                        else
                        {
                              // optionalScorers.size() >= nrOptRequired, no required scorers
                              Scorer requiredCountingSumScorer = (optionalScorers.Count > nrOptRequired)?CountingDisjunctionSumScorer(optionalScorers, nrOptRequired):((optionalScorers.Count == 1)?new SingleMatchScorer(this, (Scorer) optionalScorers[0]):CountingConjunctionSumScorer(optionalScorers));
                              return AddProhibitedScorers(requiredCountingSumScorer);
                        }
                  }
            }
            
            private Scorer MakeCountingSumScorerSomeReq()
            {
                  // At least one required scorer.
                  if (optionalScorers.Count < minNrShouldMatch)
                  {
                        return new NonMatchingScorer(); // fewer optional clauses than minimum that should match
                  }
                  else if (optionalScorers.Count == minNrShouldMatch)
                  {
                        // all optional scorers also required.
                        System.Collections.ArrayList allReq = new System.Collections.ArrayList(requiredScorers);
                        allReq.AddRange(optionalScorers);
                        return AddProhibitedScorers(CountingConjunctionSumScorer(allReq));
                  }
                  else
                  {
                        // optionalScorers.size() > minNrShouldMatch, and at least one required scorer
                        Scorer requiredCountingSumScorer = (requiredScorers.Count == 1)?new SingleMatchScorer(this, (Scorer) requiredScorers[0]):CountingConjunctionSumScorer(requiredScorers);
                        if (minNrShouldMatch > 0)
                        {
                              // use a required disjunction scorer over the optional scorers
                              return AddProhibitedScorers(DualConjunctionSumScorer(requiredCountingSumScorer, CountingDisjunctionSumScorer(optionalScorers, minNrShouldMatch)));
                        }
                        else
                        {
                              // minNrShouldMatch == 0
                              return new ReqOptSumScorer(AddProhibitedScorers(requiredCountingSumScorer), ((optionalScorers.Count == 1)?new SingleMatchScorer(this, (Scorer) optionalScorers[0]):CountingDisjunctionSumScorer(optionalScorers, 1))); // require 1 in combined, optional scorer.
                        }
                  }
            }
            
            /// <summary>Returns the scorer to be used for match counting and score summing.
            /// Uses the given required scorer and the prohibitedScorers.
            /// </summary>
            /// <param name="requiredCountingSumScorer">A required scorer already built.
            /// </param>
00383             private Scorer AddProhibitedScorers(Scorer requiredCountingSumScorer)
            {
                  return (prohibitedScorers.Count == 0)?requiredCountingSumScorer:new ReqExclScorer(requiredCountingSumScorer, ((prohibitedScorers.Count == 1)?(Scorer) prohibitedScorers[0]:new DisjunctionSumScorer(prohibitedScorers)));
            }
            
            /// <summary>Scores and collects all matching documents.</summary>
            /// <param name="hc">The collector to which all matching documents are passed through
            /// {@link HitCollector#Collect(int, float)}.
            /// <br>When this method is used the {@link #Explain(int)} method should not be used.
            /// </param>
00393             public override void  Score(HitCollector hc)
            {
                  if (countingSumScorer == null)
                  {
                        InitCountingSumScorer();
                  }
                  while (countingSumScorer.Next())
                  {
                        hc.Collect(countingSumScorer.Doc(), Score());
                  }
            }
            
            /// <summary>Expert: Collects matching documents in a range.
            /// <br>Note that {@link #Next()} must be called once before this method is
            /// called for the first time.
            /// </summary>
            /// <param name="hc">The collector to which all matching documents are passed through
            /// {@link HitCollector#Collect(int, float)}.
            /// </param>
            /// <param name="max">Do not score documents past this.
            /// </param>
            /// <returns> true if more matching documents may remain.
            /// </returns>
00416             protected internal override bool Score(HitCollector hc, int max)
            {
                  // null pointer exception when Next() was not called before:
                  int docNr = countingSumScorer.Doc();
                  while (docNr < max)
                  {
                        hc.Collect(docNr, Score());
                        if (!countingSumScorer.Next())
                        {
                              return false;
                        }
                        docNr = countingSumScorer.Doc();
                  }
                  return true;
            }
            
00432             public override int Doc()
            {
                  return countingSumScorer.Doc();
            }
            
00437             public override bool Next()
            {
                  if (countingSumScorer == null)
                  {
                        InitCountingSumScorer();
                  }
                  return countingSumScorer.Next();
            }
            
00446             public override float Score()
            {
                  coordinator.InitDoc();
                  float sum = countingSumScorer.Score();
                  return sum * coordinator.CoordFactor();
            }
            
            /// <summary>Skips to the first match beyond the current whose document number is
            /// greater than or equal to a given target.
            /// 
            /// <p>When this method is used the {@link #Explain(int)} method should not be used.
            /// 
            /// </summary>
            /// <param name="target">The target document number.
            /// </param>
            /// <returns> true iff there is such a match.
            /// </returns>
00463             public override bool SkipTo(int target)
            {
                  if (countingSumScorer == null)
                  {
                        InitCountingSumScorer();
                  }
                  return countingSumScorer.SkipTo(target);
            }
            
            /// <summary>Throws an UnsupportedOperationException.
            /// TODO: Implement an explanation of the coordination factor.
            /// </summary>
            /// <param name="doc">The document number for the explanation.
            /// </param>
            /// <throws>  UnsupportedOperationException </throws>
00478             public override Explanation Explain(int doc)
            {
                  throw new System.NotSupportedException();
                  /* How to explain the coordination factor?
                  initCountingSumScorer();
                  return countingSumScorer.explain(doc); // misses coord factor. 
                  */
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index