public virtual Explanation Explain(IndexReader indexReader, int docid, Explanation innerExplaination)
        {
            if (!(indexReader is BoboIndexReader)) throw new ArgumentException("IndexReader is not BoboIndexReader");
            BoboIndexReader reader = (BoboIndexReader)indexReader;

            Explanation exp = new Explanation();
            exp.Description = "FacetBasedBoost";

            float boost = 1.0f;
            foreach (var boostEntry in _boostMaps)
            {
                string facetName = boostEntry.Key;
                IFacetHandler handler = reader.GetFacetHandler(facetName);
                if (!(handler is IFacetScoreable))
                    throw new ArgumentException(facetName + " does not implement IFacetScoreable");

                IFacetScoreable facetScoreable = (IFacetScoreable)handler;
                BoboDocScorer scorer = facetScoreable.GetDocScorer(reader, _scoringFunctionFactory, boostEntry.Value);
                float facetBoost = scorer.Score(docid);

                Explanation facetExp = new Explanation();
                facetExp.Description = facetName;
                facetExp.Value = facetBoost;
                facetExp.AddDetail(scorer.Explain(docid));
                boost *= facetBoost;
                exp.AddDetail(facetExp);
            }
            exp.Value = boost;
            exp.AddDetail(innerExplaination);
            return exp;
        }
			public override Explanation Explain(int doc)
			{
				Explanation explanation = new Explanation();
				explanation.SetValue(1.0f);
				explanation.SetDescription("MatchAllDocsQuery");
				return explanation;
			}
 public virtual Explanation Explain(int df, float boost)
 {
     Explanation expl = new Explanation();
     expl.Value = Score(df, boost);
     expl.Description = "facet boost value of: " + boost;
     return expl;
 }
 public virtual Explanation Explain(IndexReader reader, int doc, Explanation innerExplanation)
 {
     if (reader is BoboIndexReader)
     {
         BoboIndexReader boboReader = (BoboIndexReader)reader;
         object dataObj = boboReader.GetFacetData(_timeFacetName);
         if (dataObj is FacetDataCache)
         {
             FacetDataCache facetDataCache = (FacetDataCache)(boboReader.GetFacetData(_timeFacetName));
             BigSegmentedArray orderArray = facetDataCache.OrderArray;
             TermLongList termList = (TermLongList)facetDataCache.ValArray;
             long now = System.Environment.TickCount;
             Explanation finalExpl = new Explanation();
             finalExpl.AddDetail(innerExplanation);
             float rawScore = innerExplanation.Value;
             long timeVal = termList.GetPrimitiveValue(orderArray.Get(doc));
             float timeScore = ComputeTimeFactor(timeVal);
             float finalScore = CombineScores(timeScore, rawScore);
             finalExpl.Value = finalScore;
             finalExpl.Description = "final score = (time score: " + timeScore + ") * (raw score: " + rawScore + "), timeVal: " + timeVal;
             return finalExpl;
         }
         else
         {
             throw new InvalidOperationException("underlying facet data must be of type FacetDataCache<long>");
         }
     }
     else
     {
         throw new ArgumentException("reader not instance of " + typeof(BoboIndexReader));
     }
 }
 /// <summary>Explain the score of a document.</summary>
 /// <todo>  Also show the total score. </todo>
 /// <summary> See BooleanScorer.explain() on how to do this.
 /// </summary>
 public override Explanation Explain(int doc)
 {
     Explanation res = new Explanation();
     res.SetDescription("required, optional");
     res.AddDetail(reqScorer.Explain(doc));
     res.AddDetail(optScorer.Explain(doc));
     return res;
 }
            public override Explanation Explain(IndexReader reader, int doc)
            {
                Explanation result = new Explanation();
                result.Value = _weight;
                result.Description = _parent.ToString();

                return result;
            }
 public virtual Explanation Explain(params float[] scores)
 {
     float sum = 0.0f;
     foreach (float score in scores)
     {
         sum += score;
     }
     Explanation expl = new Explanation(sum, "sum of: " + Arrays.ToString(scores));
     return expl;
 }
		public override Explanation Explain(IndexReader reader, int doc)
		{
			
			ComplexExplanation result = new ComplexExplanation();
			result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");
			System.String field = ((SpanQuery) GetQuery()).GetField();
			
			Explanation idfExpl = new Explanation(idf, "idf(" + field + ": " + idfExp.Explain() + ")");
			
			// explain query weight
			Explanation queryExpl = new Explanation();
			queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");
			
			Explanation boostExpl = new Explanation(GetQuery().GetBoost(), "boost");
			if (GetQuery().GetBoost() != 1.0f)
				queryExpl.AddDetail(boostExpl);
			queryExpl.AddDetail(idfExpl);
			
			Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
			queryExpl.AddDetail(queryNormExpl);
			
			queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());
			
			result.AddDetail(queryExpl);
			
			// explain field weight
			ComplexExplanation fieldExpl = new ComplexExplanation();
			fieldExpl.SetDescription("fieldWeight(" + field + ":" + query.ToString(field) + " in " + doc + "), product of:");
			
			Explanation tfExpl = Scorer(reader, true, false).Explain(doc);
			fieldExpl.AddDetail(tfExpl);
			fieldExpl.AddDetail(idfExpl);
			
			Explanation fieldNormExpl = new Explanation();
			byte[] fieldNorms = reader.Norms(field);
			float fieldNorm = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]):1.0f;
			fieldNormExpl.SetValue(fieldNorm);
			fieldNormExpl.SetDescription("fieldNorm(field=" + field + ", doc=" + doc + ")");
			fieldExpl.AddDetail(fieldNormExpl);
			
			fieldExpl.SetMatch(tfExpl.IsMatch());
			fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());
			
			result.AddDetail(fieldExpl);
			System.Boolean? tempAux = fieldExpl.GetMatch();
			result.SetMatch(tempAux);
			
			// combine them
			result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());
			
			if (queryExpl.GetValue() == 1.0f)
				return fieldExpl;
			
			return result;
		}
 public virtual Explanation Explain(params float[] scores)
 {
     Explanation expl = new Explanation();
     float boost = 1.0f;
     foreach (float score in scores)
     {
         boost *= score;
     }
     expl.Value = boost;
     expl.Description = "product of: " + Arrays.ToString(scores);
     return expl;
 }
 public virtual Explanation Explain(params float[] scores)
 {
     Explanation expl = new Explanation();
     float sum = 0.0f;
     foreach (float score in scores)
     {
         sum += score;
     }
     expl.Value = sum;
     expl.Description = "sum of: " + Arrays.ToString(scores);
     return expl;
 }
                public override Explanation CustomExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl)
                {
                    float       valSrcScore = valSrcExpl == null ? 0 : valSrcExpl.Value;
                    Explanation exp         = new Explanation(valSrcScore + subQueryExpl.Value, "custom score: sum of:");

                    exp.AddDetail(subQueryExpl);
                    if (valSrcExpl != null)
                    {
                        exp.AddDetail(valSrcExpl);
                    }
                    return(exp);
                }
Exemple #12
0
        public ExplanationDialog(Explanation e)
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            treeExplain.BeginUpdate();
            AddNode(null, e);
            treeExplain.ExpandAll();
            treeExplain.EndUpdate();
        }
Exemple #13
0
        public override Explanation Explain(int doc)
        {
            Explanation tfExplanation = new Explanation();

            while (Next() && Doc() < doc)
            {
            }

            float phraseFreq = (Doc() == doc)?freq:0.0f;
            tfExplanation.SetValue(GetSimilarity().Tf(phraseFreq));
            tfExplanation.SetDescription("tf(phraseFreq=" + phraseFreq + ")");

            return tfExplanation;
        }
			public override Explanation Explain(int doc)
			{
				// make sure it has minX and area
				if (validMinX.Get(doc) && validMaxX.Get(doc))
				{
					Rectangle rect = new RectangleImpl(
						minX[doc], maxX[doc],
						minY[doc], maxY[doc]);
					var exp = new Explanation();
					_enclosingInstance.similarity.Score(rect, exp);
					return exp;
				}
				return new Explanation(0, "No BBox");
			}
 public override Explanation Explain(int doc)
 {
     Explanation res = new Explanation();
     if (exclScorer.SkipTo(doc) && (exclScorer.Doc() == doc))
     {
         res.SetDescription("excluded");
     }
     else
     {
         res.SetDescription("not excluded");
         res.AddDetail(reqScorer.Explain(doc));
     }
     return res;
 }
 public override Explanation Explain(IndexSearcher searcher, Explanation firstPassExplanation, int docID)
 {
     Explanation result = base.Explain(searcher, firstPassExplanation, docID);
     IList<AtomicReaderContext> leaves = searcher.IndexReader.Leaves;
     int subReader = ReaderUtil.SubIndex(docID, leaves);
     AtomicReaderContext readerContext = leaves[subReader];
     int docIDInSegment = docID - readerContext.DocBase;
     var context = new Dictionary<string, object>();
     var fakeScorer = new FakeScorer { score = firstPassExplanation.Value, doc = docIDInSegment };
     context["scorer"] = fakeScorer;
     foreach (string variable in expression.variables)
     {
         result.AddDetail(new Explanation((float)bindings.GetValueSource(variable).GetValues
             (context, readerContext).DoubleVal(docIDInSegment), "variable \"" + variable + "\""
             ));
     }
     return result;
 }
