aGrUM  0.16.0
partialInstantiationPattern4MultiDimArray.h
Go to the documentation of this file.
1 
32 #include <agrum/core/sequence.h>
33 
34 // check if we allowed these patterns to be used
35 #ifndef GUM_PARTIAL_INSTANTIATION_PATTERN_ALLOWED
36 
37 // #warning To use partialIntantiationPattern, you must define
38 // GUM_PARTIAL_INSTANTIATION_PATTERN_ALLOWED
39 
40 #else
41 namespace gum {
42 
43  // a specialized function instantiating some variables of a table and returning
44  // the result
45 
46 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_NAME
47 # define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE GUM_SCALAR
48  template < typename GUM_SCALAR >
49  MultiDimArray< GUM_SCALAR >* GUM_MULTI_DIM_PARTIAL_INSTANTIATION_NAME(
50  const MultiDimArray< GUM_SCALAR >* table,
51  const HashTable< const DiscreteVariable*, Idx >& inst_vars)
52 # endif
53 
54  // clang-format off
55 
56 #ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER_NAME
57 #define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE GUM_SCALAR *
58 #define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
59  template <typename GUM_SCALAR>
60  MultiDimArray<GUM_SCALAR*>*
62  const MultiDimArray<GUM_SCALAR*>* table,
63  const HashTable<const DiscreteVariable*, Idx>& inst_vars )
64 #endif
65 
66 #ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_IMPL2ARRAY_NAME
67 #define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE GUM_SCALAR
68  template <typename GUM_SCALAR>
69  MultiDimImplementation<GUM_SCALAR>*
71  const MultiDimImplementation<GUM_SCALAR>* ttable,
72  const HashTable<const DiscreteVariable*, Idx>& inst_vars )
73 #endif
74 
75 #ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER_IMPL2ARRAY_NAME
76 #define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE GUM_SCALAR *
77 #define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
78  template <typename GUM_SCALAR>
79  MultiDimImplementation<GUM_SCALAR*>*
81  const MultiDimImplementation<GUM_SCALAR*>* ttable,
82  const HashTable<const DiscreteVariable*, Idx>& inst_vars )
83 #endif
84 
85  // clang-format on
86 
87  {
88 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_IMPL2ARRAY_NAME
89  const MultiDimArray< GUM_SCALAR >* table =
90  reinterpret_cast< const MultiDimArray< GUM_SCALAR >* >(ttable);
91 # endif
92 
93 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER_IMPL2ARRAY_NAME
94  const MultiDimArray< GUM_SCALAR* >* table =
95  reinterpret_cast< const MultiDimArray< GUM_SCALAR* >* >(ttable);
96 # endif
97  // get the variables of the uninstantiated table
98  const Sequence< const DiscreteVariable* >& table_vars =
99  table->variablesSequence();
100 
101  // Compute the offset of the variables. In addition, get the offset in
102  // table induced by the instantiation inst_var
103  Idx table_alone_offset = 0;
104  Idx offset = 1;
105  HashTable< const DiscreteVariable*, Idx > var1offset(table_vars.size());
106 
107  for (const auto var : table_vars) {
108  if (inst_vars.exists(var)) table_alone_offset += inst_vars[var] * offset;
109 
110  var1offset.insert(var, offset);
111  offset *= var->domainSize();
112  }
113 
114  // Compute the sequence of variables in the result table. Compute as well
115  // the offsets and the domain size of the variables that belong to result.
116  // Finally, compute has_before_incr: this is a Boolean indicating whether
117  // the instantiated variables are the last variables in the variables
118  // sequence of table (true) or not (false). If this Boolean is true, then
119  // we can fill result by parsing both table and result using only
120  // 1-increments.
121  Sequence< const DiscreteVariable* > result_varSeq;
122  std::vector< Idx > table_and_result_offset;
123  std::vector< Idx > table_and_result_domain;
124  Idx result_domain_size = 1;
125  bool has_before_incr = true;
126  bool found_inst_var = false;
127 
128  for (const auto var : table_vars) {
129  if (!inst_vars.exists(var)) {
130  table_and_result_domain.push_back(var->domainSize());
131  table_and_result_offset.push_back(var1offset[var]);
132  result_domain_size *= var->domainSize();
133  result_varSeq << var;
134 
135  if (found_inst_var) has_before_incr = false;
136  } else {
137  found_inst_var = true;
138  }
139  }
140 
141  // table_and_result_value is a vector indictating, for each uninstantiated
142  // variable, how many increments we can still perform on that variable
143  // before we must perform a "major" increment: for instance, let A and B be
144  // two variables of size 10. Then, if table_and_result_value[A] = 3 and
145  // table_and_result_value[B] = 2, this means that the offset they represent
146  // is 78 (10^2 - 32). If we still increment B twice, then the offset should
147  // be 80, which means that we shall increment A once and decrease B by 10.
148  // The value by which variables shall be decreased is indicated in
149  // table_and_result_down
150  std::vector< Idx > table_and_result_value = table_and_result_domain;
151  std::vector< Idx > table_and_result_down = table_and_result_offset;
152 
153  for (unsigned int i = 0; i < table_and_result_down.size(); ++i) {
154  table_and_result_down[i] *= (table_and_result_domain[i] - 1);
155  }
156 
157  // create a table "result" containing only the variables that are not
158  // instantiated: the variables are stored in the order in which they appear
159  // in "table". Hence, ++ operations on an instantiation on table will more
160  // or less correspond to a ++ operation on an instantiation on result
161  MultiDimArray< GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE >* result =
162  new MultiDimArray< GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE >;
163  result->beginMultipleChanges();
164 
165  for (const auto var : result_varSeq)
166  *result << *var;
167 
168  result->endMultipleChanges();
169 
170 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
171  // fill the matrix with any element
172  {
173  const GUM_SCALAR& any_element = *(table->unsafeGet(0));
174 
175  for (Idx i = 0; i < result_domain_size; ++i) {
176  result->unsafeSet(i, new GUM_SCALAR(any_element));
177  }
178  }
179 # endif /* GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER */
180 
181  // compute the result: it is now sufficient to loop over the variables that
182  // were not instantiated. ptable and presult are pointers on the arrays
183  // that are directly used for this loop
184  GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE* ptable =
185  const_cast< GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE* >(
186  &(table->unsafeGet(table_alone_offset)));
187  GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE* presult =
188  const_cast< GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE* >(
189  &(result->unsafeGet(0)));
190 
191  // but before doing so, check whether the instantiated variables are the
192  // last ones or not. If so, we can optimize the parsing of ptable and
193  // presult as both tables need be parsed using only 1-increments
194  if (has_before_incr) {
195  for (Idx i = 0; i < result_domain_size; ++i) {
196 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
197  **presult = **ptable;
198 # else
199  *presult = *ptable;
200 # endif
201 
202  // update the offset of result and table
203  ++ptable;
204  ++presult;
205  }
206  } else {
207  // here, some uninstantiated variables exist after the instantiated ones
208  // in the variables sequence of table. So, we must perform a more
209  // complicated parsing of ptable
210  Idx table_offset = 0;
211 
212  for (Idx j = 0; j < result_domain_size; ++j) {
213 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
214  **presult = *(ptable[table_offset]);
215 # else
216  *presult = ptable[table_offset];
217 # endif
218 
219  // update the offset of table
220  for (unsigned int k = 0; k < table_and_result_value.size(); ++k) {
221  --table_and_result_value[k];
222 
223  if (table_and_result_value[k]) {
224  table_offset += table_and_result_offset[k];
225  break;
226  }
227 
228  table_and_result_value[k] = table_and_result_domain[k];
229  table_offset -= table_and_result_down[k];
230  }
231 
232  // update the offset of result
233  ++presult;
234  }
235  }
236 
237  return result;
238  }
239 
240 # undef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE
241 
242 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
243 # undef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
244 # endif
245 
246 } /* End of namespace gum */
247 
248 #endif /* GUM_PARTIAL_INSTANTIATION_PATTERN_ALLOWED */
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
#define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_NAME
a specialized partial instantiation function for multiDimArrays
#define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER_NAME
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
#define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER_IMPL2ARRAY_NAME
#define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_IMPL2ARRAY_NAME