/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ #define C_LUCY_POLYQUERY #define C_LUCY_POLYCOMPILER #include "Lucy/Util/ToolSet.h" #include "Lucy/Search/PolyQuery.h" #include "Lucy/Index/DocVector.h" #include "Lucy/Index/Similarity.h" #include "Lucy/Plan/Schema.h" #include "Lucy/Search/Searcher.h" #include "Lucy/Search/Span.h" #include "Lucy/Store/InStream.h" #include "Lucy/Store/OutStream.h" #include "Lucy/Util/Freezer.h" PolyQuery* PolyQuery_init(PolyQuery *self, Vector *children) { const size_t num_kids = children ? Vec_Get_Size(children) : 0; Query_init((Query*)self, 1.0f); PolyQueryIVARS *const ivars = PolyQuery_IVARS(self); ivars->children = Vec_new(num_kids); for (size_t i = 0; i < num_kids; i++) { PolyQuery_Add_Child(self, (Query*)Vec_Fetch(children, i)); } return self; } void PolyQuery_Destroy_IMP(PolyQuery *self) { PolyQueryIVARS *const ivars = PolyQuery_IVARS(self); DECREF(ivars->children); SUPER_DESTROY(self, POLYQUERY); } void PolyQuery_Add_Child_IMP(PolyQuery *self, Query *query) { CERTIFY(query, QUERY); PolyQueryIVARS *const ivars = PolyQuery_IVARS(self); Vec_Push(ivars->children, INCREF(query)); } void PolyQuery_Set_Children_IMP(PolyQuery *self, Vector *children) { PolyQueryIVARS *const ivars = PolyQuery_IVARS(self); Vector *temp = ivars->children; ivars->children = (Vector*)INCREF(children); DECREF(temp); } Vector* PolyQuery_Get_Children_IMP(PolyQuery *self) { return PolyQuery_IVARS(self)->children; } void PolyQuery_Serialize_IMP(PolyQuery *self, OutStream *outstream) { PolyQueryIVARS *const ivars = PolyQuery_IVARS(self); const uint32_t num_kids = (uint32_t)Vec_Get_Size(ivars->children); OutStream_Write_F32(outstream, ivars->boost); OutStream_Write_U32(outstream, num_kids); for (uint32_t i = 0; i < num_kids; i++) { Query *child = (Query*)Vec_Fetch(ivars->children, i); FREEZE(child, outstream); } } PolyQuery* PolyQuery_Deserialize_IMP(PolyQuery *self, InStream *instream) { float boost = InStream_Read_F32(instream); uint32_t num_children = InStream_Read_U32(instream); PolyQuery_init(self, NULL); PolyQueryIVARS *const ivars = PolyQuery_IVARS(self); PolyQuery_Set_Boost(self, boost); Vec_Grow(ivars->children, num_children); while (num_children--) { Vec_Push(ivars->children, THAW(instream)); } return self; } Obj* PolyQuery_Dump_IMP(PolyQuery *self) { PolyQueryIVARS *ivars = PolyQuery_IVARS(self); PolyQuery_Dump_t super_dump = SUPER_METHOD_PTR(POLYQUERY, LUCY_PolyQuery_Dump); Hash *dump = (Hash*)CERTIFY(super_dump(self), HASH); Hash_Store_Utf8(dump, "children", 8, Freezer_dump((Obj*)ivars->children)); return (Obj*)dump; } Obj* PolyQuery_Load_IMP(PolyQuery *self, Obj *dump) { Hash *source = (Hash*)CERTIFY(dump, HASH); PolyQuery_Load_t super_load = SUPER_METHOD_PTR(POLYQUERY, LUCY_PolyQuery_Load); PolyQuery *loaded = (PolyQuery*)super_load(self, dump); Obj *children = CERTIFY(Hash_Fetch_Utf8(source, "children", 8), OBJ); PolyQuery_IVARS(loaded)->children = (Vector*)CERTIFY(Freezer_load(children), VECTOR); return (Obj*)loaded; } bool PolyQuery_Equals_IMP(PolyQuery *self, Obj *other) { if ((PolyQuery*)other == self) { return true; } if (!Obj_is_a(other, POLYQUERY)) { return false; } PolyQueryIVARS *const ivars = PolyQuery_IVARS(self); PolyQueryIVARS *const ovars = PolyQuery_IVARS((PolyQuery*)other); if (ivars->boost != ovars->boost) { return false; } if (!Vec_Equals(ovars->children, (Obj*)ivars->children)) { return false; } return true; } /**********************************************************************/ PolyCompiler* PolyCompiler_init(PolyCompiler *self, PolyQuery *parent, Searcher *searcher, float boost) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); PolyQueryIVARS *const parent_ivars = PolyQuery_IVARS(parent); const size_t num_kids = Vec_Get_Size(parent_ivars->children); Compiler_init((Compiler*)self, (Query*)parent, searcher, NULL, boost); ivars->children = Vec_new(num_kids); // Iterate over the children, creating a Compiler for each one. for (size_t i = 0; i < num_kids; i++) { Query *child_query = (Query*)Vec_Fetch(parent_ivars->children, i); float sub_boost = boost * Query_Get_Boost(child_query); Compiler *child_compiler = Query_Make_Compiler(child_query, searcher, sub_boost, true); Vec_Push(ivars->children, (Obj*)child_compiler); } return self; } void PolyCompiler_Destroy_IMP(PolyCompiler *self) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); DECREF(ivars->children); SUPER_DESTROY(self, POLYCOMPILER); } float PolyCompiler_Sum_Of_Squared_Weights_IMP(PolyCompiler *self) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); float sum = 0; float my_boost = PolyCompiler_Get_Boost(self); for (size_t i = 0, max = Vec_Get_Size(ivars->children); i < max; i++) { Compiler *child = (Compiler*)Vec_Fetch(ivars->children, i); sum += Compiler_Sum_Of_Squared_Weights(child); } // Compound the weight of each child. sum *= my_boost * my_boost; return sum; } void PolyCompiler_Apply_Norm_Factor_IMP(PolyCompiler *self, float factor) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); for (size_t i = 0, max = Vec_Get_Size(ivars->children); i < max; i++) { Compiler *child = (Compiler*)Vec_Fetch(ivars->children, i); Compiler_Apply_Norm_Factor(child, factor); } } Vector* PolyCompiler_Highlight_Spans_IMP(PolyCompiler *self, Searcher *searcher, DocVector *doc_vec, String *field) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); Vector *spans = Vec_new(0); for (size_t i = 0, max = Vec_Get_Size(ivars->children); i < max; i++) { Compiler *child = (Compiler*)Vec_Fetch(ivars->children, i); Vector *child_spans = Compiler_Highlight_Spans(child, searcher, doc_vec, field); if (child_spans) { Vec_Push_All(spans, child_spans); DECREF(child_spans); } } return spans; } void PolyCompiler_Serialize_IMP(PolyCompiler *self, OutStream *outstream) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); Freezer_serialize_string(PolyCompiler_get_class_name(self), outstream); Freezer_serialize_varray(ivars->children, outstream); PolyCompiler_Serialize_t super_serialize = SUPER_METHOD_PTR(POLYCOMPILER, LUCY_PolyCompiler_Serialize); super_serialize(self, outstream); } PolyCompiler* PolyCompiler_Deserialize_IMP(PolyCompiler *self, InStream *instream) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); String *class_name = Freezer_read_string(instream); DECREF(class_name); // TODO Don't serialize class name. ivars->children = Freezer_read_varray(instream); PolyCompiler_Deserialize_t super_deserialize = SUPER_METHOD_PTR(POLYCOMPILER, LUCY_PolyCompiler_Deserialize); return super_deserialize(self, instream); }