Exemple #17
0
 public double Score(Rectangle indexRect, Explanation exp)
 {
     double score;
     if (indexRect == null)
     {
         score = nullValue;
     }
     else
     {
         score = distCalc.Distance(queryPoint, indexRect.GetCenter());
     }
     if (exp != null)
     {
         exp.Value = (float) score;
         exp.Description = GetType().Name;
         exp.AddDetail(new Explanation(-1f, "" + queryPoint));
         exp.AddDetail(new Explanation(-1f, "" + indexRect));
     }
     return score;
 }
                public override Explanation CustomExplain(int doc, Explanation subQueryExpl, Explanation[] valSrcExpls)
                {
                    if (valSrcExpls.Length == 0)
                    {
                        return(subQueryExpl);
                    }
                    Explanation exp = new Explanation(valSrcExpls[0].Value + subQueryExpl.Value, "sum of:");

                    exp.AddDetail(subQueryExpl);
                    exp.AddDetail(valSrcExpls[0]);
                    if (valSrcExpls.Length == 1)
                    {
                        exp.Description = "CustomMulAdd, sum of:";
                        return(exp);
                    }
                    Explanation exp2 = new Explanation(valSrcExpls[1].Value * exp.Value, "custom score: product of:");

                    exp2.AddDetail(valSrcExpls[1]);
                    exp2.AddDetail(exp);
                    return(exp2);
                }
Exemple #19
0
        private void btnExplain_Click(object sender, System.EventArgs e)
        {
            if (listSearch.SelectedItems.Count == 0)
            {
                return;
            }
            if (searchedDocIds == null || searchedDocIds.Length < listSearch.Items.Count)
            {
                return;
            }

            if (_luke.IndexReader == null)
            {
                _luke.ShowStatus(_luke.resources.GetString("NoIndex"));
                return;
            }

            if (query == null)
            {
                return;
            }

            IndexSearcher searcher = null;

            try
            {
                searcher = new IndexSearcher(_luke.Directory, true);
                Lucene.Net.Search.Explanation expl       = searcher.Explain(query, searchedDocIds[listSearch.SelectedIndices[0]]);
                ExplanationDialog             explDialog = new ExplanationDialog(expl);
                explDialog.ShowDialog(this);
            }
            catch (Exception exc)
            {
                _luke.ErrorMessage(exc.Message);
            }
            finally
            {
                searcher.Close();
            }
        }
Exemple #20
0
        private void AddNode(TreeNode tn, Explanation e)
        {
            TreeNode node = new TreeNode(e.GetValue().ToString("G4") + "  " + e.GetDescription());

            if (null == tn)
            {
                treeExplain.Nodes.Add(node);
            }
            else
            {
                tn.Nodes.Add(node);
            }

            Explanation[] kids = e.GetDetails();
            if (kids != null && kids.Length > 0)
            {
                for (int i = 0; i < kids.Length; i++)
                {
                    AddNode(node, kids[i]);
                }
            }
        }
Exemple #21
0
        private void Explain(LNS.Query query)
        {
            int j = 0;

            while (j < collector.Array.Count)
            {
                int i;
                i = collector.Array.GetNextTrueIndex(j);
                if (i >= collector.Array.Count)
                {
                    break;
                }
                j = i + 1;

                Document        doc = searcher.Doc(i);
                LNS.Explanation exp = searcher.Explain(query, i);

                Log.Debug("Query: [{0}]", query);
                Log.Debug("Matching URI: {0}", doc.Get("Uri"));
                Log.Debug("Explanation: {0}", exp);
            }
        }
Exemple #22
0
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Request.QueryString.Count == 4 && Request.QueryString.AllKeys[0] == "query" && Request.QueryString.AllKeys[1] == "absoluteUri" && Request.QueryString.AllKeys[2] == "documentID" && Request.QueryString.AllKeys[3] == "strength")
            {
                Query query;

                if (!Request.QueryString.AllKeys[0].Contains(":"))
                {
                    query = Global.DefaultQueryParser.Parse(Request.QueryString.AllKeys[0]);
                }
                else
                {
                    query = Global.CustomQueryParser.Parse(Request.QueryString.AllKeys[0]);
                }

                uxHlAbsoluteUri.NavigateUrl = Request.QueryString[1];
                uxHlAbsoluteUri.Text        = Request.QueryString[1];

                Lucene.Net.Search.Explanation explanation = Global.IndexSearcher.Explain(query, int.Parse(Request.QueryString[2]));

                uxLblExplanation.Text = explanation.ToHtml();
                uxLblStrength.Text    = "<ul><li>Strength: " + Request.QueryString[3] + "</li></ul>";
            }
        }
Exemple #23
0
            public override Explanation Explain(IndexReader reader, int doc)
            {
                ComplexExplanation result = new ComplexExplanation();

                result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");

                Explanation expl = new Explanation(idf, idfExp.Explain());

                // explain query weight
                Explanation queryExpl = new Explanation();

                queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");

                Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");

                if (Enclosing_Instance.GetBoost() != 1.0f)
                {
                    queryExpl.AddDetail(boostExpl);
                }
                queryExpl.AddDetail(expl);

                Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");

                queryExpl.AddDetail(queryNormExpl);

                queryExpl.SetValue(boostExpl.GetValue() * expl.GetValue() * queryNormExpl.GetValue());

                result.AddDetail(queryExpl);

                // explain field weight
                System.String      field     = Enclosing_Instance.term.Field();
                ComplexExplanation fieldExpl = new ComplexExplanation();

                fieldExpl.SetDescription("fieldWeight(" + Enclosing_Instance.term + " in " + doc + "), product of:");

                Explanation tfExpl = Scorer(reader, true, false).Explain(doc);

                fieldExpl.AddDetail(tfExpl);
                fieldExpl.AddDetail(expl);

                Explanation fieldNormExpl = new Explanation();

                byte[] fieldNorms = reader.Norms(field);
                float  fieldNorm  = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]) : 1.0f;

                fieldNormExpl.SetValue(fieldNorm);
                fieldNormExpl.SetDescription("fieldNorm(field=" + field + ", doc=" + doc + ")");
                fieldExpl.AddDetail(fieldNormExpl);

                fieldExpl.SetMatch(tfExpl.IsMatch());
                fieldExpl.SetValue(tfExpl.GetValue() * expl.GetValue() * fieldNormExpl.GetValue());

                result.AddDetail(fieldExpl);
                System.Boolean?tempAux = fieldExpl.GetMatch();
                result.SetMatch(tempAux);

                // combine them
                result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());

                if (queryExpl.GetValue() == 1.0f)
                {
                    return(fieldExpl);
                }

                return(result);
            }
			public virtual Explanation Explain(IndexReader reader, int doc)
			{
				// explain query weight
				Explanation queryExpl = new Explanation();
				queryExpl.SetDescription("MatchAllDocsQuery:");
				
				Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");
				if (Enclosing_Instance.GetBoost() != 1.0f)
					queryExpl.AddDetail(boostExpl);
				queryExpl.SetValue(boostExpl.GetValue());
				
				return queryExpl;
			}
        /// <summary>Returns an explanation of the score for a document.
        /// <br>When this method is used, the {@link #next()} method
        /// and the {@link #Score(HitCollector)} method should not be used.
        /// </summary>
        /// <param name="doc">The document number for the explanation.
        /// </param>
        public override Explanation Explain(int doc)
        {
            TermQuery query = (TermQuery) weight.GetQuery();
            Explanation tfExplanation = new Explanation();
            int tf = 0;
            while (pointer < pointerMax)
            {
                if (docs[pointer] == doc)
                    tf = freqs[pointer];
                pointer++;
            }
            if (tf == 0)
            {
                if (termDocs.SkipTo(doc))
                {
                    if (termDocs.Doc() == doc)
                    {
                        tf = termDocs.Freq();
                    }
                }
            }
            termDocs.Close();
            tfExplanation.SetValue(GetSimilarity().Tf(tf));
            tfExplanation.SetDescription("tf(termFreq(" + query.GetTerm() + ")=" + tf + ")");

            return tfExplanation;
        }
            public override Explanation Explain(IndexReader reader, int doc)
            {
                Explanation result = new Explanation();

                result.Description = "weight(" + Query + " in " + doc + "), product of:";

                System.Text.StringBuilder docFreqs = new System.Text.StringBuilder();
                System.Text.StringBuilder query    = new System.Text.StringBuilder();
                query.Append('\"');
                docFreqs.Append(idfExp.Explain());
                for (int i = 0; i < Enclosing_Instance.terms.Count; i++)
                {
                    if (i != 0)
                    {
                        query.Append(" ");
                    }

                    Term term = Enclosing_Instance.terms[i];

                    query.Append(term.Text);
                }
                query.Append('\"');

                Explanation idfExpl = new Explanation(idf, "idf(" + Enclosing_Instance.field + ":" + docFreqs + ")");

                // explain query weight
                Explanation queryExpl = new Explanation();

                queryExpl.Description = "queryWeight(" + Query + "), product of:";

                Explanation boostExpl = new Explanation(Enclosing_Instance.Boost, "boost");

                if (Enclosing_Instance.Boost != 1.0f)
                {
                    queryExpl.AddDetail(boostExpl);
                }
                queryExpl.AddDetail(idfExpl);

                Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");

                queryExpl.AddDetail(queryNormExpl);

                queryExpl.Value = boostExpl.Value * idfExpl.Value * queryNormExpl.Value;

                result.AddDetail(queryExpl);

                // explain field weight
                Explanation fieldExpl = new Explanation();

                fieldExpl.Description = "fieldWeight(" + Enclosing_Instance.field + ":" + query + " in " + doc + "), product of:";

                PhraseScorer scorer = (PhraseScorer)Scorer(reader, true, false);

                if (scorer == null)
                {
                    return(new Explanation(0.0f, "no matching docs"));
                }
                Explanation tfExplanation = new Explanation();
                int         d             = scorer.Advance(doc);
                float       phraseFreq    = (d == doc) ? scorer.CurrentFreq() : 0.0f;

                tfExplanation.Value       = similarity.Tf(phraseFreq);
                tfExplanation.Description = "tf(phraseFreq=" + phraseFreq + ")";

                fieldExpl.AddDetail(tfExplanation);
                fieldExpl.AddDetail(idfExpl);

                Explanation fieldNormExpl = new Explanation();

                byte[] fieldNorms = reader.Norms(Enclosing_Instance.field);
                float  fieldNorm  = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]) : 1.0f;

                fieldNormExpl.Value       = fieldNorm;
                fieldNormExpl.Description = "fieldNorm(field=" + Enclosing_Instance.field + ", doc=" + doc + ")";
                fieldExpl.AddDetail(fieldNormExpl);

                fieldExpl.Value = tfExplanation.Value * idfExpl.Value * fieldNormExpl.Value;

                result.AddDetail(fieldExpl);

                // combine them
                result.Value = queryExpl.Value * fieldExpl.Value;

                if (queryExpl.Value == 1.0f)
                {
                    return(fieldExpl);
                }

                return(result);
            }
