aGrUM  0.21.0
a C++ library for (probabilistic) graphical models
DBTranslatorSet.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /** @file
23  * @brief A class for storing several translators
24  *
25  * When learning Bayesian networks, the records of the train dataset are
26  * used to construct contingency tables that are either exploited in
27  * statistical conditional independence tests or in scores. In both cases,
28  * the values observed in the records must be translated into indices in
29  * the finite domain of the corresponding random variables. DBTranslator
30  * instances are used for this purpose. To make the parsing of all the columns
31  * of the dataset easier, all the DBTranslator instances used are gathered
32  * into a single DBRowTranslatorSet.
33  *
34  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
35  */
36 #ifndef GUM_LEARNING_DB_TRANSLATOR_SET_H
37 #define GUM_LEARNING_DB_TRANSLATOR_SET_H
38 
39 #include <vector>
40 #include <limits>
41 #include <type_traits>
42 
43 #include <agrum/agrum.h>
44 #include <agrum/tools/database/DBTranslator.h>
45 #include <agrum/tools/database/DBTranslator4LabelizedVariable.h>
46 #include <agrum/tools/database/DBTranslator4DiscretizedVariable.h>
47 #include <agrum/tools/database/DBTranslator4IntegerVariable.h>
48 #include <agrum/tools/database/DBTranslator4RangeVariable.h>
49 #include <agrum/tools/database/DBTranslator4ContinuousVariable.h>
50 
51 
52 namespace gum {
53 
54  namespace learning {
55 
56  /** @class DBTranslatorSet
57  * @headerfile DBTranslatorSet.h <agrum/tools/database/DBTranslatorSet.h>
58  * @ingroup learning_database
59  * @brief the class for packing together the translators used to preprocess
60  * the datasets
61  *
62  * When learning Bayesian networks, the records of the train dataset are
63  * used to construct contingency tables that are either exploited in
64  * statistical conditional independence tests or in scores. In both cases,
65  * the values observed in the records must be translated into indices in
66  * the finite domain of the corresponding random variables. The
67  * DBTranslator classes are used for this purpose. To make the parsing
68  * of all the columns of the dataset easier, all the DBTranslator
69  * instances used are gathered into a DBTranslatorSet.
70  *
71  * @par Here is an example of how to use this class:
72  * @code
73  * // create an empty translator set
74  * gum::learning::DBTranslatorSet<> set;
75  *
76  * std::vector<std::string> missing { "?", "N/A", "???" };
77  *
78  * // create the translators and add them to the translator set. First,
79  * // create translator1 that will perform its translations on Column 1
80  * // of the dataset (columns start from index 0)
81  * gum::learning::DBTranslator4LabelizedVariable<> translator1 ( missing, 3 );
82  * std::size_t pos1 = set.insertTranslator ( translator1, 1 );
83  * // currently, pos1 is equal to 0, that is, translator1 is the first
84  * // translator in the translator set
85  *
86  * // create a translator handling Column 0 of the dataset
87  * gum::learning::DBTranslator4ContinuousVariable<> translator0;
88  * std::size_t pos0 = set.insertTranslator ( translator0, 0 );
89  * // translator0 has been inserted into the translator set at position pos0.
90  * // pos0 = 0 because translators are sorted by increasing column order in
91  * // the translator set. So, now, in the set, the first translator is
92  * // translator0 and the the second one is translator1.
93  *
94  * gum::learning::DBTranslator4LabelizedVariable<> translator2;
95  * std::size_t pos2 = set.insertTranslator ( translator2, 2 );
96  * // the set contains { translator0, translator1, translator2 }, in this order
97  *
98  * // parsing the rows of the dataset
99  * std::vector<std::string> row1 { ".33", "toto", "titi" };
100  * float val0 = set.translate ( row1, 0 ).cont_val; // val0 = 0.33f
101  * std::size_t val1 = set.translate ( row1, 1 ).discr_val; // val1 = 0 (toto)
102  * std::size_t val2 = set.translate ( row1, 2 ).discr_val; // val2 = 0 (titi)
103  * std::vector<std::string> row2 { "4.22x", "???", "??" };
104  * val0 = set.translate ( row2, 0 ).cont_val; // raises gum::TypeError
105  * val1 = set.translate ( row2, 1 ).discr_val;
106  * // = std::numeric_limits<std::size_t>::max ()
107  * val2 = set.translate ( row2, 2 ).discr_val; // = 1 (??)
108  *
109  * // with method translateSafe, an exception is raised whenever we try to
110  * // translate a column that is not taken into account by the translators
111  * set.translateSafe ( row2, 3 ); // raises gum::UndefinedElement
112  * @endcode
113  */
114  template < template < typename > class ALLOC = std::allocator >
116  public:
117  /// type for the allocators passed in arguments of methods
119 
120  // ##########################################################################
121  /// @name Constructors / Destructors
122  // ##########################################################################
123 
124  /// @{
125 
126  /// default constructor
127  DBTranslatorSet(const allocator_type& alloc = allocator_type());
128 
129  /// copy constructor
130  DBTranslatorSet(const DBTranslatorSet< ALLOC >& from);
131 
132  /// copy constructor with a given allocator
133  DBTranslatorSet(const DBTranslatorSet< ALLOC >& from, const allocator_type& alloc);
134 
135  /// move constructor
136  DBTranslatorSet(DBTranslatorSet< ALLOC >&& from);
137 
138  /// move constructor with a given allocator
139  DBTranslatorSet(DBTranslatorSet< ALLOC >&& from, const allocator_type& alloc);
140 
141  /// virtual copy constructor
142  virtual DBTranslatorSet< ALLOC >* clone() const;
143 
144  /// virtual copy constructor with a given allocator
145  virtual DBTranslatorSet< ALLOC >* clone(const allocator_type& alloc) const;
146 
147  /// destructor
148  virtual ~DBTranslatorSet();
149 
150  /// @}
151 
152  // ##########################################################################
153  /// @name Operators
154  // ##########################################################################
155 
156  /// @{
157 
158  /// copy operator
160 
161  /// move operator
163 
164  /// returns the kth translator
165  /** @warning this operator assumes that there are at least k translators.
166  * So, it won't check that the kth translator actually exists. If unsure,
167  * use method translatorSafe that performs this check. */
168  DBTranslator< ALLOC >& operator[](const std::size_t k);
169 
170  /// returns the kth translator
171  /** @warning this operator assumes that there are at least k translators.
172  * So, it won't check that the kth translator actually exists. If unsure,
173  * use method translatorSafe that performs this check. */
174  const DBTranslator< ALLOC >& operator[](const std::size_t k) const;
175 
176  /// @}
177 
178 
179  // ##########################################################################
180  /// @name Accessors / Modifiers
181  // ##########################################################################
182 
183  /// @{
184 
185  /// inserts a new translator at the end of the translator set
186  /** @param translator a translator that will be copied into the
187  * translator set
188  * @param column the index of the column that this new translator should
189  * read in the database.
190  * @param unique_column indicates whether the column can be read by
191  * several translators.
192  * @return the position of the translator within the translator set.
193  * @throw DuplicateElement is raised if there already exists a translator
194  * reading the column passed in argument and the unique_column
195  * argument is set to true. */
196  template < template < template < typename > class > class Translator >
197  std::size_t insertTranslator(const Translator< ALLOC >& translator,
198  const std::size_t column,
199  const bool unique_column = true);
200 
201  /** @brief inserts a new translator for a given variable at the end of
202  * the translator set
203  *
204  * @param var the variable that will be contained into the translator
205  * @param column the index of the column that this new translator should
206  * read in the database.
207  * @param missing_symbols the set of symbols in the database
208  * representing missing values
209  * @param unique_column indicates whether the column can be read by
210  * several translators.
211  * @throw DuplicateElement is raised if there already exists a translator
212  * reading the column passed in argument and the unique_column
213  * argument is set to true.
214  */
215  template < template < typename > class XALLOC >
216  std::size_t
217  insertTranslator(const Variable& var,
218  const std::size_t column,
219  const std::vector< std::string, XALLOC< std::string > >& missing_symbols,
220  const bool unique_column = true);
221 
222  /** @brief inserts a new translator for a given variable at the end of
223  * the translator set
224  *
225  * @param var the variable that will be contained into the translator
226  * @param column the index of the column that this new translator should
227  * read in the database.
228  * @param unique_column indicates whether the column can be read by
229  * several translators.
230  * @throw DuplicateElement is raised if there already exists a translator
231  * reading the column passed in argumentt and the unique_column
232  * argument is set to true.
233  */
234  std::size_t insertTranslator(const Variable& var,
235  const std::size_t column,
236  const bool unique_column = true);
237 
238  /// substitute a translator by another one
239  /**
240  *
241  * @param new_translator the new translator, copied at index pos of the
242  * TranslatorSet
243  * @param pos the position where the new translator should replace the
244  * old one.
245  */
246  template < template < template < typename > class > class Translator >
247  void substituteTranslator(const Translator< ALLOC >& new_translator,
248  const std::size_t pos);
249 
250  /** @brief erases either the kth translator or those parsing the kth
251  * column of the input database
252  *
253  * DBTranslatorSets do not necessarily read all the columns of their
254  * input database. For instance, a CSV may contain 10 columns, but the
255  * DBTranslatorSet may only contain two translators reading columns 3
256  * and 5 respectively. When k_is_input_col is set to false, Parameter k
257  * passed in argument corresponds to either 0 or 1, i.e., to the index of
258  * one of the two translators stored into the DBTranslatorSet. When
259  * k_is_input_col is set to true, the translators to be erased are the ones
260  * that parse the kth column of the input database (when several
261  * translators parse the column k, all of them are removed).
262  * @warning if the translator does not exists, nothing is done. In
263  * particular, no exception is raised. */
264  void eraseTranslator(const std::size_t k, const bool k_is_input_col = false);
265 
266  /// returns the kth translator
267  /** @warning this method assumes that there are at least k translators.
268  * So, it won't check that the kth translator actually exists. If unsure,
269  * use method translatorSafe that performs this check.*/
270  DBTranslator< ALLOC >& translator(const std::size_t k);
271 
272  /// returns the kth translator
273  /** @warning this method assumes that there are at least k translators.
274  * So, it won't check that the kth translator actually exists. If unsure,
275  * use method translatorSafe that performs this check.*/
276  const DBTranslator< ALLOC >& translator(const std::size_t k) const;
277 
278  /// returns the kth translator
279  /** @throw UndefinedElement is raised if there are fewer than k
280  * translators in the translator set. */
282 
283  /// returns the kth translator
284  /** @throw UndefinedElement is raised if there are fewer than k
285  * translators in the translator set. */
286  const DBTranslator< ALLOC >& translatorSafe(const std::size_t k) const;
287 
288  /// ask the kth translator to translate a string in a row of the database
289  /** @param row a row of the original database
290  * @param k the index of the translator that will perform the translation
291  * @warning this method assumes that there are at least k translators.
292  * So, it won't check that the kth translator actually exists. If unsure,
293  * use method translateSafe that performs this check.
294  * @warning as there is not necessarily an identity mapping between the
295  * set of columns of the database and the set of translators used, k may
296  * not necessarily corresponds to the index of a column in the database:
297  * this is the index of a translator within the set */
298  template < template < typename > class OTHER_ALLOC >
300  const std::size_t k) const;
301 
302  /** @brief similar to method translate, except that it checks that the kth
303  * translator exists
304  *
305  * @param row a row of the original database
306  * @param k the index of the translator that will perform the translation
307  * @throw UndefinedElement is raised if there are fewer than k
308  * translators in the translator set.
309  * @warning as there is not necessarily an identity mapping between the
310  * set of columns of the database and the set of translators used, k may
311  * not necessarily corresponds to the index of a column in the database:
312  * this is the index of a translator within the set */
313  template < template < typename > class OTHER_ALLOC >
316  const std::size_t k) const;
317 
318  /// returns the original string that was translated into translated_val
319  /** @param translated_val the value from which we look for the
320  * original string
321  * @param k the index of the translator that performed the translation
322  * @warning this method assumes that there are at least k translators.
323  * So, it won't check that the kth translator actually exists. If unsure,
324  * use method translateBackSafe that performs this check.
325  * @warning as there is not necessarily an identity mapping between the
326  * set of columns of the database and the set of translators used, k may
327  * not necessarily corresponds to the index of a column in the database:
328  * this is the index of a translator within the set */
330 
331  /** @brief similar to method translateBack, except that it checks that
332  * the kth translator exists
333  *
334  * @param translated_val the value from which we look for the
335  * original string
336  * @param k the index of the translator that performed the translation
337  * @throw UndefinedElement is raised if there are fewer than k
338  * translators in the translator set.
339  * @warning as there is not necessarily an identity mapping between the
340  * set of columns of the database and the set of translators used, k may
341  * not necessarily corresponds to the index of a column in the database:
342  * this is the index of a translator within the set */
344  const std::size_t k) const;
345 
346  /** @brief indicates whether the kth translator considers a translated_val
347  * as a missing value
348  *
349  * @param translated_val the value that we compare to the translation of
350  * a missing value
351  * @param k the index of the translator that performed the translation
352  * @warning this method assumes that there are at least k translators.
353  * So, it won't check that the kth translator actually exists. If unsure,
354  * use method isMissingValueSafe that performs this check.
355  */
356  bool isMissingValue(const DBTranslatedValue translated_val, const std::size_t k) const;
357 
358  /** @brief similar to method isMissingValue, except that it checks that
359  * the kth translator exists
360  *
361  * @param translated_val the value that we compare to the translation of
362  * a missing value
363  * @param k the index of the translator that performed the translation
364  * @throw UndefinedElement is raised if there are fewer than k
365  * translators in the translator set.
366  */
367  bool isMissingValueSafe(const DBTranslatedValue translated_val, const std::size_t k) const;
368 
369  /// returns the domain size of the variable stored into the kth translator
370  /** @warning this method assumes that there are at least k translators.
371  * So, it won't check that the kth translator actually exists. If unsure,
372  * use method domainSizeSafe that performs this check. */
373  std::size_t domainSize(const std::size_t k) const;
374 
375  /// returns the domain size of the variable stored into the kth translator
376  /** @throw UndefinedElement is raised if there are fewer than k
377  * translators in the translator set. */
378  std::size_t domainSizeSafe(const std::size_t k) const;
379 
380  /// returns the variable stored into the kth translator
381  /** @warning this method assumes that there are at least k translators.
382  * So, it won't check that the kth translator actually exists. If unsure,
383  * use method variableSafe that performs this check. */
384  const Variable& variable(const std::size_t k) const;
385 
386  /// returns the variable stored into the kth translator
387  /** @throw UndefinedElement is raised if there are fewer than k
388  * translators in the translator set. */
389  const Variable& variableSafe(const std::size_t k) const;
390 
391  /** @brief indicates whether a reordering is needed to make the kth
392  * translator sorted
393  *
394  * For a given translator, if the strings represented by the translations
395  * are only numbers, the translations are considered to be sorted if and
396  * only if they are sorted by increasing number. If the strings do not
397  * only represent numbers, then translations are considered to be sorted
398  * if and only if they are sorted lexicographically.
399  *
400  * When constructing dynamically its dictionary, the translator may
401  * assign wrong DBTranslatedValue values to strings. For instance, a
402  * translator reading sequentially integer strings 4, 1, 3, may map
403  * 4 into DBTranslatedValue{std::size_t(0)},
404  * 1 into DBTranslatedValue{std::size_t(1)} and
405  * 3 into DBTranslatedValue{std::size_t(2)}, resulting in random variables
406  * having domain {4,1,3}. The user may prefer having domain {1,3,4}, i.e.,
407  * a domain specified with increasing values. This requires a
408  * reordering. Method needsReodering() returns a Boolean indicating
409  * whether such a reordering should be performed or whether the current
410  * order is OK.
411  * @warning this method assumes that there are at least k translators.
412  * So, it won't check that the kth translator actually exists. If unsure,
413  * use method needsReorderingSafe that performs this check. */
414  bool needsReordering(const std::size_t k) const;
415 
416  /// same as method needsReordering but checks that the kth translator exists
417  /** @throw UndefinedElement is raised if there are fewer than k
418  * translators in the translator set. */
419  bool needsReorderingSafe(const std::size_t k) const;
420 
421  /** @brief performs a reordering of the dictionary and returns a mapping
422  * from the old translated values to the new ones.
423  *
424  * When a reordering is needed, i.e., string values must be translated
425  * differently, Method reorder() computes how the translations should be
426  * changed. It updates accordingly the dictionary and returns the mapping
427  * that enables changing the old dictionary values into the new ones.
428  * Note that the hash table returned is expressed in terms of std::size_t
429  * because only the translations for discrete random variables need be
430  * reordered, those for continuous random variables are identity mappings.
431  * @warning this method assumes that there are at least k translators.
432  * So, it won't check that the kth translator actually exists. If unsure,
433  * use method reorderSafe that performs this check. */
435  reorder(const std::size_t k);
436 
437  /// same as method reorder but checks that the kth translator exists
438  /** @throw UndefinedElement is raised if there are fewer than k
439  * translators in the translator set. */
441  reorderSafe(const std::size_t k);
442 
443  /** @brief returns the column of the input database that will be read
444  * by the kth translator
445  *
446  * @warning this method assumes that there are at least k translators.
447  * So, it won't check that the kth translator actually exists. If unsure,
448  * use method inputColumnSafe that performs this check. */
449  std::size_t inputColumn(const std::size_t k) const;
450 
451  /** @brief returns the column of the input database that will be read
452  * by the kth translator
453  * @throw UndefinedElement is raised if there are fewer than k
454  * translators in the translator set. */
455  std::size_t inputColumnSafe(const std::size_t k) const;
456 
457  /// returns the largest input database column index read by the translators
458  std::size_t highestInputColumn() const;
459 
460  /// remove all the translators
461  void clear();
462 
463  /// returns the number of translators stored into the set
464  std::size_t nbTranslators() const;
465 
466  /// returns the number of translators stored into the set
467  std::size_t size() const;
468 
469  /// returns the allocator used by the translator set
471 
472  /// returns the set of translators
473  const std::vector< DBTranslator< ALLOC >*, ALLOC< DBTranslator< ALLOC >* > >&
474  translators() const;
475 
476  /// @}
477 
478 #ifndef DOXYGEN_SHOULD_SKIP_THIS
479 
480  private:
481  // the set of all the translators
483 
484  // a vector indicating which column of the original database each
485  // translator should translate
486  std::vector< std::size_t, ALLOC< std::size_t > > _columns_;
487 
488  // the highest column index read by the translators
489  std::size_t _highest_column_{std::size_t(0)};
490 
491  /// copy the content of another translator set that uses another allocator
492  void _copy_(const DBTranslatorSet< ALLOC >& from, const allocator_type& alloc);
493 
494 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
495  };
496 
497  } /* namespace learning */
498 
499 } /* namespace gum */
500 
501 // always include templated implementation
502 #include <agrum/tools/database/DBTranslatorSet_tpl.h>
503 
504 #endif /* GUM_LEARNING_DB_TRANSLATOR_SET_H */
HashTable< std::size_t, std::size_t, ALLOC< std::pair< std::size_t, std::size_t > > > reorder(const std::size_t k)
performs a reordering of the dictionary and returns a mapping from the old translated values to the n...
const Variable & variable(const std::size_t k) const
returns the variable stored into the kth translator
DBTranslatorSet(const DBTranslatorSet< ALLOC > &from, const allocator_type &alloc)
copy constructor with a given allocator
const std::vector< DBTranslator< ALLOC > *, ALLOC< DBTranslator< ALLOC > *> > & translators() const
returns the set of translators
void eraseTranslator(const std::size_t k, const bool k_is_input_col=false)
erases either the kth translator or those parsing the kth column of the input database ...
DBTranslatorSet(const DBTranslatorSet< ALLOC > &from)
copy constructor
DBTranslatorSet< ALLOC > & operator=(const DBTranslatorSet< ALLOC > &from)
copy operator
std::string translateBack(const DBTranslatedValue translated_val, const std::size_t k) const
returns the original string that was translated into translated_val
const Variable & variableSafe(const std::size_t k) const
returns the variable stored into the kth translator
std::size_t domainSizeSafe(const std::size_t k) const
returns the domain size of the variable stored into the kth translator
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
std::size_t highestInputColumn() const
returns the largest input database column index read by the translators
DBTranslator< ALLOC > & translatorSafe(const std::size_t k)
returns the kth translator
std::size_t insertTranslator(const Variable &var, const std::size_t column, const bool unique_column=true)
inserts a new translator for a given variable at the end of the translator set
const DBTranslator< ALLOC > & operator[](const std::size_t k) const
returns the kth translator
std::size_t inputColumnSafe(const std::size_t k) const
returns the column of the input database that will be read by the kth translator
DBTranslatorSet(DBTranslatorSet< ALLOC > &&from, const allocator_type &alloc)
move constructor with a given allocator
std::size_t nbTranslators() const
returns the number of translators stored into the set
DBTranslator< ALLOC > & operator[](const std::size_t k)
returns the kth translator
std::size_t domainSize(const std::size_t k) const
returns the domain size of the variable stored into the kth translator
std::size_t insertTranslator(const Variable &var, const std::size_t column, const std::vector< std::string, XALLOC< std::string > > &missing_symbols, const bool unique_column=true)
inserts a new translator for a given variable at the end of the translator set
DBTranslator< ALLOC > & translator(const std::size_t k)
returns the kth translator
bool isMissingValueSafe(const DBTranslatedValue translated_val, const std::size_t k) const
similar to method isMissingValue, except that it checks that the kth translator exists ...
allocator_type getAllocator() const
returns the allocator used by the translator set
std::size_t insertTranslator(const Translator< ALLOC > &translator, const std::size_t column, const bool unique_column=true)
inserts a new translator at the end of the translator set
bool needsReordering(const std::size_t k) const
indicates whether a reordering is needed to make the kth translator sorted
virtual ~DBTranslatorSet()
destructor
std::size_t inputColumn(const std::size_t k) const
returns the column of the input database that will be read by the kth translator
const DBTranslator< ALLOC > & translator(const std::size_t k) const
returns the kth translator
std::string translateBackSafe(const DBTranslatedValue translated_val, const std::size_t k) const
similar to method translateBack, except that it checks that the kth translator exists ...
const DBTranslator< ALLOC > & translatorSafe(const std::size_t k) const
returns the kth translator
std::size_t size() const
returns the number of translators stored into the set
DBTranslatorSet< ALLOC > & operator=(DBTranslatorSet< ALLOC > &&from)
move operator
DBTranslatedValue translateSafe(const std::vector< std::string, OTHER_ALLOC< std::string > > &row, const std::size_t k) const
similar to method translate, except that it checks that the kth translator exists ...
void substituteTranslator(const Translator< ALLOC > &new_translator, const std::size_t pos)
substitute a translator by another one
bool needsReorderingSafe(const std::size_t k) const
same as method needsReordering but checks that the kth translator exists
DBTranslatedValue translate(const std::vector< std::string, OTHER_ALLOC< std::string > > &row, const std::size_t k) const
ask the kth translator to translate a string in a row of the database
void clear()
remove all the translators
HashTable< std::size_t, std::size_t, ALLOC< std::pair< std::size_t, std::size_t > > > reorderSafe(const std::size_t k)
same as method reorder but checks that the kth translator exists
virtual DBTranslatorSet< ALLOC > * clone() const
virtual copy constructor
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
virtual DBTranslatorSet< ALLOC > * clone(const allocator_type &alloc) const
virtual copy constructor with a given allocator
bool isMissingValue(const DBTranslatedValue translated_val, const std::size_t k) const
indicates whether the kth translator considers a translated_val as a missing value ...
DBTranslatorSet(DBTranslatorSet< ALLOC > &&from)
move constructor