LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
morph_model.cpp
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#include "morph_model.h"
8
9#include <iostream>
10#include <limits>
11
12
13using namespace std;
14
15namespace deeplima
16{
17namespace morph_model
18{
19
20morph_feats_t morph_model_t::convert(const string& upos, const map<string, set<string>>& feats) const
21{
22 assert(m_upos_dict.has(upos));
23 size_t upos_id = m_upos_dict.get_id(upos);
24 morph_feats_t v(upos_id);
25
26 const auto& feats2mask = m_feats2mask[upos_id];
27
28 for ( const auto& kv : feats )
29 {
30 const string& feat_name = kv.first;
31 assert(kv.second.size() == 1);
32 assert(m_feat_dict.has(feat_name));
33 size_t feat_id = m_feat_dict.get_id(feat_name);
34
35 const auto it = feats2mask.find(feat_id);
36 assert(feats2mask.end() != it);
37 size_t mask_id = it->second;
38 assert(mask_id < m_offset.size());
39 uint8_t offset = m_offset[mask_id];
40
41 const string& feat_value = *(kv.second.begin());
42 size_t value_id = m_feats[feat_id].get_id(feat_value);
43 v.append(value_id << offset);
44 }
45
46#ifndef NDEBUG
47 //cerr << pretty_bits_to_string(v.toBaseType()) << endl;
48 const string& decoded_upos = decode_upos_to_str(v);
49 assert(upos == decoded_upos);
50#endif
51
52 return v;
53}
54
55const string& morph_model_t::decode_upos_to_str(const morph_feats_t& feats) const
56{
57 feat_base_t upos_id = decode_upos(feats);
58 return m_upos_dict.get_key(upos_id);
59}
60
62{
63 return m_feats.size();
64}
65
66morph_model_t::dict_t::dict_t(const string& str)
67{
68 istringstream iss(str);
69 size_t sz = 0;
70 iss >> sz;
71 string t;
72 while (iss >> t)
73 {
74 add_key(t);
75 }
76}
77
78morph_model_t::dict_t morph_model_t::dict_t::from_string(const string& str)
79{
80 dict_t d(str);
81 return d;
82}
83
84string morph_model_t::dict_t::to_string() const
85{
86 ostringstream oss;
87
88 oss << m_id2key.size();
89 for (const string& v : m_id2key)
90 {
91 assert(string::npos == v.find(' '));
92 assert(string::npos == v.find('\n'));
93 oss << " " << v;
94 }
95
96 return oss.str();
97}
98
100{
101 istringstream iss(str);
102 string t;
103
104 // m_upos_dict
105 t.clear();
106 while (t.empty())
107 {
108 getline(iss, t);
109 }
110 if (t.empty())
111 {
112 throw std::runtime_error("morph_model_t: t should not be empty here.");
113 }
114 m_upos_dict = morph_model_t::dict_t::from_string(t);
115
116 // m_feat_dict
117 t.clear();
118 while (t.empty())
119 {
120 getline(iss, t);
121 } if (t.empty())
122 {
123 throw std::runtime_error("morph_model_t: t should not be empty here.");
124 }
125 m_feat_dict = morph_model_t::dict_t::from_string(t);
126
127 // m_upos_mask
128 iss >> m_upos_mask;
129
130 // m_masks
131 assert(m_masks.size() == 0);
132 t.clear();
133 while (t.empty())
134 {
135 getline(iss, t);
136 }
137
138 {
139 istringstream temp_iss(t);
140 feat_base_t v;
141 while (temp_iss >> v)
142 {
143 m_masks.push_back(v);
144 }
145 }
146
147 // m_offset
148 assert(m_offset.size() == 0);
149 t.clear();
150 while (t.empty())
151 {
152 getline(iss, t);
153 }
154
155 {
156 std::istringstream temp_iss(t);
157 int v;
158 while (temp_iss >> v)
159 {
160 if (v < 0 || v > std::numeric_limits<uint8_t>::max())
161 {
162 throw std::runtime_error("morph_model_t: invalid value for v.");
163 }
164 uint8_t ui = uint8_t(v);
165 m_offset.push_back(ui);
166 }
167 }
168
169 // m_feats2mask
170 assert(m_feats2mask.size() == 0);
171 t.clear();
172 while (t.empty())
173 {
174 getline(iss, t);
175 }
176 do
177 {
178 istringstream temp_iss(t);
179 string p;
180 m_feats2mask.resize(m_feats2mask.size() + 1);
181 while (temp_iss >> p)
182 {
183 string::size_type i = p.find('_');
184 if (string::npos == i)
185 {
186 throw std::runtime_error("_ has not been found in p.");
187 }
188 p[i] = ' ';
189 istringstream p_iss(p);
190 size_t a, b;
191 p_iss >> a >> b;
192 if (m_feats2mask[m_feats2mask.size() - 1].end() != m_feats2mask[m_feats2mask.size() - 1].find(a))
193 {
194 throw std::runtime_error("morph_model_t: a not found in mask.");
195 }
196 m_feats2mask[m_feats2mask.size() - 1][a] = b;
197 }
198 getline(iss, t);
199 } while (!t.empty());
200
201 // m_feats
202 assert(m_feats.size() == 0);
203 t.clear();
204 while (t.empty())
205 {
206 getline(iss, t);
207 }
208 while (!t.empty())
209 {
210 m_feats.resize(m_feats.size() + 1);
211 m_feats[m_feats.size() - 1] = morph_model_t::dict_t::from_string(t);
212 getline(iss, t);
213 }
214}
215
217{
218 std::ostringstream oss;
219
220 oss << m_upos_dict.to_string() << std::endl;
221 oss << m_feat_dict.to_string() << std::endl;
222 oss << m_upos_mask << std::endl;
223
224 // m_masks
225 for (size_t i = 0; i < m_masks.size(); ++i)
226 {
227 if (i > 0)
228 {
229 oss << " ";
230 }
231 oss << m_masks[i];
232 }
233 oss << endl;
234
235 // m_offset
236 for (size_t i = 0; i < m_offset.size(); ++i)
237 {
238 if (i > 0)
239 {
240 oss << " ";
241 }
242 oss << int(m_offset[i]);
243 }
244 oss << endl;
245
246 // m_feats2mask
247 for (const auto& m : m_feats2mask)
248 {
249 size_t c = 0;
250 for (const auto& kv : m)
251 {
252 if (c > 0)
253 {
254 oss << " ";
255 }
256 oss << kv.first << "_" << kv.second;
257 c++;
258 }
259 oss << endl;
260 }
261 oss << endl;
262
263 // m_feats
264 for (const auto& d : m_feats)
265 {
266 oss << d.to_string() << endl;
267 }
268 oss << endl;
269
270 return oss.str();
271}
272
273std::string morph_model_t::to_string(const morph_feats_t& feats) const
274{
275
276 std::vector<std::string> out_strings;
277 out_strings.emplace_back(decode_upos_to_str(feats));
278
279 //feat_base_t upos_id = decode_upos(feats);
280 for (size_t feat_idx = 1; feat_idx < m_feats.size(); ++feat_idx)
281 {
282 feat_base_t feat_val = decode_feat(feats, feat_idx);
283 out_strings.emplace_back(m_feats[feat_idx].get_key(feat_val));
284 }
285
286 std::ostringstream oss;
287 for (size_t i = 0; i < out_strings.size(); ++i)
288 {
289 oss << " " << out_strings[i];
290 }
291 return oss.str();
292}
293
294} // morph_model
295} // deeplima
296
Encoding on one 64 bits integer of the set of morphological features for one token.
Definition morph_model.h:36
const std::string & decode_upos_to_str(const morph_feats_t &feats) const
std::vector< std::map< size_t, size_t > > m_feats2mask
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
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
std::vector< feat_base_t > m_masks
STL namespace.