Exemple #27
0
            public virtual Explanation Explain(IndexReader reader, int doc)
            {
                Explanation result = new Explanation();

                result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");

                Explanation idfExpl = new Explanation(idf, "idf(docFreq=" + reader.DocFreq(Enclosing_Instance.term) + ")");

                // explain query weight
                Explanation queryExpl = new Explanation();

                queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");

                Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");

                if (Enclosing_Instance.GetBoost() != 1.0f)
                {
                    queryExpl.AddDetail(boostExpl);
                }
                queryExpl.AddDetail(idfExpl);

                Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");

                queryExpl.AddDetail(queryNormExpl);

                queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());

                result.AddDetail(queryExpl);

                // explain field weight
                System.String field     = Enclosing_Instance.term.Field();
                Explanation   fieldExpl = new Explanation();

                fieldExpl.SetDescription("fieldWeight(" + Enclosing_Instance.term + " in " + doc + "), product of:");

                Explanation tfExpl = Scorer(reader).Explain(doc);

                fieldExpl.AddDetail(tfExpl);
                fieldExpl.AddDetail(idfExpl);

                Explanation fieldNormExpl = new Explanation();

                byte[] fieldNorms = reader.Norms(field);
                float  fieldNorm  = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]) : 0.0f;

                fieldNormExpl.SetValue(fieldNorm);
                fieldNormExpl.SetDescription("fieldNorm(field=" + field + ", doc=" + doc + ")");
                fieldExpl.AddDetail(fieldNormExpl);

                fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());

                result.AddDetail(fieldExpl);

                // combine them
                result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());

                if (queryExpl.GetValue() == 1.0f)
                {
                    return(fieldExpl);
                }

                return(result);
            }
	    /// <summary>Adds a sub-node to this explanation node. </summary>
		public virtual void  AddDetail(Explanation detail)
		{
			if (details == null)
				details = new List<Explanation>();
			details.Add(detail);
		}
