LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
morph_model.h
Go to the documentation of this file.
1// Copyright 2002-2021 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6#ifndef DEEPLIMA_LIBS_MORPH_MODEL_H
7#define DEEPLIMA_LIBS_MORPH_MODEL_H
8
9#include <cstdint>
10#include <string>
11#include <vector>
12#include <set>
13#include <map>
14#include <unordered_map>
15#include <cassert>
16#include <limits>
17
18#ifndef NDEBUG
19#include <iostream>
21#endif
22
23namespace deeplima
24{
25namespace morph_model
26{
27
28typedef uint64_t feat_base_t;
29
36{
37 feat_base_t m_value;
38
39public:
40
42 : m_value(0) { }
44 : m_value(other.m_value) { }
46 : m_value(val) { }
47
48 inline void append(feat_base_t val)
49 {
50 assert((m_value & val) == 0);
51 m_value |= val;
52 }
53
54 inline bool operator==(const morph_feats_t other) const
55 {
56 return m_value == other.m_value;
57 }
58
59 inline bool operator!=(const morph_feats_t other) const
60 {
61 return m_value != other.m_value;
62 }
63
64 inline bool operator<(const morph_feats_t other) const
65 {
66 return m_value < other.m_value;
67 }
68
69 const feat_base_t& toBaseType() const
70 {
71 return m_value;
72 }
73
74 inline feat_base_t subvalue(feat_base_t mask, uint8_t offset) const
75 {
76 return (m_value & mask) >> offset;
77 }
78
79 inline auto hash() const
80 {
81 return std::hash<feat_base_t>{}(m_value);
82 }
83};
84
85class morph_model_builder;
86
93{
94 struct dict_t
95 {
96 std::unordered_map<std::string, size_t> m_key2id;
97 std::vector<std::string> m_id2key;
98
99 dict_t() { }
100 dict_t(const std::string& str);
101 static dict_t from_string(const std::string& str);
102
103 std::string to_string() const;
104
105 const std::vector<std::string>& get_vec_ref() const
106 {
107 return m_id2key;
108 }
109
110 size_t get_id(const std::string& name) const
111 {
112 auto it = m_key2id.find(name);
113 assert(m_key2id.end() != it);
114 // if (m_key2id.end() == it)
115 // {
116 // throw std::runtime_error(std::string("morph_model get_id unknown name ")+name);
117 // }
118 return it->second;
119 }
120
121 const std::string& get_key(size_t id) const
122 {
123 assert(id < m_id2key.size());
124 return m_id2key[id];
125 }
126
127 size_t add_key(const std::string& name)
128 {
129 if (m_key2id.end() == m_key2id.find(name))
130 {
131 m_id2key.push_back(name);
132 m_key2id[name] = m_id2key.size() - 1;
133 }
134 return get_id(name);
135 }
136
137 bool has(const std::string& name) const
138 {
139 auto it = m_key2id.find(name);
140 return m_key2id.end() != it;
141 }
142 };
143
144 dict_t m_upos_dict;
145 dict_t m_feat_dict;
146
147public:
149 morph_model_t(const std::string& str);
150 std::string to_string() const;
151 std::string to_string(const morph_feats_t& feats) const;
152
153 inline const std::vector<std::string>& get_feat_vec_ref(size_t feat_id) const
154 {
155 if (0 == feat_id)
156 {
157 return m_upos_dict.get_vec_ref();
158 }
159 return m_feats[feat_id].get_vec_ref();
160 }
161
162 size_t get_feats_count() const;
163 inline bool has_feat(const std::string& feat_name) const
164 {
165 return m_feat_dict.has(feat_name);
166 }
167
168 inline const std::string& get_feat_name(size_t feat_id) const
169 {
170 return m_feat_dict.get_key(feat_id);
171 }
172
173 inline size_t get_feat_idx(const std::string& feat_name) const
174 {
175 return m_feat_dict.get_id(feat_name);
176 }
177
178 inline feat_base_t decode_upos(const morph_feats_t& feats) const
179 {
180 return feats.subvalue(m_upos_mask, 0);
181 }
182
183 inline feat_base_t decode_feat(const morph_feats_t& feats, size_t feat_id) const
184 {
185 feat_base_t upos_id = decode_upos(feats);
186 assert(upos_id < m_feats2mask.size());
187 auto it = m_feats2mask[upos_id].find(feat_id);
188 if (m_feats2mask[upos_id].end() == it)
189 {
190 return feat_base_t(0);
191 }
192 size_t feat_mask_id = it->second;
193 return feats.subvalue(m_masks[feat_mask_id], m_offset[feat_mask_id]);
194 }
195
196 size_t get_upos_id(const std::string& name) const
197 {
198 return m_upos_dict.get_id(name);
199 }
200
201protected:
202 size_t add_upos(const std::string& name)
203 {
204 return m_upos_dict.add_key(name);
205 }
206
207 size_t get_feat_id(const std::string& name) const
208 {
209 return m_feat_dict.get_id(name);
210 }
211
212 size_t add_feat(const std::string& name)
213 {
214 return m_feat_dict.add_key(name);
215 }
216
218 {
219 uint8_t m_start;
220 uint8_t m_len;
221
223 : m_start(0), m_len(0) { }
224 };
225
226public:
228 // feat_value == ( feat_base & mask ) >> offset
229 std::vector<feat_base_t> m_masks; // mask_id -> mask
230 std::vector<uint8_t> m_offset; // mask_id -> offset
231
232 std::vector<std::map<size_t, size_t>> m_feats2mask; // upos_id -> (feat_id -> mask_id)
233 std::vector<dict_t> m_feats; // feat_id -> feat_values
234
235public:
236
237 morph_feats_t convert(const std::string& upos, const std::map<std::string, std::set<std::string>>& feats) const;
238
239 template <typename F>
240 morph_feats_t convert(F featid2value) const
241 {
242 auto upos_idx = m_feat_dict.get_id("upos");
243 assert(upos_idx != std::numeric_limits<size_t>::max());
244 auto upos_id = featid2value(upos_idx);
245 const std::map<std::string, std::set<std::string>> feats;
246
247 morph_feats_t v(upos_id);
248
249 const auto& feats2mask = m_feats2mask[upos_id];
250
251 for ( const auto& kv : feats2mask )
252 {
253 const auto feat_id = kv.first;
254 if (feat_id == upos_idx)
255 {
256 continue;
257 }
258
259 size_t mask_id = kv.second;
260 assert(mask_id < m_offset.size());
261 uint8_t offset = m_offset[mask_id];
262
263 size_t feat_value_id = featid2value(feat_id);
264 if (feat_value_id != std::numeric_limits<size_t>::max())
265 {
266 feat_value_id = feat_value_id << offset ;
267 v.append(feat_value_id);
268 }
269 }
270
271#ifndef NDEBUG
272 std::cerr << pretty_bits_to_string(v.toBaseType()) << " " << to_string(v) << std::endl;
273#endif
274
275 return v;
276 }
277
278 const std::string& decode_upos_to_str(const morph_feats_t& feats) const;
279
281};
282
283} // morph_model
284} // deeplima
285
286#endif
287
Encoding on one 64 bits integer of the set of morphological features for one token.
Definition morph_model.h:36
bool operator==(const morph_feats_t other) const
Definition morph_model.h:54
bool operator<(const morph_feats_t other) const
Definition morph_model.h:64
feat_base_t subvalue(feat_base_t mask, uint8_t offset) const
Definition morph_model.h:74
bool operator!=(const morph_feats_t other) const
Definition morph_model.h:59
const feat_base_t & toBaseType() const
Definition morph_model.h:69
morph_feats_t(const morph_feats_t &other)
Definition morph_model.h:43
Helper class for morphology data (upos, features) binarization.
Definition morph_model.h:93
size_t get_feat_idx(const std::string &feat_name) const
bool has_feat(const std::string &feat_name) const
const std::string & decode_upos_to_str(const morph_feats_t &feats) const
morph_feats_t convert(F featid2value) const
std::vector< std::map< size_t, size_t > > m_feats2mask
size_t get_feat_id(const std::string &name) const
size_t get_upos_id(const std::string &name) const
morph_feats_t convert(const std::string &upos, const std::map< std::string, std::set< std::string > > &feats) const
std::vector< uint8_t > m_offset
const std::vector< std::string > & get_feat_vec_ref(size_t feat_id) const
const std::string & get_feat_name(size_t feat_id) const
feat_base_t decode_feat(const morph_feats_t &feats, size_t feat_id) const
feat_base_t decode_upos(const morph_feats_t &feats) const
size_t add_upos(const std::string &name)
size_t add_feat(const std::string &name)
std::vector< feat_base_t > m_masks
std::string pretty_bits_to_string(const T arg)
Definition pretty.h:28