BooleanScorer2.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:15k
源码类别:

搜索引擎

开发平台:

C#

  1. /*
  2.  * Copyright 2005 The Apache Software Foundation
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  * 
  8.  * http://www.apache.org/licenses/LICENSE-2.0
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16. using System;
  17. namespace Lucene.Net.Search
  18. {
  19. /// <summary>An alternative to BooleanScorer.
  20. /// <br>Uses ConjunctionScorer, DisjunctionScorer, ReqOptScorer and ReqExclScorer.
  21. /// <br>Implements skipTo(), and has no limitations on the numbers of added scorers.
  22. /// </summary>
  23. class BooleanScorer2 : Scorer
  24. {
  25. private class AnonymousClassDisjunctionSumScorer : DisjunctionSumScorer
  26. {
  27. private void  InitBlock(BooleanScorer2 enclosingInstance)
  28. {
  29. this.enclosingInstance = enclosingInstance;
  30. }
  31. private BooleanScorer2 enclosingInstance;
  32. public BooleanScorer2 Enclosing_Instance
  33. {
  34. get
  35. {
  36. return enclosingInstance;
  37. }
  38. }
  39. internal AnonymousClassDisjunctionSumScorer(BooleanScorer2 enclosingInstance, System.Collections.IList Param1, int Param2):base(Param1, Param2)
  40. {
  41. InitBlock(enclosingInstance);
  42. }
  43. private int lastScoredDoc = - 1;
  44. public override float Score()
  45. {
  46. if (Doc() > lastScoredDoc)
  47. {
  48. lastScoredDoc = Doc();
  49. Enclosing_Instance.coordinator.nrMatchers += base.nrMatchers;
  50. }
  51. return base.Score();
  52. }
  53. }
  54.         private class AnonymousClassConjunctionScorer : ConjunctionScorer
  55. {
  56. private void  InitBlock(int requiredNrMatchers, BooleanScorer2 enclosingInstance)
  57. {
  58. this.requiredNrMatchers = requiredNrMatchers;
  59. this.enclosingInstance = enclosingInstance;
  60. }
  61. private int requiredNrMatchers;
  62. private BooleanScorer2 enclosingInstance;
  63. public BooleanScorer2 Enclosing_Instance
  64. {
  65. get
  66. {
  67. return enclosingInstance;
  68. }
  69. }
  70. internal AnonymousClassConjunctionScorer(int requiredNrMatchers, BooleanScorer2 enclosingInstance, Lucene.Net.Search.Similarity Param1):base(Param1)
  71. {
  72. InitBlock(requiredNrMatchers, enclosingInstance);
  73. }
  74. private int lastScoredDoc = - 1;
  75. public override float Score()
  76. {
  77. if (Doc() > lastScoredDoc)
  78. {
  79. lastScoredDoc = Doc();
  80. Enclosing_Instance.coordinator.nrMatchers += requiredNrMatchers;
  81. }
  82. // All scorers match, so defaultSimilarity super.score() always has 1 as
  83. // the coordination factor.
  84. // Therefore the sum of the scores of the requiredScorers
  85. // is used as score.
  86. return base.Score();
  87. }
  88. }
  89. private System.Collections.ArrayList requiredScorers = new System.Collections.ArrayList();
  90. private System.Collections.ArrayList optionalScorers = new System.Collections.ArrayList();
  91. private System.Collections.ArrayList prohibitedScorers = new System.Collections.ArrayList();
  92. private class Coordinator
  93. {
  94. public Coordinator(BooleanScorer2 enclosingInstance)
  95. {
  96. InitBlock(enclosingInstance);
  97. }
  98. private void  InitBlock(BooleanScorer2 enclosingInstance)
  99. {
  100. this.enclosingInstance = enclosingInstance;
  101. }
  102. private BooleanScorer2 enclosingInstance;
  103. public BooleanScorer2 Enclosing_Instance
  104. {
  105. get
  106. {
  107. return enclosingInstance;
  108. }
  109. }
  110. internal int maxCoord = 0; // to be increased for each non prohibited scorer
  111. private float[] coordFactors = null;
  112. internal virtual void  Init()
  113. {
  114. // use after all scorers have been added.
  115. coordFactors = new float[maxCoord + 1];
  116. Similarity sim = Enclosing_Instance.GetSimilarity();
  117. for (int i = 0; i <= maxCoord; i++)
  118. {
  119. coordFactors[i] = sim.Coord(i, maxCoord);
  120. }
  121. }
  122. internal int nrMatchers; // to be increased by score() of match counting scorers.
  123. internal virtual void  InitDoc()
  124. {
  125. nrMatchers = 0;
  126. }
  127. internal virtual float CoordFactor()
  128. {
  129. return coordFactors[nrMatchers];
  130. }
  131. }
  132. private Coordinator coordinator;
  133. /// <summary>The scorer to which all scoring will be delegated,
  134. /// except for computing and using the coordination factor.
  135. /// </summary>
  136. private Scorer countingSumScorer = null;
  137. /// <summary>The number of optionalScorers that need to match (if there are any) </summary>
  138. private int minNrShouldMatch;
  139. /// <summary>Create a BooleanScorer2.</summary>
  140. /// <param name="similarity">The similarity to be used.
  141. /// </param>
  142. /// <param name="minNrShouldMatch">The minimum number of optional added scorers
  143. /// that should match during the search.
  144. /// In case no required scorers are added,
  145. /// at least one of the optional scorers will have to
  146. /// match during the search.
  147. /// </param>
  148. public BooleanScorer2(Similarity similarity, int minNrShouldMatch):base(similarity)
  149. {
  150. if (minNrShouldMatch < 0)
  151. {
  152. throw new System.ArgumentException("Minimum number of optional scorers should not be negative");
  153. }
  154. coordinator = new Coordinator(this);
  155. this.minNrShouldMatch = minNrShouldMatch;
  156. }
  157. /// <summary>Create a BooleanScorer2.
  158. /// In no required scorers are added,
  159. /// at least one of the optional scorers will have to match during the search.
  160. /// </summary>
  161. /// <param name="similarity">The similarity to be used.
  162. /// </param>
  163. public BooleanScorer2(Similarity similarity) : this(similarity, 0)
  164. {
  165. }
  166. public virtual void  Add(Scorer scorer, bool required, bool prohibited)
  167. {
  168. if (!prohibited)
  169. {
  170. coordinator.maxCoord++;
  171. }
  172. if (required)
  173. {
  174. if (prohibited)
  175. {
  176. throw new System.ArgumentException("scorer cannot be required and prohibited");
  177. }
  178. requiredScorers.Add(scorer);
  179. }
  180. else if (prohibited)
  181. {
  182. prohibitedScorers.Add(scorer);
  183. }
  184. else
  185. {
  186. optionalScorers.Add(scorer);
  187. }
  188. }
  189. /// <summary>Initialize the match counting scorer that sums all the
  190. /// scores. <p>
  191. /// When "counting" is used in a name it means counting the number
  192. /// of matching scorers.<br>
  193. /// When "sum" is used in a name it means score value summing
  194. /// over the matching scorers
  195. /// </summary>
  196. private void  InitCountingSumScorer()
  197. {
  198. coordinator.Init();
  199. countingSumScorer = MakeCountingSumScorer();
  200. }
  201. /// <summary>Count a scorer as a single match. </summary>
  202. private class SingleMatchScorer : Scorer
  203. {
  204. private void  InitBlock(BooleanScorer2 enclosingInstance)
  205. {
  206. this.enclosingInstance = enclosingInstance;
  207. }
  208. private BooleanScorer2 enclosingInstance;
  209. public BooleanScorer2 Enclosing_Instance
  210. {
  211. get
  212. {
  213. return enclosingInstance;
  214. }
  215. }
  216. private Scorer scorer;
  217. private int lastScoredDoc = - 1;
  218. internal SingleMatchScorer(BooleanScorer2 enclosingInstance, Scorer scorer) : base(scorer.GetSimilarity())
  219. {
  220. InitBlock(enclosingInstance);
  221. this.scorer = scorer;
  222. }
  223. public override float Score()
  224. {
  225. if (Doc() > lastScoredDoc)
  226. {
  227. lastScoredDoc = Doc();
  228. Enclosing_Instance.coordinator.nrMatchers++;
  229. }
  230. return scorer.Score();
  231. }
  232. public override int Doc()
  233. {
  234. return scorer.Doc();
  235. }
  236. public override bool Next()
  237. {
  238. return scorer.Next();
  239. }
  240. public override bool SkipTo(int docNr)
  241. {
  242. return scorer.SkipTo(docNr);
  243. }
  244. public override Explanation Explain(int docNr)
  245. {
  246. return scorer.Explain(docNr);
  247. }
  248. }
  249. private Scorer CountingDisjunctionSumScorer(System.Collections.IList scorers, int minMrShouldMatch)
  250. // each scorer from the list counted as a single matcher
  251. {
  252. return new AnonymousClassDisjunctionSumScorer(this, scorers, minMrShouldMatch);
  253. }
  254. private static Similarity defaultSimilarity = new DefaultSimilarity();
  255. private Scorer CountingConjunctionSumScorer(System.Collections.IList requiredScorers)
  256. {
  257. // each scorer from the list counted as a single matcher
  258. int requiredNrMatchers = requiredScorers.Count;
  259. ConjunctionScorer cs = new AnonymousClassConjunctionScorer(requiredNrMatchers, this, defaultSimilarity);
  260. System.Collections.IEnumerator rsi = requiredScorers.GetEnumerator();
  261. while (rsi.MoveNext())
  262. {
  263. cs.Add((Scorer) rsi.Current);
  264. }
  265. return cs;
  266. }
  267. private Scorer DualConjunctionSumScorer(Scorer req1, Scorer req2)
  268. {
  269. // non counting. 
  270. //UPGRADE_NOTE: Final was removed from the declaration of 'requiredNrMatchers '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
  271. int requiredNrMatchers = requiredScorers.Count;
  272. ConjunctionScorer cs = new ConjunctionScorer(defaultSimilarity);
  273. // All scorers match, so defaultSimilarity super.score() always has 1 as
  274. // the coordination factor.
  275. // Therefore the sum of the scores of two scorers
  276. // is used as score.
  277. cs.Add(req1);
  278. cs.Add(req2);
  279. return cs;
  280. }
  281. /// <summary>Returns the scorer to be used for match counting and score summing.
  282. /// Uses requiredScorers, optionalScorers and prohibitedScorers.
  283. /// </summary>
  284. private Scorer MakeCountingSumScorer()
  285. {
  286. // each scorer counted as a single matcher
  287. return (requiredScorers.Count == 0)?MakeCountingSumScorerNoReq():MakeCountingSumScorerSomeReq();
  288. }
  289. private Scorer MakeCountingSumScorerNoReq()
  290. {
  291. // No required scorers
  292. if (optionalScorers.Count == 0)
  293. {
  294. return new NonMatchingScorer(); // no clauses or only prohibited clauses
  295. }
  296. else
  297. {
  298. // No required scorers. At least one optional scorer.
  299. // minNrShouldMatch optional scorers are required, but at least 1
  300. int nrOptRequired = (minNrShouldMatch < 1)?1:minNrShouldMatch;
  301. if (optionalScorers.Count < nrOptRequired)
  302. {
  303. return new NonMatchingScorer(); // fewer optional clauses than minimum (at least 1) that should match
  304. }
  305. else
  306. {
  307. // optionalScorers.size() >= nrOptRequired, no required scorers
  308. Scorer requiredCountingSumScorer = (optionalScorers.Count > nrOptRequired)?CountingDisjunctionSumScorer(optionalScorers, nrOptRequired):((optionalScorers.Count == 1)?new SingleMatchScorer(this, (Scorer) optionalScorers[0]):CountingConjunctionSumScorer(optionalScorers));
  309. return AddProhibitedScorers(requiredCountingSumScorer);
  310. }
  311. }
  312. }
  313. private Scorer MakeCountingSumScorerSomeReq()
  314. {
  315. // At least one required scorer.
  316. if (optionalScorers.Count < minNrShouldMatch)
  317. {
  318. return new NonMatchingScorer(); // fewer optional clauses than minimum that should match
  319. }
  320. else if (optionalScorers.Count == minNrShouldMatch)
  321. {
  322. // all optional scorers also required.
  323. System.Collections.ArrayList allReq = new System.Collections.ArrayList(requiredScorers);
  324. allReq.AddRange(optionalScorers);
  325. return AddProhibitedScorers(CountingConjunctionSumScorer(allReq));
  326. }
  327. else
  328. {
  329. // optionalScorers.size() > minNrShouldMatch, and at least one required scorer
  330. Scorer requiredCountingSumScorer = (requiredScorers.Count == 1)?new SingleMatchScorer(this, (Scorer) requiredScorers[0]):CountingConjunctionSumScorer(requiredScorers);
  331. if (minNrShouldMatch > 0)
  332. {
  333. // use a required disjunction scorer over the optional scorers
  334. return AddProhibitedScorers(DualConjunctionSumScorer(requiredCountingSumScorer, CountingDisjunctionSumScorer(optionalScorers, minNrShouldMatch)));
  335. }
  336. else
  337. {
  338. // minNrShouldMatch == 0
  339. return new ReqOptSumScorer(AddProhibitedScorers(requiredCountingSumScorer), ((optionalScorers.Count == 1)?new SingleMatchScorer(this, (Scorer) optionalScorers[0]):CountingDisjunctionSumScorer(optionalScorers, 1))); // require 1 in combined, optional scorer.
  340. }
  341. }
  342. }
  343. /// <summary>Returns the scorer to be used for match counting and score summing.
  344. /// Uses the given required scorer and the prohibitedScorers.
  345. /// </summary>
  346. /// <param name="requiredCountingSumScorer">A required scorer already built.
  347. /// </param>
  348. private Scorer AddProhibitedScorers(Scorer requiredCountingSumScorer)
  349. {
  350. return (prohibitedScorers.Count == 0)?requiredCountingSumScorer:new ReqExclScorer(requiredCountingSumScorer, ((prohibitedScorers.Count == 1)?(Scorer) prohibitedScorers[0]:new DisjunctionSumScorer(prohibitedScorers)));
  351. }
  352. /// <summary>Scores and collects all matching documents.</summary>
  353. /// <param name="hc">The collector to which all matching documents are passed through
  354. /// {@link HitCollector#Collect(int, float)}.
  355. /// <br>When this method is used the {@link #Explain(int)} method should not be used.
  356. /// </param>
  357. public override void  Score(HitCollector hc)
  358. {
  359. if (countingSumScorer == null)
  360. {
  361. InitCountingSumScorer();
  362. }
  363. while (countingSumScorer.Next())
  364. {
  365. hc.Collect(countingSumScorer.Doc(), Score());
  366. }
  367. }
  368. /// <summary>Expert: Collects matching documents in a range.
  369. /// <br>Note that {@link #Next()} must be called once before this method is
  370. /// called for the first time.
  371. /// </summary>
  372. /// <param name="hc">The collector to which all matching documents are passed through
  373. /// {@link HitCollector#Collect(int, float)}.
  374. /// </param>
  375. /// <param name="max">Do not score documents past this.
  376. /// </param>
  377. /// <returns> true if more matching documents may remain.
  378. /// </returns>
  379. protected internal override bool Score(HitCollector hc, int max)
  380. {
  381. // null pointer exception when Next() was not called before:
  382. int docNr = countingSumScorer.Doc();
  383. while (docNr < max)
  384. {
  385. hc.Collect(docNr, Score());
  386. if (!countingSumScorer.Next())
  387. {
  388. return false;
  389. }
  390. docNr = countingSumScorer.Doc();
  391. }
  392. return true;
  393. }
  394. public override int Doc()
  395. {
  396. return countingSumScorer.Doc();
  397. }
  398. public override bool Next()
  399. {
  400. if (countingSumScorer == null)
  401. {
  402. InitCountingSumScorer();
  403. }
  404. return countingSumScorer.Next();
  405. }
  406. public override float Score()
  407. {
  408. coordinator.InitDoc();
  409. float sum = countingSumScorer.Score();
  410. return sum * coordinator.CoordFactor();
  411. }
  412. /// <summary>Skips to the first match beyond the current whose document number is
  413. /// greater than or equal to a given target.
  414. /// 
  415. /// <p>When this method is used the {@link #Explain(int)} method should not be used.
  416. /// 
  417. /// </summary>
  418. /// <param name="target">The target document number.
  419. /// </param>
  420. /// <returns> true iff there is such a match.
  421. /// </returns>
  422. public override bool SkipTo(int target)
  423. {
  424. if (countingSumScorer == null)
  425. {
  426. InitCountingSumScorer();
  427. }
  428. return countingSumScorer.SkipTo(target);
  429. }
  430. /// <summary>Throws an UnsupportedOperationException.
  431. /// TODO: Implement an explanation of the coordination factor.
  432. /// </summary>
  433. /// <param name="doc">The document number for the explanation.
  434. /// </param>
  435. /// <throws>  UnsupportedOperationException </throws>
  436. public override Explanation Explain(int doc)
  437. {
  438. throw new System.NotSupportedException();
  439. /* How to explain the coordination factor?
  440. initCountingSumScorer();
  441. return countingSumScorer.explain(doc); // misses coord factor. 
  442. */
  443. }
  444. }
  445. }