Exemple #29
0
            public override Explanation Explain(IndexReader reader, int doc)
            {
                int minShouldMatch         = Enclosing_Instance.GetMinimumNumberShouldMatch();
                ComplexExplanation sumExpl = new ComplexExplanation();

                sumExpl.SetDescription("sum of:");
                int   coord            = 0;
                int   maxCoord         = 0;
                float sum              = 0.0f;
                bool  fail             = false;
                int   shouldMatchCount = 0;

                for (System.Collections.IEnumerator wIter = weights.GetEnumerator(), cIter = Enclosing_Instance.clauses.GetEnumerator(); wIter.MoveNext();)
                {
                    cIter.MoveNext();

                    Weight        w = (Weight)wIter.Current;
                    BooleanClause c = (BooleanClause)cIter.Current;
                    if (w.Scorer(reader, true, true) == null)
                    {
                        continue;
                    }
                    Explanation e = w.Explain(reader, doc);
                    if (!c.IsProhibited())
                    {
                        maxCoord++;
                    }
                    if (e.IsMatch())
                    {
                        if (!c.IsProhibited())
                        {
                            sumExpl.AddDetail(e);
                            sum += e.GetValue();
                            coord++;
                        }
                        else
                        {
                            Explanation r = new Explanation(0.0f, "match on prohibited clause (" + c.GetQuery().ToString() + ")");
                            r.AddDetail(e);
                            sumExpl.AddDetail(r);
                            fail = true;
                        }
                        if (c.GetOccur() == Occur.SHOULD)
                        {
                            shouldMatchCount++;
                        }
                    }
                    else if (c.IsRequired())
                    {
                        Explanation r = new Explanation(0.0f, "no match on required clause (" + c.GetQuery().ToString() + ")");
                        r.AddDetail(e);
                        sumExpl.AddDetail(r);
                        fail = true;
                    }
                }
                if (fail)
                {
                    System.Boolean tempAux = false;
                    sumExpl.SetMatch(tempAux);
                    sumExpl.SetValue(0.0f);
                    sumExpl.SetDescription("Failure to meet condition(s) of required/prohibited clause(s)");
                    return(sumExpl);
                }
                else if (shouldMatchCount < minShouldMatch)
                {
                    System.Boolean tempAux2 = false;
                    sumExpl.SetMatch(tempAux2);
                    sumExpl.SetValue(0.0f);
                    sumExpl.SetDescription("Failure to match minimum number " + "of optional clauses: " + minShouldMatch);
                    return(sumExpl);
                }

                sumExpl.SetMatch(0 < coord?true:false);
                sumExpl.SetValue(sum);

                float coordFactor = similarity.Coord(coord, maxCoord);

                if (coordFactor == 1.0f)
                {
                    // coord is no-op
                    return(sumExpl);
                }
                // eliminate wrapper
                else
                {
                    ComplexExplanation result = new ComplexExplanation(sumExpl.IsMatch(), sum * coordFactor, "product of:");
                    result.AddDetail(sumExpl);
                    result.AddDetail(new Explanation(coordFactor, "coord(" + coord + "/" + maxCoord + ")"));
                    return(result);
                }
            }
        public virtual void  TestTermQueryMultiSearcherExplain()
        {
            // creating two directories for indices
            Directory indexStoreA = new MockRAMDirectory();
            Directory indexStoreB = new MockRAMDirectory();

            Document lDoc = new Document();

            lDoc.Add(new Field("handle", "1 2", Field.Store.YES, Field.Index.ANALYZED));
            Document lDoc2 = new Document();

            lDoc2.Add(new Field("handle", "1 2", Field.Store.YES, Field.Index.ANALYZED));
            Document lDoc3 = new Document();

            lDoc3.Add(new Field("handle", "1 2", Field.Store.YES, Field.Index.ANALYZED));

            IndexWriter writerA = new IndexWriter(indexStoreA, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED);
            IndexWriter writerB = new IndexWriter(indexStoreB, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED);

            writerA.AddDocument(lDoc);
            writerA.AddDocument(lDoc2);
            writerA.Optimize();
            writerA.Close();

            writerB.AddDocument(lDoc3);
            writerB.Close();

            QueryParser parser = new QueryParser(Util.Version.LUCENE_CURRENT, "fulltext", new StandardAnalyzer(Util.Version.LUCENE_CURRENT));
            Query       query  = parser.Parse("handle:1");

            Searcher[] searchers = new Searcher[2];
            searchers[0] = new IndexSearcher(indexStoreB, true);
            searchers[1] = new IndexSearcher(indexStoreA, true);
            Searcher mSearcher = new MultiSearcher(searchers);

            ScoreDoc[] hits = mSearcher.Search(query, null, 1000).ScoreDocs;

            Assert.AreEqual(3, hits.Length);

            Explanation explain = mSearcher.Explain(query, hits[0].Doc);

            System.String exp = explain.ToString(0);
            Assert.IsTrue(exp.IndexOf("maxDocs=3") > -1, exp);
            Assert.IsTrue(exp.IndexOf("docFreq=3") > -1, exp);

            query = parser.Parse("handle:\"1 2\"");
            hits  = mSearcher.Search(query, null, 1000).ScoreDocs;

            Assert.AreEqual(3, hits.Length);

            explain = mSearcher.Explain(query, hits[0].Doc);
            exp     = explain.ToString(0);
            Assert.IsTrue(exp.IndexOf("1=3") > -1, exp);
            Assert.IsTrue(exp.IndexOf("2=3") > -1, exp);

            query = new SpanNearQuery(new SpanQuery[] { new SpanTermQuery(new Term("handle", "1")), new SpanTermQuery(new Term("handle", "2")) }, 0, true);
            hits  = mSearcher.Search(query, null, 1000).ScoreDocs;

            Assert.AreEqual(3, hits.Length);

            explain = mSearcher.Explain(query, hits[0].Doc);
            exp     = explain.ToString(0);
            Assert.IsTrue(exp.IndexOf("1=3") > -1, exp);
            Assert.IsTrue(exp.IndexOf("2=3") > -1, exp);
            mSearcher.Close();
        }
			public override Explanation Explain(IndexReader reader, int doc)
			{
				
				ComplexExplanation result = new ComplexExplanation();
				result.Description = "weight(" + Query + " in " + doc + "), product of:";
				
				Explanation expl = new Explanation(idf, idfExp.Explain());
				
				// explain query weight
				Explanation queryExpl = new Explanation();
				queryExpl.Description = "queryWeight(" + Query + "), product of:";
				
				Explanation boostExpl = new Explanation(Enclosing_Instance.Boost, "boost");
				if (Enclosing_Instance.Boost != 1.0f)
					queryExpl.AddDetail(boostExpl);
				queryExpl.AddDetail(expl);
				
				Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
				queryExpl.AddDetail(queryNormExpl);
				
				queryExpl.Value = boostExpl.Value * expl.Value * queryNormExpl.Value;
				
				result.AddDetail(queryExpl);
				
				// explain field weight
				System.String field = Enclosing_Instance.term.Field;
				ComplexExplanation fieldExpl = new ComplexExplanation();
				fieldExpl.Description = "fieldWeight(" + Enclosing_Instance.term + " in " + doc + "), product of:";

                Explanation tfExplanation = new Explanation();
                int tf = 0;
                TermDocs termDocs = reader.TermDocs(enclosingInstance.term);
                if (termDocs != null)
                {
                    try
                    {
                        if (termDocs.SkipTo(doc) && termDocs.Doc == doc)
                        {
                            tf = termDocs.Freq;
                        }
                    }
                    finally
                    {
                        termDocs.Close();
                    }
                    tfExplanation.Value = similarity.Tf(tf);
                    tfExplanation.Description = "tf(termFreq(" + enclosingInstance.term + ")=" + tf + ")";
                }
                else
                {
                    tfExplanation.Value = 0.0f;
                    tfExplanation.Description = "no matching term";
                }
                fieldExpl.AddDetail(tfExplanation);
				fieldExpl.AddDetail(expl);
				
				Explanation fieldNormExpl = new Explanation();
				byte[] fieldNorms = reader.Norms(field);
				float fieldNorm = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]):1.0f;
				fieldNormExpl.Value = fieldNorm;
				fieldNormExpl.Description = "fieldNorm(field=" + field + ", doc=" + doc + ")";
				fieldExpl.AddDetail(fieldNormExpl);

                fieldExpl.Match = tfExplanation.IsMatch;
                fieldExpl.Value = tfExplanation.Value * expl.Value * fieldNormExpl.Value;
				
				result.AddDetail(fieldExpl);
				System.Boolean? tempAux = fieldExpl.Match;
				result.Match = tempAux;
				
				// combine them
				result.Value = queryExpl.Value * fieldExpl.Value;
				
				if (queryExpl.Value == 1.0f)
					return fieldExpl;
				
				return result;
			}
        public virtual void TestExplain()
        {
            Directory         dir = NewDirectory();
            RandomIndexWriter w   = new RandomIndexWriter(Random(), dir, Similarity, TimeZone);

            Document doc = new Document();

            doc.Add(NewStringField("id", "0", Field.Store.YES));
            doc.Add(NewTextField("field", "wizard the the the the the oz", Field.Store.NO));
            w.AddDocument(doc);
            doc = new Document();
            doc.Add(NewStringField("id", "1", Field.Store.YES));
            // 1 extra token, but wizard and oz are close;
            doc.Add(NewTextField("field", "wizard oz the the the the the the", Field.Store.NO));
            w.AddDocument(doc);
            IndexReader r = w.Reader;

            w.Dispose();

            // Do ordinary BooleanQuery:
            BooleanQuery bq = new BooleanQuery();

            bq.Add(new TermQuery(new Term("field", "wizard")), Occur.SHOULD);
            bq.Add(new TermQuery(new Term("field", "oz")), Occur.SHOULD);
            IndexSearcher searcher = GetSearcher(r);

            TopDocs hits = searcher.Search(bq, 10);

            Assert.AreEqual(2, hits.TotalHits);
            Assert.AreEqual("0", searcher.Doc(hits.ScoreDocs[0].Doc).Get("id"));
            Assert.AreEqual("1", searcher.Doc(hits.ScoreDocs[1].Doc).Get("id"));

            // Now, resort using PhraseQuery:
            PhraseQuery pq = new PhraseQuery();

            pq.Add(new Term("field", "wizard"));
            pq.Add(new Term("field", "oz"));

            Rescorer rescorer = new QueryRescorerAnonymousInnerClassHelper2(this, pq);

            TopDocs hits2 = rescorer.Rescore(searcher, hits, 10);

            // Resorting changed the order:
            Assert.AreEqual(2, hits2.TotalHits);
            Assert.AreEqual("1", searcher.Doc(hits2.ScoreDocs[0].Doc).Get("id"));
            Assert.AreEqual("0", searcher.Doc(hits2.ScoreDocs[1].Doc).Get("id"));

            int         docID   = hits2.ScoreDocs[0].Doc;
            Explanation explain = rescorer.Explain(searcher, searcher.Explain(bq, docID), docID);
            string      s       = explain.ToString();

            Assert.IsTrue(s.Contains("TestQueryRescorer+"));
            Assert.IsTrue(s.Contains("combined first and second pass score"));
            Assert.IsTrue(s.Contains("first pass score"));
            Assert.IsTrue(s.Contains("= second pass score"));
            Assert.AreEqual(hits2.ScoreDocs[0].Score, explain.Value, 0.0f);

            docID   = hits2.ScoreDocs[1].Doc;
            explain = rescorer.Explain(searcher, searcher.Explain(bq, docID), docID);
            s       = explain.ToString();
            Assert.IsTrue(s.Contains("TestQueryRescorer+"));
            Assert.IsTrue(s.Contains("combined first and second pass score"));
            Assert.IsTrue(s.Contains("first pass score"));
            Assert.IsTrue(s.Contains("no second pass score"));
            Assert.IsFalse(s.Contains("= second pass score"));
            Assert.IsTrue(s.Contains("NON-MATCH"));
            Assert.IsTrue(Math.Abs(hits2.ScoreDocs[1].Score - explain.Value) < 0.0000001f);

            r.Dispose();
            dir.Dispose();
        }
