You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2010/06/22 08:23:12 UTC

svn commit: r956785 - in /lucene/lucy/trunk: core/Lucy/Search/RequiredOptionalScorer.bp core/Lucy/Search/RequiredOptionalScorer.c perl/lib/Lucy/Search/RequiredOptionalScorer.pm perl/t/519-req_opt_scorer.t

Author: marvin
Date: Tue Jun 22 06:23:12 2010
New Revision: 956785

URL: http://svn.apache.org/viewvc?rev=956785&view=rev
Log:
LUCY-117:
Add RequiredOptionalScorer.
(req_opt_scorer.patch)

Added:
    lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.bp   (with props)
    lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.c   (with props)
    lucene/lucy/trunk/perl/lib/Lucy/Search/RequiredOptionalScorer.pm   (with props)
    lucene/lucy/trunk/perl/t/519-req_opt_scorer.t   (with props)

Added: lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.bp?rev=956785&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.bp (added)
+++ lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.bp Tue Jun 22 06:23:12 2010
@@ -0,0 +1,51 @@
+parcel Lucy;
+
+/** Intersect required and optional scorers.
+ */
+
+class Lucy::Search::RequiredOptionalScorer cnick ReqOptScorer
+    extends Lucy::Search::PolyMatcher {
+
+    Matcher      *req_matcher;
+    Matcher      *opt_matcher;
+    bool_t        opt_matcher_first_time;
+
+    inert incremented RequiredOptionalScorer* 
+    new(Similarity *similarity, Matcher *required_matcher, 
+        Matcher *optional_matcher);
+
+    inert RequiredOptionalScorer* 
+    init(RequiredOptionalScorer *self, Similarity *similarity, 
+         Matcher *required_matcher, Matcher *optional_matcher);
+
+    public void
+    Destroy(RequiredOptionalScorer *self);
+
+    public int32_t
+    Next(RequiredOptionalScorer *self);
+
+    public int32_t
+    Advance(RequiredOptionalScorer *self, int32_t target);
+
+    public float
+    Score(RequiredOptionalScorer *self);
+
+    public int32_t 
+    Get_Doc_ID(RequiredOptionalScorer *self);
+}
+
+/* Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.bp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.c?rev=956785&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.c (added)
+++ lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.c Tue Jun 22 06:23:12 2010
@@ -0,0 +1,117 @@
+#define C_LUCY_REQUIREDOPTIONALSCORER
+#include "Lucy/Util/ToolSet.h"
+
+#include "Lucy/Search/RequiredOptionalScorer.h"
+#include "Lucy/Index/Similarity.h"
+
+RequiredOptionalScorer*
+ReqOptScorer_new(Similarity *similarity, Matcher *required_matcher, 
+                 Matcher *optional_matcher) 
+{
+    RequiredOptionalScorer *self 
+        = (RequiredOptionalScorer*)VTable_Make_Obj(REQUIREDOPTIONALSCORER);
+    return ReqOptScorer_init(self, similarity, required_matcher, 
+        optional_matcher);
+}
+
+RequiredOptionalScorer*
+ReqOptScorer_init(RequiredOptionalScorer *self, Similarity *similarity, 
+                  Matcher *required_matcher, Matcher *optional_matcher) 
+{
+    VArray *children = VA_new(2);
+    VA_Push(children, INCREF(required_matcher));
+    VA_Push(children, INCREF(optional_matcher));
+    PolyMatcher_init((PolyMatcher*)self, children, similarity);
+
+    // Assign. 
+    self->req_matcher       = (Matcher*)INCREF(required_matcher);
+    self->opt_matcher       = (Matcher*)INCREF(optional_matcher);
+
+    // Init. 
+    self->opt_matcher_first_time = true;
+
+    DECREF(children);
+    return self;
+}
+
+void
+ReqOptScorer_destroy(RequiredOptionalScorer *self) 
+{
+    DECREF(self->req_matcher);
+    DECREF(self->opt_matcher);
+    SUPER_DESTROY(self, REQUIREDOPTIONALSCORER);
+}
+
+int32_t
+ReqOptScorer_next(RequiredOptionalScorer *self)
+{
+    return Matcher_Next(self->req_matcher);
+}
+
+int32_t
+ReqOptScorer_advance(RequiredOptionalScorer *self, int32_t target)
+{
+    return Matcher_Advance(self->req_matcher, target);
+}
+
+int32_t
+ReqOptScorer_get_doc_id(RequiredOptionalScorer *self)
+{
+    return Matcher_Get_Doc_ID(self->req_matcher);
+}
+
+float
+ReqOptScorer_score(RequiredOptionalScorer *self)
+{
+    int32_t const current_doc = Matcher_Get_Doc_ID(self->req_matcher);
+
+    if (self->opt_matcher_first_time) {
+        self->opt_matcher_first_time = false;
+        if ( !Matcher_Advance(self->opt_matcher, current_doc) ) {
+            DECREF(self->opt_matcher);
+            self->opt_matcher = NULL;
+        }
+    }
+
+    if (self->opt_matcher == NULL) {
+        return Matcher_Score(self->req_matcher);
+    }
+    else {
+        int32_t opt_matcher_doc = Matcher_Get_Doc_ID(self->opt_matcher);
+
+        if (opt_matcher_doc < current_doc) {
+            opt_matcher_doc = Matcher_Advance(self->opt_matcher, current_doc);
+            if (!opt_matcher_doc) {
+                DECREF(self->opt_matcher);
+                self->opt_matcher = NULL;
+                return Matcher_Score(self->req_matcher);
+            }
+        }
+
+        if (opt_matcher_doc == current_doc) {
+            float score = Matcher_Score(self->req_matcher)
+                        + Matcher_Score(self->opt_matcher);
+            score *= self->coord_factors[2];
+            return score;
+        }
+        else {
+            return Matcher_Score(self->req_matcher);
+        }
+    }
+}
+
+/* Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Search/RequiredOptionalScorer.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/perl/lib/Lucy/Search/RequiredOptionalScorer.pm
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/lib/Lucy/Search/RequiredOptionalScorer.pm?rev=956785&view=auto
==============================================================================
--- lucene/lucy/trunk/perl/lib/Lucy/Search/RequiredOptionalScorer.pm (added)
+++ lucene/lucy/trunk/perl/lib/Lucy/Search/RequiredOptionalScorer.pm Tue Jun 22 06:23:12 2010
@@ -0,0 +1,33 @@
+package Lucy::Search::RequiredOptionalScorer;
+use Lucy;
+
+1;
+
+__END__
+
+__BINDING__
+
+Clownfish::Binding::Perl::Class->register(
+    parcel            => "Lucy",
+    class_name        => "Lucy::Search::RequiredOptionalScorer",
+    bind_constructors => ["new"],
+);
+
+__COPYRIGHT__
+
+    /**
+     * Copyright 2010 The Apache Software Foundation
+     *
+     * Licensed under the Apache License, Version 2.0 (the "License");
+     * you may not use this file except in compliance with the License.
+     * You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+     * implied.  See the License for the specific language governing
+     * permissions and limitations under the License.
+     */
+

