diff options
author | Haavard <havardpe@yahoo-inc.com> | 2017-02-23 15:13:44 +0000 |
---|---|---|
committer | Haavard <havardpe@yahoo-inc.com> | 2017-02-23 17:10:37 +0000 |
commit | 9cb7505ccdc58dcfaa341a9c54eee60d2d16531e (patch) | |
tree | 67baab933561ad0c3dbc55a597672a0a4842cade /searchlib/src/tests/fef | |
parent | beea9069a65cd3625ebbbd20fb386baeed091d24 (diff) |
lazy evaluate ranking expressions
Diffstat (limited to 'searchlib/src/tests/fef')
3 files changed, 91 insertions, 40 deletions
diff --git a/searchlib/src/tests/fef/featureoverride/featureoverride.cpp b/searchlib/src/tests/fef/featureoverride/featureoverride.cpp index 80389064a8f..e77e50a99c8 100644 --- a/searchlib/src/tests/fef/featureoverride/featureoverride.cpp +++ b/searchlib/src/tests/fef/featureoverride/featureoverride.cpp @@ -97,10 +97,10 @@ TEST_F("test decorator - transitive override", Fixture) FeatureExecutor *fe2 = &stash.create<DoubleExecutor>(3); fe2 = &stash.create<FeatureOverrider>(*fe2, 2, 10.0); - auto inputs = stash.create_array<const NumberOrObject *>(3); - inputs[0] = fe->outputs().get_raw(0); - inputs[1] = fe->outputs().get_raw(1); - inputs[2] = fe->outputs().get_raw(2); + auto inputs = stash.create_array<LazyValue>(3, nullptr); + inputs[0] = LazyValue(fe->outputs().get_raw(0), fe); + inputs[1] = LazyValue(fe->outputs().get_raw(1), fe); + inputs[2] = LazyValue(fe->outputs().get_raw(2), fe); fe2->bind_inputs(inputs); f.add(fe2, 3).run(); EXPECT_EQUAL(fe2->outputs().size(), 3u); @@ -143,9 +143,8 @@ TEST("test overrides") overrides.add("bogus(feature)", "10.0"); rankProgram->setup(mdl, queryEnv, overrides); - rankProgram->run(2); - std::map<vespalib::string, feature_t> res = Utils::getAllFeatures(*rankProgram); + std::map<vespalib::string, feature_t> res = Utils::getAllFeatures(*rankProgram, 2); EXPECT_EQUAL(res.size(), 20u); EXPECT_APPROX(res["value(1)"], 1.0, 1e-6); diff --git a/searchlib/src/tests/fef/object_passing/object_passing_test.cpp b/searchlib/src/tests/fef/object_passing/object_passing_test.cpp index 53f9b028e9d..d62be9b42fb 100644 --- a/searchlib/src/tests/fef/object_passing/object_passing_test.cpp +++ b/searchlib/src/tests/fef/object_passing/object_passing_test.cpp @@ -91,11 +91,10 @@ struct Fixture { Properties overrides; RankProgram program(resolver); program.setup(mdl, queryEnv, overrides); - program.run(1); auto result = program.get_seeds(); EXPECT_EQUAL(1u, result.num_features()); EXPECT_TRUE(!result.is_object(0)); // verifies auto-unboxing - return *result.resolve_number(0); + return result.resolve(0).as_number(1); } bool verify(const vespalib::string &feature) { diff --git a/searchlib/src/tests/fef/rank_program/rank_program_test.cpp b/searchlib/src/tests/fef/rank_program/rank_program_test.cpp index b70b78d8d28..91c266f2745 100644 --- a/searchlib/src/tests/fef/rank_program/rank_program_test.cpp +++ b/searchlib/src/tests/fef/rank_program/rank_program_test.cpp @@ -13,19 +13,47 @@ using namespace search::fef; using namespace search::fef::test; using namespace search::features; -size_t count_unique_features(const RankProgram &program) { - std::set<const NumberOrObject *> seen; +uint32_t default_docid = 1; + +void maybe_insert(const LazyValue &value, std::vector<LazyValue> &seen) { + for (const auto &entry: seen) { + if (value.is_same(entry)) { + return; + } + } + seen.push_back(value); +} + +std::vector<LazyValue> get_features(const RankProgram &program) { + std::vector<LazyValue> seen; auto unboxed = program.get_all_features(true); for (size_t i = 0; i < unboxed.num_features(); ++i) { - // fprintf(stderr, "seen feature (unboxed): %s\n", unboxed.name_of(i).c_str()); - seen.insert(unboxed.resolve_raw(i)); + maybe_insert(unboxed.resolve(i), seen); } auto maybe_boxed = program.get_all_features(false); for (size_t i = 0; i < maybe_boxed.num_features(); ++i) { - // fprintf(stderr, "seen feature (maybe boxed): %s\n", maybe_boxed.name_of(i).c_str()); - seen.insert(maybe_boxed.resolve_raw(i)); + maybe_insert(maybe_boxed.resolve(i), seen); } - return seen.size(); + return seen; +} + +template <typename Predicate> +size_t count(const RankProgram &program, Predicate pred) { + size_t cnt = 0; + for (const auto &value: get_features(program)) { + if (pred(value)) { + ++cnt; + } + } + return cnt; +} + +size_t count_features(const RankProgram &program) { + return count(program, [](const LazyValue &){ return true; }); +} + +size_t count_const_features(const RankProgram &program) { + return count(program, [](const LazyValue &value){ return value.is_const(); }); } struct ImpureValueExecutor : FeatureExecutor { @@ -51,6 +79,23 @@ struct ImpureValueBlueprint : Blueprint { } }; +struct DocidExecutor : FeatureExecutor { + void execute(uint32_t docid) override { outputs().set_number(0, docid); } +}; + +struct DocidBlueprint : Blueprint { + DocidBlueprint() : Blueprint("docid") {} + void visitDumpFeatures(const IIndexEnvironment &, IDumpFeatureVisitor &) const override {} + Blueprint::UP createInstance() const override { return Blueprint::UP(new DocidBlueprint()); } + bool setup(const IIndexEnvironment &, const std::vector<vespalib::string> &) override { + describeOutput("out", "the local document id"); + return true; + } + FeatureExecutor &createExecutor(const IQueryEnvironment &, vespalib::Stash &stash) const override { + return stash.create<DocidExecutor>(); + } +}; + struct MySetup { BlueprintFactory factory; IndexEnvironment indexEnv; @@ -63,6 +108,7 @@ struct MySetup { factory.addPrototype(Blueprint::SP(new ValueBlueprint())); factory.addPrototype(Blueprint::SP(new ImpureValueBlueprint())); factory.addPrototype(Blueprint::SP(new SumBlueprint())); + factory.addPrototype(Blueprint::SP(new DocidBlueprint())); } MySetup &add(const vespalib::string &feature) { resolver->addSeed(feature); @@ -79,20 +125,16 @@ struct MySetup { program.setup(mdl, queryEnv, overrides); return *this; } - MySetup &run() { - program.run(1); - return *this; - } - double get() { + double get(uint32_t docid = default_docid) { auto result = program.get_seeds(); EXPECT_EQUAL(1u, result.num_features()); - return *result.resolve_number(0); + return result.resolve(0).as_number(docid); } double get(const vespalib::string &feature) { auto result = program.get_seeds(); for (size_t i = 0; i < result.num_features(); ++i) { if (result.name_of(i) == feature) { - return *result.resolve_number(i); + return result.resolve(i).as_number(default_docid); } } return 31212.0; @@ -101,41 +143,42 @@ struct MySetup { auto result = program.get_seeds(); std::map<vespalib::string, double> result_map; for (size_t i = 0; i < result.num_features(); ++i) { - result_map[result.name_of(i)] = *result.resolve_number(i); + result_map[result.name_of(i)] = result.resolve(i).as_number(default_docid); } return result_map; } }; TEST_F("require that simple program works", MySetup()) { - EXPECT_EQUAL(15.0, f1.add("mysum(value(10),ivalue(5))").compile().run().get()); + EXPECT_EQUAL(15.0, f1.add("mysum(value(10),ivalue(5))").compile().get()); EXPECT_EQUAL(3u, f1.program.num_executors()); - EXPECT_EQUAL(2u, f1.program.program_size()); + EXPECT_EQUAL(3u, count_features(f1.program)); + EXPECT_EQUAL(1u, count_const_features(f1.program)); } -TEST_F("require that const features are calculated during setup", MySetup()) { +TEST_F("require that const features work", MySetup()) { f1.add("mysum(value(10),value(5))").compile(); EXPECT_EQUAL(15.0, f1.get()); EXPECT_EQUAL(3u, f1.program.num_executors()); - EXPECT_EQUAL(0u, f1.program.program_size()); + EXPECT_EQUAL(3u, count_features(f1.program)); + EXPECT_EQUAL(3u, count_const_features(f1.program)); } -TEST_F("require that non-const features are calculated during run", MySetup()) { +TEST_F("require that non-const features work", MySetup()) { f1.add("mysum(ivalue(10),ivalue(5))").compile(); - EXPECT_EQUAL(0.0, f1.get()); - f1.run(); EXPECT_EQUAL(15.0, f1.get()); EXPECT_EQUAL(3u, f1.program.num_executors()); - EXPECT_EQUAL(3u, f1.program.program_size()); + EXPECT_EQUAL(3u, count_features(f1.program)); + EXPECT_EQUAL(0u, count_const_features(f1.program)); } TEST_F("require that a single program can calculate multiple output features", MySetup()) { f1.add("value(1)").add("ivalue(2)").add("ivalue(3)"); f1.add("mysum(value(1),value(2),ivalue(3))"); - f1.compile().run(); + f1.compile(); EXPECT_EQUAL(5u, f1.program.num_executors()); - EXPECT_EQUAL(3u, f1.program.program_size()); - EXPECT_EQUAL(5u, count_unique_features(f1.program)); + EXPECT_EQUAL(5u, count_features(f1.program)); + EXPECT_EQUAL(2u, count_const_features(f1.program)); auto result = f1.all(); EXPECT_EQUAL(4u, result.size()); EXPECT_EQUAL(1.0, result["value(1)"]); @@ -146,20 +189,20 @@ TEST_F("require that a single program can calculate multiple output features", M TEST_F("require that a single executor can produce multiple features", MySetup()) { f1.add("mysum(value(1,2,3).0,value(1,2,3).1,value(1,2,3).2)"); - EXPECT_EQUAL(6.0, f1.compile().run().get()); + EXPECT_EQUAL(6.0, f1.compile().get()); EXPECT_EQUAL(2u, f1.program.num_executors()); - EXPECT_EQUAL(0u, f1.program.program_size()); - EXPECT_EQUAL(4u, count_unique_features(f1.program)); + EXPECT_EQUAL(4u, count_features(f1.program)); + EXPECT_EQUAL(4u, count_const_features(f1.program)); } TEST_F("require that feature values can be overridden", MySetup()) { f1.add("value(1)").add("ivalue(2)").add("ivalue(3)"); f1.add("mysum(value(1),value(2),ivalue(3))"); f1.override("value(2)", 20.0).override("ivalue(3)", 30.0); - f1.compile().run(); + f1.compile(); EXPECT_EQUAL(5u, f1.program.num_executors()); - EXPECT_EQUAL(3u, f1.program.program_size()); - EXPECT_EQUAL(5u, count_unique_features(f1.program)); + EXPECT_EQUAL(5u, count_features(f1.program)); + EXPECT_EQUAL(2u, count_const_features(f1.program)); auto result = f1.all(); EXPECT_EQUAL(4u, result.size()); EXPECT_EQUAL(1.0, result["value(1)"]); @@ -168,4 +211,14 @@ TEST_F("require that feature values can be overridden", MySetup()) { EXPECT_EQUAL(51.0, result["mysum(value(1),value(2),ivalue(3))"]); } +TEST_F("require that the rank program can calculate scores for multiple documents", MySetup()) { + f1.add("mysum(value(10),docid)").compile(); + EXPECT_EQUAL(3u, count_features(f1.program)); + EXPECT_EQUAL(1u, count_const_features(f1.program)); + EXPECT_EQUAL(f1.get(1), 11.0); + EXPECT_EQUAL(f1.get(2), 12.0); + EXPECT_EQUAL(f1.get(3), 13.0); + EXPECT_EQUAL(f1.get(1), 11.0); +} + TEST_MAIN() { TEST_RUN_ALL(); } |