Exemple #33
0
        /// <summary>
        /// Assert that an explanation has the expected score, and optionally that its
        /// sub-details max/sum/factor match to that score.
        /// </summary>
        /// <param name="q"> String representation of the query for assertion messages. </param>
        /// <param name="doc"> Document ID for assertion messages. </param>
        /// <param name="score"> Real score value of doc with query <paramref name="q"/>. </param>
        /// <param name="deep"> Indicates whether a deep comparison of sub-Explanation details should be executed. </param>
        /// <param name="expl"> The <see cref="Explanation"/> to match against score. </param>
        public static void VerifyExplanation(string q, int doc, float score, bool deep, Explanation expl)
        {
            float value = expl.Value;

            Assert.AreEqual(score, value, ExplainToleranceDelta(score, value), q + ": score(doc=" + doc + ")=" + score + " != explanationScore=" + value + " Explanation: " + expl);

            if (!deep)
            {
                return;
            }

            Explanation[] detail = expl.GetDetails();
            // TODO: can we improve this entire method? its really geared to work only with TF/IDF
            if (expl.Description.EndsWith("computed from:", StringComparison.Ordinal))
            {
                return; // something more complicated.
            }
            if (detail != null)
            {
                if (detail.Length == 1)
                {
                    // simple containment, unless its a freq of: (which lets a query explain how the freq is calculated),
                    // just verify contained expl has same score
                    if (!expl.Description.EndsWith("with freq of:", StringComparison.Ordinal))
                    {
                        VerifyExplanation(q, doc, score, deep, detail[0]);
                    }
                }
                else
                {
                    // explanation must either:
                    // - end with one of: "product of:", "sum of:", "max of:", or
                    // - have "max plus <x> times others" (where <x> is float).
                    float  x              = 0;
                    string descr          = CultureInfo.InvariantCulture.TextInfo.ToLower(expl.Description);
                    bool   productOf      = descr.EndsWith("product of:", StringComparison.Ordinal);
                    bool   sumOf          = descr.EndsWith("sum of:", StringComparison.Ordinal);
                    bool   maxOf          = descr.EndsWith("max of:", StringComparison.Ordinal);
                    bool   maxTimesOthers = false;
                    if (!(productOf || sumOf || maxOf))
                    {
                        // maybe 'max plus x times others'
                        int k1 = descr.IndexOf("max plus ", StringComparison.Ordinal);
                        if (k1 >= 0)
                        {
                            k1 += "max plus ".Length;
                            int k2 = descr.IndexOf(" ", k1, StringComparison.Ordinal);

                            // LUCENENET NOTE: Using current culture here is intentional because
                            // we are parsing from text that was made using the current culture.
                            if (float.TryParse(descr.Substring(k1, k2 - k1).Trim(), out x) &&
                                descr.Substring(k2).Trim().Equals("times others of:", StringComparison.Ordinal))
                            {
                                maxTimesOthers = true;
                            }
                        }
                    }
                    // TODO: this is a TERRIBLE assertion!!!!
                    Assert.IsTrue(productOf || sumOf || maxOf || maxTimesOthers,
                                  q + ": multi valued explanation description=\"" + descr
                                  + "\" must be 'max of plus x times others' or end with 'product of'"
                                  + " or 'sum of:' or 'max of:' - " + expl);
                    float sum     = 0;
                    float product = 1;
                    float max     = 0;
                    for (int i = 0; i < detail.Length; i++)
                    {
                        float dval = detail[i].Value;
                        VerifyExplanation(q, doc, dval, deep, detail[i]);
                        product *= dval;
                        sum     += dval;
                        max      = Math.Max(max, dval);
                    }
                    float combined = 0;
                    if (productOf)
                    {
                        combined = product;
                    }
                    else if (sumOf)
                    {
                        combined = sum;
                    }
                    else if (maxOf)
                    {
                        combined = max;
                    }
                    else if (maxTimesOthers)
                    {
                        combined = max + x * (sum - max);
                    }
                    else
                    {
                        Assert.IsTrue(false, "should never get here!");
                    }
                    Assert.AreEqual(combined, value, ExplainToleranceDelta(combined, value),
                                    q + ": actual subDetails combined==" + combined + " != value=" + value + " Explanation: " + expl);
                }
            }
        }
            public override Explanation Explain(IndexReader reader, int doc)
            {
                ComplexExplanation result = new ComplexExplanation();

                result.Description = "weight(" + Query + " in " + doc + "), product of:";

                Explanation idfExpl = new Explanation(idf, "idf(" + Query + ")");

                // explain query weight
                Explanation queryExpl = new Explanation();

                queryExpl.Description = "queryWeight(" + Query + "), product of:";

                Explanation boostExpl = new Explanation(Enclosing_Instance.Boost, "boost");

                if (Enclosing_Instance.Boost != 1.0f)
                {
                    queryExpl.AddDetail(boostExpl);
                }

                queryExpl.AddDetail(idfExpl);

                Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");

                queryExpl.AddDetail(queryNormExpl);

                queryExpl.Value = boostExpl.Value * idfExpl.Value * queryNormExpl.Value;

                result.AddDetail(queryExpl);

                // explain field weight
                ComplexExplanation fieldExpl = new ComplexExplanation();

                fieldExpl.Description = "fieldWeight(" + Query + " in " + doc + "), product of:";

                PhraseScorer scorer = (PhraseScorer)Scorer(reader, true, false);

                if (scorer == null)
                {
                    return(new Explanation(0.0f, "no matching docs"));
                }
                Explanation tfExplanation = new Explanation();
                int         d             = scorer.Advance(doc);
                float       phraseFreq    = (d == doc) ? scorer.CurrentFreq() : 0.0f;

                tfExplanation.Value       = similarity.Tf(phraseFreq);
                tfExplanation.Description = "tf(phraseFreq=" + phraseFreq + ")";
                fieldExpl.AddDetail(tfExplanation);
                fieldExpl.AddDetail(idfExpl);

                Explanation fieldNormExpl = new Explanation();

                byte[] fieldNorms = reader.Norms(Enclosing_Instance.field);
                float  fieldNorm  = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]) : 1.0f;

                fieldNormExpl.Value       = fieldNorm;
                fieldNormExpl.Description = "fieldNorm(field=" + Enclosing_Instance.field + ", doc=" + doc + ")";
                fieldExpl.AddDetail(fieldNormExpl);

                fieldExpl.Match = tfExplanation.IsMatch;
                fieldExpl.Value = tfExplanation.Value * idfExpl.Value * fieldNormExpl.Value;

                result.AddDetail(fieldExpl);
                System.Boolean?tempAux = fieldExpl.Match;
                result.Match = tempAux;

                // combine them
                result.Value = queryExpl.Value * fieldExpl.Value;

                if (queryExpl.Value == 1.0f)
                {
                    return(fieldExpl);
                }

                return(result);
            }
 /// <summary>Adds a sub-node to this explanation node. </summary>
 public virtual void AddDetail(Explanation detail)
 {
     if (details == null)
         details = new System.Collections.ArrayList();
     details.Add(detail);
 }
 public override Explanation CustomExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl)
 {
     float valSrcScore = valSrcExpl == null ? 0 : valSrcExpl.Value;
     Explanation exp = new Explanation(valSrcScore + subQueryExpl.Value, "custom score: sum of:");
     exp.AddDetail(subQueryExpl);
     if (valSrcExpl != null)
     {
         exp.AddDetail(valSrcExpl);
     }
     return exp;
 }
