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

搜索引擎

开发平台:

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. sealed class BooleanScorer : Scorer
  20. {
  21. private void  InitBlock()
  22. {
  23. bucketTable = new BucketTable(this);
  24. }
  25. private SubScorer scorers = null;
  26. private BucketTable bucketTable;
  27. private int maxCoord = 1;
  28. private float[] coordFactors = null;
  29. private int requiredMask = 0;
  30. private int prohibitedMask = 0;
  31. private int nextMask = 1;
  32. internal BooleanScorer(Similarity similarity) : base(similarity)
  33. {
  34. InitBlock();
  35. }
  36. internal sealed class SubScorer
  37. {
  38. public Scorer scorer;
  39. public bool done;
  40. public bool required = false;
  41. public bool prohibited = false;
  42. public HitCollector collector;
  43. public SubScorer next;
  44. public SubScorer(Scorer scorer, bool required, bool prohibited, HitCollector collector, SubScorer next)
  45. {
  46. this.scorer = scorer;
  47. this.done = !scorer.Next();
  48. this.required = required;
  49. this.prohibited = prohibited;
  50. this.collector = collector;
  51. this.next = next;
  52. }
  53. }
  54. internal void  Add(Scorer scorer, bool required, bool prohibited)
  55. {
  56. int mask = 0;
  57. if (required || prohibited)
  58. {
  59. if (nextMask == 0)
  60. throw new System.IndexOutOfRangeException("More than 32 required/prohibited clauses in query.");
  61. mask = nextMask;
  62. nextMask = nextMask << 1;
  63. }
  64. else
  65. mask = 0;
  66. if (!prohibited)
  67. maxCoord++;
  68. if (prohibited)
  69. prohibitedMask |= mask;
  70. // update prohibited mask
  71. else if (required)
  72. requiredMask |= mask; // update required mask
  73. scorers = new SubScorer(scorer, required, prohibited, bucketTable.NewCollector(mask), scorers);
  74. }
  75. private void  ComputeCoordFactors()
  76. {
  77. coordFactors = new float[maxCoord];
  78. for (int i = 0; i < maxCoord; i++)
  79. coordFactors[i] = GetSimilarity().Coord(i, maxCoord - 1);
  80. }
  81. private int end;
  82. private Bucket current;
  83. public override void  Score(HitCollector hc)
  84. {
  85. Next();
  86. Score(hc, System.Int32.MaxValue);
  87. }
  88. protected internal override bool Score(HitCollector hc, int max)
  89. {
  90. if (coordFactors == null)
  91. ComputeCoordFactors();
  92. bool more;
  93. Bucket tmp;
  94. do 
  95. {
  96. bucketTable.first = null;
  97. while (current != null)
  98. {
  99. // more queued 
  100. // check prohibited & required
  101. if ((current.bits & prohibitedMask) == 0 && (current.bits & requiredMask) == requiredMask)
  102. {
  103. if (current.doc >= max)
  104. {
  105. tmp = current;
  106. current = current.next;
  107. tmp.next = bucketTable.first;
  108. bucketTable.first = tmp;
  109. continue;
  110. }
  111. hc.Collect(current.doc, current.score * coordFactors[current.coord]);
  112. }
  113. current = current.next; // pop the queue
  114. }
  115. if (bucketTable.first != null)
  116. {
  117. current = bucketTable.first;
  118. bucketTable.first = current.next;
  119. return true;
  120. }
  121. // refill the queue
  122. more = false;
  123. end += BucketTable.SIZE;
  124. for (SubScorer sub = scorers; sub != null; sub = sub.next)
  125. {
  126. if (!sub.done)
  127. {
  128. sub.done = !sub.scorer.Score(sub.collector, end);
  129. if (!sub.done)
  130. more = true;
  131. }
  132. }
  133. current = bucketTable.first;
  134. }
  135. while (current != null || more);
  136. return false;
  137. }
  138. public override int Doc()
  139. {
  140. return current.doc;
  141. }
  142. public override bool Next()
  143. {
  144. bool more;
  145. do 
  146. {
  147. while (bucketTable.first != null)
  148. {
  149. // more queued
  150. current = bucketTable.first;
  151. bucketTable.first = current.next; // pop the queue
  152. // check prohibited & required
  153. if ((current.bits & prohibitedMask) == 0 && (current.bits & requiredMask) == requiredMask)
  154. {
  155. return true;
  156. }
  157. }
  158. // refill the queue
  159. more = false;
  160. end += BucketTable.SIZE;
  161. for (SubScorer sub = scorers; sub != null; sub = sub.next)
  162. {
  163. Scorer scorer = sub.scorer;
  164. while (!sub.done && scorer.Doc() < end)
  165. {
  166. sub.collector.Collect(scorer.Doc(), scorer.Score());
  167. sub.done = !scorer.Next();
  168. }
  169. if (!sub.done)
  170. {
  171. more = true;
  172. }
  173. }
  174. }
  175. while (bucketTable.first != null || more);
  176. return false;
  177. }
  178. public override float Score()
  179. {
  180. if (coordFactors == null)
  181. ComputeCoordFactors();
  182. return current.score * coordFactors[current.coord];
  183. }
  184. internal sealed class Bucket
  185. {
  186. internal int doc = - 1; // tells if bucket is valid
  187. internal float score; // incremental score
  188. internal int bits; // used for bool constraints
  189. internal int coord; // count of terms in score
  190. internal Bucket next; // next valid bucket
  191. }
  192. /// <summary>A simple hash table of document scores within a range. </summary>
  193. internal sealed class BucketTable
  194. {
  195. private void  InitBlock()
  196. {
  197. buckets = new Bucket[SIZE];
  198. }
  199. public const int SIZE = 1 << 11;
  200. public static readonly int MASK;
  201. internal Bucket[] buckets;
  202. internal Bucket first = null; // head of valid list
  203. private BooleanScorer scorer;
  204. public BucketTable(BooleanScorer scorer)
  205. {
  206. this.scorer = scorer;
  207. }
  208. public int Size()
  209. {
  210. return SIZE;
  211. }
  212. public HitCollector NewCollector(int mask)
  213. {
  214. return new Collector(mask, this);
  215. }
  216. static BucketTable()
  217. {
  218. MASK = SIZE - 1;
  219. }
  220. }
  221. internal sealed class Collector : HitCollector
  222. {
  223. private BucketTable bucketTable;
  224. private int mask;
  225. public Collector(int mask, BucketTable bucketTable)
  226. {
  227. this.mask = mask;
  228. this.bucketTable = bucketTable;
  229. }
  230. public override void  Collect(int doc, float score)
  231. {
  232. BucketTable table = bucketTable;
  233. int i = doc & Lucene.Net.Search.BooleanScorer.BucketTable.MASK;
  234. Bucket bucket = table.buckets[i];
  235. if (bucket == null)
  236. table.buckets[i] = bucket = new Bucket();
  237. if (bucket.doc != doc)
  238. {
  239. // invalid bucket
  240. bucket.doc = doc; // set doc
  241. bucket.score = score; // initialize score
  242. bucket.bits = mask; // initialize mask
  243. bucket.coord = 1; // initialize coord
  244. bucket.next = table.first; // push onto valid list
  245. table.first = bucket;
  246. }
  247. else
  248. {
  249. // valid bucket
  250. bucket.score += score; // increment score
  251. bucket.bits |= mask; // add bits in mask
  252. bucket.coord++; // increment coord
  253. }
  254. }
  255. }
  256. public override bool SkipTo(int target)
  257. {
  258. throw new System.NotSupportedException();
  259. }
  260. public override Explanation Explain(int doc)
  261. {
  262. throw new System.NotSupportedException();
  263. }
  264. public override System.String ToString()
  265. {
  266. System.Text.StringBuilder buffer = new System.Text.StringBuilder();
  267. buffer.Append("boolean(");
  268. for (SubScorer sub = scorers; sub != null; sub = sub.next)
  269. {
  270. buffer.Append(sub.scorer.ToString());
  271. buffer.Append(" ");
  272. }
  273. buffer.Append(")");
  274. return buffer.ToString();
  275. }
  276. }
  277. }