• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "lang_id/common/fel/feature-extractor.h"
18 
19 #include "lang_id/common/fel/feature-types.h"
20 #include "lang_id/common/fel/fel-parser.h"
21 #include "lang_id/common/lite_base/logging.h"
22 #include "lang_id/common/lite_strings/numbers.h"
23 
24 namespace libtextclassifier3 {
25 namespace mobile {
26 
27 constexpr FeatureValue GenericFeatureFunction::kNone;
28 
GenericFeatureExtractor()29 GenericFeatureExtractor::GenericFeatureExtractor() {}
30 
~GenericFeatureExtractor()31 GenericFeatureExtractor::~GenericFeatureExtractor() {}
32 
Parse(const string & source)33 bool GenericFeatureExtractor::Parse(const string &source) {
34   // Parse feature specification into descriptor.
35   FELParser parser;
36 
37   if (!parser.Parse(source, mutable_descriptor())) {
38     SAFTM_LOG(ERROR) << "Error parsing the FEL spec " << source;
39     return false;
40   }
41 
42   // Initialize feature extractor from descriptor.
43   return InitializeFeatureFunctions();
44 }
45 
InitializeFeatureTypes()46 bool GenericFeatureExtractor::InitializeFeatureTypes() {
47   // Register all feature types.
48   GetFeatureTypes(&feature_types_);
49   for (size_t i = 0; i < feature_types_.size(); ++i) {
50     FeatureType *ft = feature_types_[i];
51     ft->set_base(i);
52 
53     // Check for feature space overflow.
54     double domain_size = ft->GetDomainSize();
55     if (domain_size < 0) {
56       SAFTM_LOG(ERROR) << "Illegal domain size for feature " << ft->name()
57                        << ": " << domain_size;
58       return false;
59     }
60   }
61   return true;
62 }
63 
GetParameter(const string & name,const string & default_value) const64 string GenericFeatureFunction::GetParameter(const string &name,
65                                             const string &default_value) const {
66   // Find named parameter in feature descriptor.
67   for (int i = 0; i < descriptor_->parameter_size(); ++i) {
68     if (name == descriptor_->parameter(i).name()) {
69       return descriptor_->parameter(i).value();
70     }
71   }
72   return default_value;
73 }
74 
GenericFeatureFunction()75 GenericFeatureFunction::GenericFeatureFunction() {}
76 
~GenericFeatureFunction()77 GenericFeatureFunction::~GenericFeatureFunction() { delete feature_type_; }
78 
GetIntParameter(const string & name,int default_value) const79 int GenericFeatureFunction::GetIntParameter(const string &name,
80                                             int default_value) const {
81   string value_str = GetParameter(name, "");
82   if (value_str.empty()) {
83     // Parameter not specified, use default value for it.
84     return default_value;
85   }
86   int value = 0;
87   if (!LiteAtoi(value_str, &value)) {
88     SAFTM_LOG(DFATAL) << "Unable to parse '" << value_str
89                       << "' as int for parameter " << name;
90     return default_value;
91   }
92   return value;
93 }
94 
GetBoolParameter(const string & name,bool default_value) const95 bool GenericFeatureFunction::GetBoolParameter(const string &name,
96                                               bool default_value) const {
97   string value = GetParameter(name, "");
98   if (value.empty()) return default_value;
99   if (value == "true") return true;
100   if (value == "false") return false;
101   SAFTM_LOG(DFATAL) << "Illegal value '" << value << "' for bool parameter "
102                     << name;
103   return default_value;
104 }
105 
GetFeatureTypes(std::vector<FeatureType * > * types) const106 void GenericFeatureFunction::GetFeatureTypes(
107     std::vector<FeatureType *> *types) const {
108   if (feature_type_ != nullptr) types->push_back(feature_type_);
109 }
110 
GetFeatureType() const111 FeatureType *GenericFeatureFunction::GetFeatureType() const {
112   // If a single feature type has been registered return it.
113   if (feature_type_ != nullptr) return feature_type_;
114 
115   // Get feature types for function.
116   std::vector<FeatureType *> types;
117   GetFeatureTypes(&types);
118 
119   // If there is exactly one feature type return this, else return null.
120   if (types.size() == 1) return types[0];
121   return nullptr;
122 }
123 
name() const124 string GenericFeatureFunction::name() const {
125   string output;
126   if (descriptor_->name().empty()) {
127     if (!prefix_.empty()) {
128       output.append(prefix_);
129       output.append(".");
130     }
131     ToFEL(*descriptor_, &output);
132   } else {
133     output = descriptor_->name();
134   }
135   return output;
136 }
137 
138 }  // namespace mobile
139 }  // namespace nlp_saft
140