Exemple #37
0
            public virtual Explanation Explain(IndexReader reader, int doc)
            {
                Explanation result = new Explanation();

                result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");

                System.Text.StringBuilder docFreqs = new System.Text.StringBuilder();
                System.Text.StringBuilder query    = new System.Text.StringBuilder();
                query.Append('\"');
                for (int i = 0; i < Enclosing_Instance.terms.Count; i++)
                {
                    if (i != 0)
                    {
                        docFreqs.Append(" ");
                        query.Append(" ");
                    }

                    Term term = (Term)Enclosing_Instance.terms[i];

                    docFreqs.Append(term.Text());
                    docFreqs.Append("=");
                    docFreqs.Append(reader.DocFreq(term));

                    query.Append(term.Text());
                }
                query.Append('\"');

                Explanation idfExpl = new Explanation(idf, "idf(" + Enclosing_Instance.field + ": " + docFreqs + ")");

                // explain query weight
                Explanation queryExpl = new Explanation();

                queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");

                Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");

                if (Enclosing_Instance.GetBoost() != 1.0f)
                {
                    queryExpl.AddDetail(boostExpl);
                }
                queryExpl.AddDetail(idfExpl);

                Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");

                queryExpl.AddDetail(queryNormExpl);

                queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());

                result.AddDetail(queryExpl);

                // explain field weight
                Explanation fieldExpl = new Explanation();

                fieldExpl.SetDescription("fieldWeight(" + Enclosing_Instance.field + ":" + query + " in " + doc + "), product of:");

                Explanation tfExpl = Scorer(reader).Explain(doc);

                fieldExpl.AddDetail(tfExpl);
                fieldExpl.AddDetail(idfExpl);

                Explanation fieldNormExpl = new Explanation();

                byte[] fieldNorms = reader.Norms(Enclosing_Instance.field);
                float  fieldNorm  = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]) : 0.0f;

                fieldNormExpl.SetValue(fieldNorm);
                fieldNormExpl.SetDescription("fieldNorm(field=" + Enclosing_Instance.field + ", doc=" + doc + ")");
                fieldExpl.AddDetail(fieldNormExpl);

                fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());

                result.AddDetail(fieldExpl);

                // combine them
                result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());

                if (queryExpl.GetValue() == 1.0f)
                {
                    return(fieldExpl);
                }

                return(result);
            }
			public virtual Explanation Explain(IndexReader reader, int doc)
			{
				
				Explanation result = new Explanation();
				result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");
				
				System.Text.StringBuilder docFreqs = new System.Text.StringBuilder();
				System.Text.StringBuilder query = new System.Text.StringBuilder();
				query.Append('\"');
				for (int i = 0; i < Enclosing_Instance.terms.Count; i++)
				{
					if (i != 0)
					{
						docFreqs.Append(" ");
						query.Append(" ");
					}
					
					Term term = (Term) Enclosing_Instance.terms[i];
					
					docFreqs.Append(term.Text());
					docFreqs.Append("=");
					docFreqs.Append(reader.DocFreq(term));
					
					query.Append(term.Text());
				}
				query.Append('\"');
				
				Explanation idfExpl = new Explanation(idf, "idf(" + Enclosing_Instance.field + ": " + docFreqs + ")");
				
				// explain query weight
				Explanation queryExpl = new Explanation();
				queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");
				
				Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");
				if (Enclosing_Instance.GetBoost() != 1.0f)
					queryExpl.AddDetail(boostExpl);
				queryExpl.AddDetail(idfExpl);
				
				Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
				queryExpl.AddDetail(queryNormExpl);
				
				queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());
				
				result.AddDetail(queryExpl);
				
				// explain field weight
				Explanation fieldExpl = new Explanation();
				fieldExpl.SetDescription("fieldWeight(" + Enclosing_Instance.field + ":" + query + " in " + doc + "), product of:");
				
				Explanation tfExpl = Scorer(reader).Explain(doc);
				fieldExpl.AddDetail(tfExpl);
				fieldExpl.AddDetail(idfExpl);
				
				Explanation fieldNormExpl = new Explanation();
				byte[] fieldNorms = reader.Norms(Enclosing_Instance.field);
				float fieldNorm = fieldNorms != null ? Similarity.DecodeNorm(fieldNorms[doc]) : 0.0f;
				fieldNormExpl.SetValue(fieldNorm);
				fieldNormExpl.SetDescription("fieldNorm(field=" + Enclosing_Instance.field + ", doc=" + doc + ")");
				fieldExpl.AddDetail(fieldNormExpl);
				
				fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());
				
				result.AddDetail(fieldExpl);
				
				// combine them
				result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());
				
				if (queryExpl.GetValue() == 1.0f)
					return fieldExpl;
				
				return result;
			}
        /// <summary> Assert that an explanation has the expected score, and optionally that its
        /// sub-details max/sum/factor match to that score.
        ///
        /// </summary>
        /// <param name="q">String representation of the query for assertion messages
        /// </param>
        /// <param name="doc">Document ID for assertion messages
        /// </param>
        /// <param name="score">Real score value of doc with query q
        /// </param>
        /// <param name="deep">indicates whether a deep comparison of sub-Explanation details should be executed
        /// </param>
        /// <param name="expl">The Explanation to match against score
        /// </param>
        public static void  VerifyExplanation(System.String q, int doc, float score, bool deep, Explanation expl)
        {
            float value_Renamed = expl.Value;

            Assert.AreEqual(score, value_Renamed, EXPLAIN_SCORE_TOLERANCE_DELTA, q + ": score(doc=" + doc + ")=" + score + " != explanationScore=" + value_Renamed + " Explanation: " + expl);

            if (!deep)
            {
                return;
            }

            Explanation[] detail = expl.GetDetails();
            if (detail != null)
            {
                if (detail.Length == 1)
                {
                    // simple containment, no matter what the description says,
                    // just verify contained expl has same score
                    VerifyExplanation(q, doc, score, deep, detail[0]);
                }
                else
                {
                    // explanation must either:
                    // - end with one of: "product of:", "sum of:", "max of:", or
                    // - have "max plus <x> times others" (where <x> is float).
                    float         x              = 0;
                    System.String descr          = expl.Description.ToLower();
                    bool          productOf      = descr.EndsWith("product of:");
                    bool          sumOf          = descr.EndsWith("sum of:");
                    bool          maxOf          = descr.EndsWith("max of:");
                    bool          maxTimesOthers = false;
                    if (!(productOf || sumOf || maxOf))
                    {
                        // maybe 'max plus x times others'
                        int k1 = descr.IndexOf("max plus ");
                        if (k1 >= 0)
                        {
                            k1 += "max plus ".Length;
                            int k2 = descr.IndexOf(" ", k1);
                            try
                            {
                                x = Single.Parse(descr.Substring(k1, (k2) - (k1)).Trim());
                                if (descr.Substring(k2).Trim().Equals("times others of:"))
                                {
                                    maxTimesOthers = true;
                                }
                            }
                            catch (System.FormatException)
                            {
                            }
                        }
                    }
                    Assert.IsTrue(productOf || sumOf || maxOf || maxTimesOthers, q + ": multi valued explanation description=\"" + descr + "\" must be 'max of plus x times others' or end with 'product of'" + " or 'sum of:' or 'max of:' - " + expl);
                    float sum     = 0;
                    float product = 1;
                    float max     = 0;
                    for (int i = 0; i < detail.Length; i++)
                    {
                        float dval = detail[i].Value;
                        VerifyExplanation(q, doc, dval, deep, detail[i]);
                        product *= dval;
                        sum     += dval;
                        max      = System.Math.Max(max, dval);
                    }
                    float combined = 0;
                    if (productOf)
                    {
                        combined = product;
                    }
                    else if (sumOf)
                    {
                        combined = sum;
                    }
                    else if (maxOf)
                    {
                        combined = max;
                    }
                    else if (maxTimesOthers)
                    {
                        combined = max + x * (sum - max);
                    }
                    else
                    {
                        Assert.IsTrue(false, "should never get here!");
                    }
                    Assert.AreEqual(combined, value_Renamed, EXPLAIN_SCORE_TOLERANCE_DELTA, q + ": actual subDetails combined==" + combined + " != value=" + value_Renamed + " Explanation: " + expl);
                }
            }
        }
        public virtual Explanation Explain(IndexReader reader, int doc)
        {
            ComplexExplanation result = new ComplexExplanation();
            result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");
            System.String field = ((SpanQuery) GetQuery()).GetField();

            System.Text.StringBuilder docFreqs = new System.Text.StringBuilder();
            System.Collections.IEnumerator i = terms.GetEnumerator();
            while (i.MoveNext())
            {
                System.Collections.DictionaryEntry tmp = (System.Collections.DictionaryEntry) i.Current;
                Term term = (Term) tmp.Key;
                docFreqs.Append(term.Text());
                docFreqs.Append("=");
                docFreqs.Append(reader.DocFreq(term));

                if (i.MoveNext())
                {
                    docFreqs.Append(" ");
                }
            }

            Explanation idfExpl = new Explanation(idf, "idf(" + field + ": " + docFreqs + ")");

            // explain query weight
            Explanation queryExpl = new Explanation();
            queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");

            Explanation boostExpl = new Explanation(GetQuery().GetBoost(), "boost");
            if (GetQuery().GetBoost() != 1.0f)
                queryExpl.AddDetail(boostExpl);
            queryExpl.AddDetail(idfExpl);

            Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
            queryExpl.AddDetail(queryNormExpl);

            queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());

            result.AddDetail(queryExpl);

            // explain field weight
            ComplexExplanation fieldExpl = new ComplexExplanation();
            fieldExpl.SetDescription("fieldWeight(" + field + ":" + query.ToString(field) + " in " + doc + "), product of:");

            Explanation tfExpl = Scorer(reader).Explain(doc);
            fieldExpl.AddDetail(tfExpl);
            fieldExpl.AddDetail(idfExpl);

            Explanation fieldNormExpl = new Explanation();
            byte[] fieldNorms = reader.Norms(field);
            float fieldNorm = fieldNorms != null ? Similarity.DecodeNorm(fieldNorms[doc]) : 0.0f;
            fieldNormExpl.SetValue(fieldNorm);
            fieldNormExpl.SetDescription("fieldNorm(field=" + field + ", doc=" + doc + ")");
            fieldExpl.AddDetail(fieldNormExpl);

            fieldExpl.SetMatch(tfExpl.IsMatch());
            fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());

            result.AddDetail(fieldExpl);
            System.Boolean tempAux = fieldExpl.GetMatch();
            result.SetMatch(tempAux);

            // combine them
            result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());

            if (queryExpl.GetValue() == 1.0f)
                return fieldExpl;

            return result;
        }
 public override Explanation CustomExplain(int doc, Explanation subQueryExpl, Explanation[] valSrcExpls)
 {
     if (valSrcExpls.Length == 0)
     {
         return subQueryExpl;
     }
     Explanation exp = new Explanation(valSrcExpls[0].Value + subQueryExpl.Value, "sum of:");
     exp.AddDetail(subQueryExpl);
     exp.AddDetail(valSrcExpls[0]);
     if (valSrcExpls.Length == 1)
     {
         exp.Description = "CustomMulAdd, sum of:";
         return exp;
     }
     Explanation exp2 = new Explanation(valSrcExpls[1].Value * exp.Value, "custom score: product of:");
     exp2.AddDetail(valSrcExpls[1]);
     exp2.AddDetail(exp);
     return exp2;
 }
 internal virtual Explanation DoExplain(AtomicReaderContext info, int doc)
 {
     var subQueryExpl = subQueryWeight.Explain(info, doc);
     if (!subQueryExpl.IsMatch)
     {
         return subQueryExpl;
     }
     // match
     var valSrcExpls = new Explanation[valSrcWeights.Length];
     for (int i = 0; i < valSrcWeights.Length; i++)
     {
         valSrcExpls[i] = valSrcWeights[i].Explain(info, doc);
     }
     Explanation customExp = outerInstance.GetCustomScoreProvider(info)
         .CustomExplain(doc, subQueryExpl, valSrcExpls);
     float sc = outerInstance.Boost * customExp.Value;
     Explanation res = new ComplexExplanation(true, sc, outerInstance.ToString() + ", product of:");
     res.AddDetail(customExp);
     res.AddDetail(new Explanation(outerInstance.Boost, "queryBoost"));
     // actually using the q boost as q weight (== weight value)
     return res;
 }
			public virtual Explanation Explain(IndexReader reader, int doc)
			{
				Explanation result = new Explanation();
				result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");
				
				Explanation idfExpl = new Explanation(idf, "idf(" + GetQuery() + ")");
				
				// explain query weight
				Explanation queryExpl = new Explanation();
				queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");
				
				Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");
				if (Enclosing_Instance.GetBoost() != 1.0f)
					queryExpl.AddDetail(boostExpl);
				
				queryExpl.AddDetail(idfExpl);
				
				Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
				queryExpl.AddDetail(queryNormExpl);
				
				queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());
				
				result.AddDetail(queryExpl);
				
				// explain field weight
				Explanation fieldExpl = new Explanation();
				fieldExpl.SetDescription("fieldWeight(" + GetQuery() + " in " + doc + "), product of:");
				
				Explanation tfExpl = Scorer(reader).Explain(doc);
				fieldExpl.AddDetail(tfExpl);
				fieldExpl.AddDetail(idfExpl);
				
				Explanation fieldNormExpl = new Explanation();
				byte[] fieldNorms = reader.Norms(Enclosing_Instance.field);
				float fieldNorm = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]):0.0f;
				fieldNormExpl.SetValue(fieldNorm);
				fieldNormExpl.SetDescription("fieldNorm(field=" + Enclosing_Instance.field + ", doc=" + doc + ")");
				fieldExpl.AddDetail(fieldNormExpl);
				
				fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());
				
				result.AddDetail(fieldExpl);
				
				// combine them
				result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());
				
				if (queryExpl.GetValue() == 1.0f)
					return fieldExpl;
				
				return result;
			}