Propchange: lucene/lucy/trunk/perl/lib/Lucy/Search/RequiredOptionalScorer.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/perl/t/519-req_opt_scorer.t
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/t/519-req_opt_scorer.t?rev=956785&view=auto
==============================================================================
--- lucene/lucy/trunk/perl/t/519-req_opt_scorer.t (added)
+++ lucene/lucy/trunk/perl/t/519-req_opt_scorer.t Tue Jun 22 06:23:12 2010
@@ -0,0 +1,77 @@
+use strict;
+use warnings;
+use lib 'buildlib';
+
+use Test::More skip_all => 'requires SortCollector';
+# use Test::More tests => 726;
+use Lucy::Test;
+use LucyX::Search::MockScorer;
+use Lucy::Test::TestUtils qw( modulo_set doc_ids_from_td_coll );
+
+my $sim = Lucy::Index::Similarity::LuceneSimilarity->new;
+
+for my $req_interval ( 1 .. 10, 75 ) {
+    for my $opt_interval ( 1 .. 10, 75 ) {
+        check_scorer( $req_interval, $opt_interval );
+        check_scorer( $opt_interval, $req_interval );
+    }
+}
+
+sub check_scorer {
+    my ( $req_interval, $opt_interval ) = @_;
+    my $req_docs = modulo_set( $req_interval, 100 );
+    my $opt_docs = modulo_set( $opt_interval, 100 );
+    my $req_mock = LucyX::Search::MockScorer->new(
+        doc_ids => $req_docs,
+        scores  => [ (1) x scalar @$req_docs ],
+    );
+    my $opt_mock = LucyX::Search::MockScorer->new(
+        doc_ids => $opt_docs,
+        scores  => [ (1) x scalar @$opt_docs ],
+    );
+    my $req_opt_scorer = Lucy::Search::RequiredOptionalScorer->new(
+        similarity       => $sim,
+        required_matcher => $req_mock,
+        optional_matcher => $opt_mock,
+    );
+    my $collector
+        = Lucy::Search::Collector::SortCollector->new( wanted => 1000 );
+    $req_opt_scorer->collect( collector => $collector );
+    my ( $got_by_score, $got_by_id ) = doc_ids_from_td_coll($collector);
+    my ( $expected_by_count, $expected_by_id )
+        = calc_result_sets( $req_interval, $opt_interval );
+    is( scalar @$got_by_id,
+        scalar @$expected_by_id,
+        "total hits: $req_interval $opt_interval"
+    );
+
+    is_deeply( $got_by_id, $expected_by_id,
+        "got all docs: $req_interval $opt_interval" );
+
+    is_deeply( $got_by_score, $expected_by_count,
+        "scores accumulated: $req_interval $opt_interval" );
+}
+
+sub calc_result_sets {
+    my ( $req_interval, $opt_interval ) = @_;
+
+    my @good;
+    my @better;
+    for my $doc_id ( 1 .. 99 ) {
+        if ( $doc_id % $req_interval == 0 ) {
+            if ( $doc_id % $opt_interval == 0 ) {
+                push @better, $doc_id;
+            }
+            else {
+                push @good, $doc_id;
+            }
+        }
+    }
+    my @by_count_then_id = ( @better, @good );
+    my @by_id = sort { $a <=> $b } @by_count_then_id;
+
+    return ( \@by_count_then_id, \@by_id );
+}
+
+# Trigger destruction.
+undef $sim;

Propchange: lucene/lucy/trunk/perl/t/519-req_opt_scorer.t
------------------------------------------------------------------------------
    svn:eol-style = native