Exemple #44
0
		public double Score(Rectangle target, Explanation exp)
		{
			if (target == null || queryArea <= 0)
			{
				return 0;
			}
			double targetArea = target.GetArea(null);
			if (targetArea <= 0)
			{
				return 0;
			}
			double score = 0;

			double top = Math.Min(queryExtent.GetMaxY(), target.GetMaxY());
			double bottom = Math.Max(queryExtent.GetMinY(), target.GetMinY());
			double height = top - bottom;
			double width = 0;

			// queries that cross the date line
			if (queryExtent.GetCrossesDateLine())
			{
				// documents that cross the date line
				if (target.GetCrossesDateLine())
				{
					double left = Math.Max(queryExtent.GetMinX(), target.GetMinX());
					double right = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
					width = right + 360.0 - left;
				}
				else
				{
					double qryWestLeft = Math.Max(queryExtent.GetMinX(), target.GetMaxX());
					double qryWestRight = Math.Min(target.GetMaxX(), 180.0);
					double qryWestWidth = qryWestRight - qryWestLeft;
					if (qryWestWidth > 0)
					{
						width = qryWestWidth;
					}
					else
					{
						double qryEastLeft = Math.Max(target.GetMaxX(), -180.0);
						double qryEastRight = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
						double qryEastWidth = qryEastRight - qryEastLeft;
						if (qryEastWidth > 0)
						{
							width = qryEastWidth;
						}
					}
				}
			}
			else
			{ // queries that do not cross the date line

				if (target.GetCrossesDateLine())
				{
					double tgtWestLeft = Math.Max(queryExtent.GetMinX(), target.GetMinX());
					double tgtWestRight = Math.Min(queryExtent.GetMaxX(), 180.0);
					double tgtWestWidth = tgtWestRight - tgtWestLeft;
					if (tgtWestWidth > 0)
					{
						width = tgtWestWidth;
					}
					else
					{
						double tgtEastLeft = Math.Max(queryExtent.GetMinX(), -180.0);
						double tgtEastRight = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
						double tgtEastWidth = tgtEastRight - tgtEastLeft;
						if (tgtEastWidth > 0)
						{
							width = tgtEastWidth;
						}
					}
				}
				else
				{
					double left = Math.Max(queryExtent.GetMinX(), target.GetMinX());
					double right = Math.Min(queryExtent.GetMaxX(), target.GetMaxX());
					width = right - left;
				}
			}


			// calculate the score
			if ((width > 0) && (height > 0))
			{
				double intersectionArea = width * height;
				double queryRatio = intersectionArea / queryArea;
				double targetRatio = intersectionArea / targetArea;
				double queryFactor = Math.Pow(queryRatio, queryPower);
				double targetFactor = Math.Pow(targetRatio, targetPower);
				score = queryFactor * targetFactor * 10000.0;

				if (exp != null)
				{
					//        StringBuilder sb = new StringBuilder();
					//        sb.append("\nscore=").append(score);
					//        sb.append("\n  query=").append();
					//        sb.append("\n  target=").append(target.toString());
					//        sb.append("\n  intersectionArea=").append(intersectionArea);
					//        
					//        sb.append(" queryArea=").append(queryArea).append(" targetArea=").append(targetArea);
					//        sb.append("\n  queryRatio=").append(queryRatio).append(" targetRatio=").append(targetRatio);
					//        sb.append("\n  queryFactor=").append(queryFactor).append(" targetFactor=").append(targetFactor);
					//        sb.append(" (queryPower=").append(queryPower).append(" targetPower=").append(targetPower).append(")");

					exp.Value = (float) score;
					exp.Description = GetType().Name;

					Explanation e = null;

					exp.AddDetail(e = new Explanation((float)intersectionArea, "IntersectionArea"));
					e.AddDetail(new Explanation((float)width, "width; Query: " + queryExtent));
					e.AddDetail(new Explanation((float)height, "height; Target: " + target));

					exp.AddDetail(e = new Explanation((float)queryFactor, "Query"));
					e.AddDetail(new Explanation((float)queryArea, "area"));
					e.AddDetail(new Explanation((float)queryRatio, "ratio"));
					e.AddDetail(new Explanation((float)queryPower, "power"));

					exp.AddDetail(e = new Explanation((float)targetFactor, "Target"));
					e.AddDetail(new Explanation((float)targetArea, "area"));
					e.AddDetail(new Explanation((float)targetRatio, "ratio"));
					e.AddDetail(new Explanation((float)targetPower, "power"));
				}
			}
			else if (exp != null)
			{
				exp.Value = 0;
				exp.Description = "Shape does not intersect";
			}
			return score;
		}
Exemple #45
0
            public override Explanation Explain(AtomicReaderContext context, int doc)
            {
                int minShouldMatch         = outerInstance.MinimumNumberShouldMatch;
                ComplexExplanation sumExpl = new ComplexExplanation();

                sumExpl.Description = "sum of:";
                int   coord                       = 0;
                float sum                         = 0.0f;
                bool  fail                        = false;
                int   shouldMatchCount            = 0;
                IEnumerator <BooleanClause> cIter = outerInstance.clauses.GetEnumerator();

                for (IEnumerator <Weight> wIter = m_weights.GetEnumerator(); wIter.MoveNext();)
                {
                    Weight w = wIter.Current;
                    cIter.MoveNext();
                    BooleanClause c = cIter.Current;
                    if (w.GetScorer(context, context.AtomicReader.LiveDocs) == null)
                    {
                        if (c.IsRequired)
                        {
                            fail = true;
                            Explanation r = new Explanation(0.0f, "no match on required clause (" + c.Query.ToString() + ")");
                            sumExpl.AddDetail(r);
                        }
                        continue;
                    }
                    Explanation e = w.Explain(context, doc);
                    if (e.IsMatch)
                    {
                        if (!c.IsProhibited)
                        {
                            sumExpl.AddDetail(e);
                            sum += e.Value;
                            coord++;
                        }
                        else
                        {
                            Explanation r = new Explanation(0.0f, "match on prohibited clause (" + c.Query.ToString() + ")");
                            r.AddDetail(e);
                            sumExpl.AddDetail(r);
                            fail = true;
                        }
                        if (c.Occur == Occur_e.SHOULD)
                        {
                            shouldMatchCount++;
                        }
                    }
                    else if (c.IsRequired)
                    {
                        Explanation r = new Explanation(0.0f, "no match on required clause (" + c.Query.ToString() + ")");
                        r.AddDetail(e);
                        sumExpl.AddDetail(r);
                        fail = true;
                    }
                }
                if (fail)
                {
                    sumExpl.Match       = false;
                    sumExpl.Value       = 0.0f;
                    sumExpl.Description = "Failure to meet condition(s) of required/prohibited clause(s)";
                    return(sumExpl);
                }
                else if (shouldMatchCount < minShouldMatch)
                {
                    sumExpl.Match       = false;
                    sumExpl.Value       = 0.0f;
                    sumExpl.Description = "Failure to match minimum number " + "of optional clauses: " + minShouldMatch;
                    return(sumExpl);
                }

                sumExpl.Match = 0 < coord ? true : false;
                sumExpl.Value = sum;

                float coordFactor = disableCoord ? 1.0f : Coord(coord, m_maxCoord);

                if (coordFactor == 1.0f)
                {
                    return(sumExpl); // eliminate wrapper
                }
                else
                {
                    ComplexExplanation result = new ComplexExplanation(sumExpl.IsMatch, sum * coordFactor, "product of:");
                    result.AddDetail(sumExpl);
                    result.AddDetail(new Explanation(coordFactor, "coord(" + coord + "/" + m_maxCoord + ")"));
                    return(result);
                }
            }
            public override Explanation Explain(IndexReader reader, int doc)
            {
                ComplexExplanation result = new ComplexExplanation();

                result.Description = "weight(" + Query + " in " + doc + "), product of:";

                Explanation expl = new Explanation(idf, idfExp.Explain());

                // explain query weight
                Explanation queryExpl = new Explanation();

                queryExpl.Description = "queryWeight(" + Query + "), product of:";

                Explanation boostExpl = new Explanation(Enclosing_Instance.Boost, "boost");

                if (Enclosing_Instance.Boost != 1.0f)
                {
                    queryExpl.AddDetail(boostExpl);
                }
                queryExpl.AddDetail(expl);

                Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");

                queryExpl.AddDetail(queryNormExpl);

                queryExpl.Value = boostExpl.Value * expl.Value * queryNormExpl.Value;

                result.AddDetail(queryExpl);

                // explain field weight
                System.String      field     = Enclosing_Instance.term.Field;
                ComplexExplanation fieldExpl = new ComplexExplanation();

                fieldExpl.Description = "fieldWeight(" + Enclosing_Instance.term + " in " + doc + "), product of:";

                Explanation tfExplanation = new Explanation();
                int         tf            = 0;
                TermDocs    termDocs      = reader.TermDocs(enclosingInstance.term);

                if (termDocs != null)
                {
                    try
                    {
                        if (termDocs.SkipTo(doc) && termDocs.Doc == doc)
                        {
                            tf = termDocs.Freq;
                        }
                    }
                    finally
                    {
                        termDocs.Close();
                    }
                    tfExplanation.Value       = similarity.Tf(tf);
                    tfExplanation.Description = "tf(termFreq(" + enclosingInstance.term + ")=" + tf + ")";
                }
                else
                {
                    tfExplanation.Value       = 0.0f;
                    tfExplanation.Description = "no matching term";
                }
                fieldExpl.AddDetail(tfExplanation);
                fieldExpl.AddDetail(expl);

                Explanation fieldNormExpl = new Explanation();

                byte[] fieldNorms = reader.Norms(field);
                float  fieldNorm  = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]) : 1.0f;

                fieldNormExpl.Value       = fieldNorm;
                fieldNormExpl.Description = "fieldNorm(field=" + field + ", doc=" + doc + ")";
                fieldExpl.AddDetail(fieldNormExpl);

                fieldExpl.Match = tfExplanation.IsMatch;
                fieldExpl.Value = tfExplanation.Value * expl.Value * fieldNormExpl.Value;

                result.AddDetail(fieldExpl);
                System.Boolean?tempAux = fieldExpl.Match;
                result.Match = tempAux;

                // combine them
                result.Value = queryExpl.Value * fieldExpl.Value;

                if (queryExpl.Value == 1.0f)
                {
                    return(fieldExpl);
                }

                return(result);
            }
            public virtual Explanation Explain(IndexReader reader, int doc)
            {
                int minShouldMatch = Enclosing_Instance.GetMinimumNumberShouldMatch();
                ComplexExplanation sumExpl = new ComplexExplanation();
                sumExpl.SetDescription("sum of:");
                int coord = 0;
                int maxCoord = 0;
                float sum = 0.0f;
                bool fail = false;
                int shouldMatchCount = 0;
                for (int i = 0; i < weights.Count; i++)
                {
                    BooleanClause c = (BooleanClause) Enclosing_Instance.clauses[i];
                    Weight w = (Weight) weights[i];
                    Explanation e = w.Explain(reader, doc);
                    if (!c.IsProhibited())
                        maxCoord++;
                    if (e.IsMatch())
                    {
                        if (!c.IsProhibited())
                        {
                            sumExpl.AddDetail(e);
                            sum += e.GetValue();
                            coord++;
                        }
                        else
                        {
                            Explanation r = new Explanation(0.0f, "match on prohibited clause (" + c.GetQuery().ToString() + ")");
                            r.AddDetail(e);
                            sumExpl.AddDetail(r);
                            fail = true;
                        }
                        if (c.GetOccur().Equals(Occur.SHOULD))
                            shouldMatchCount++;
                    }
                    else if (c.IsRequired())
                    {
                        Explanation r = new Explanation(0.0f, "no match on required clause (" + c.GetQuery().ToString() + ")");
                        r.AddDetail(e);
                        sumExpl.AddDetail(r);
                        fail = true;
                    }
                }
                if (fail)
                {
                    System.Boolean tempAux = false;
                    sumExpl.SetMatch(tempAux);
                    sumExpl.SetValue(0.0f);
                    sumExpl.SetDescription("Failure to meet condition(s) of required/prohibited clause(s)");
                    return sumExpl;
                }
                else if (shouldMatchCount < minShouldMatch)
                {
                    System.Boolean tempAux2 = false;
                    sumExpl.SetMatch(tempAux2);
                    sumExpl.SetValue(0.0f);
                    sumExpl.SetDescription("Failure to match minimum number " + "of optional clauses: " + minShouldMatch);
                    return sumExpl;
                }

                sumExpl.SetMatch(0 < coord ? true : false);
                sumExpl.SetValue(sum);

                float coordFactor = similarity.Coord(coord, maxCoord);
                if (coordFactor == 1.0f)
                // coord is no-op
                    return sumExpl;
                // eliminate wrapper
                else
                {
                    ComplexExplanation result = new ComplexExplanation(sumExpl.IsMatch(), sum * coordFactor, "product of:");
                    result.AddDetail(sumExpl);
                    result.AddDetail(new Explanation(coordFactor, "coord(" + coord + "/" + maxCoord + ")"));
                    return result;
                }
            }
Exemple #48
0
            public virtual Explanation Explain(IndexReader reader, int doc)
            {
                Explanation sumExpl = new Explanation();

                sumExpl.SetDescription("sum of:");
                int   coord    = 0;
                int   maxCoord = 0;
                float sum      = 0.0f;

                for (int i = 0; i < weights.Count; i++)
                {
                    BooleanClause c = (BooleanClause)Enclosing_Instance.clauses[i];
                    Weight        w = (Weight)weights[i];
                    Explanation   e = w.Explain(reader, doc);
                    if (!c.IsProhibited())
                    {
                        maxCoord++;
                    }
                    if (e.GetValue() > 0)
                    {
                        if (!c.IsProhibited())
                        {
                            sumExpl.AddDetail(e);
                            sum += e.GetValue();
                            coord++;
                        }
                        else
                        {
                            return(new Explanation(0.0f, "match prohibited"));
                        }
                    }
                    else if (c.IsRequired())
                    {
                        return(new Explanation(0.0f, "match required"));
                    }
                }
                sumExpl.SetValue(sum);

                if (coord == 1)
                {
                    // only one clause matched
                    sumExpl = sumExpl.GetDetails()[0];                     // eliminate wrapper
                }
                float coordFactor = similarity.Coord(coord, maxCoord);

                if (coordFactor == 1.0f)
                {
                    // coord is no-op
                    return(sumExpl);
                }
                // eliminate wrapper
                else
                {
                    Explanation result = new Explanation();
                    result.SetDescription("product of:");
                    result.AddDetail(sumExpl);
                    result.AddDetail(new Explanation(coordFactor, "coord(" + coord + "/" + maxCoord + ")"));
                    result.SetValue(sum * coordFactor);
                    return(result);
                }
            }