50#ifndef DOXYGEN_SHOULD_SKIP_THIS
61 template <
class TABLE >
63 TABLE (*combine)(
const TABLE&,
const TABLE&),
69 GUM_CONSTRUCTOR(MultiDimCombineAndProjectDefault);
73 template <
class TABLE >
74 MultiDimCombineAndProjectDefault< TABLE >::MultiDimCombineAndProjectDefault(
75 const MultiDimCombineAndProjectDefault< TABLE >& from) :
76 MultiDimCombineAndProject< TABLE >(), _combination_(from._combination_->clone()),
77 _projection_(from._projection_->clone()) {
79 GUM_CONS_CPY(MultiDimCombineAndProjectDefault);
83 template <
class TABLE >
84 MultiDimCombineAndProjectDefault< TABLE >::~MultiDimCombineAndProjectDefault() {
86 GUM_DESTRUCTOR(MultiDimCombineAndProjectDefault);
92 template <
class TABLE >
93 MultiDimCombineAndProjectDefault< TABLE >*
94 MultiDimCombineAndProjectDefault< TABLE >::clone()
const {
95 return new MultiDimCombineAndProjectDefault< TABLE >(*
this);
99 template <
class TABLE >
101 MultiDimCombineAndProjectDefault< TABLE >::execute(
const Set< const TABLE* >& table_set,
104 std::vector< const IScheduleMultiDim* > tables;
105 tables.reserve(table_set.size());
106 for (
const auto table: table_set) {
107 tables.push_back(
new ScheduleMultiDim< TABLE >(*table,
false));
111 auto ops_plus_res = operations(tables, del_vars,
false);
112 for (
auto op: ops_plus_res.first) {
117 Set< const TABLE* > result(ops_plus_res.second.size());
118 for (
const auto pot: ops_plus_res.second) {
119 auto& schedule_result =
const_cast< ScheduleMultiDim< TABLE >&
>(
120 static_cast< const ScheduleMultiDim< TABLE >&
>(*pot));
121 auto potres =
new TABLE(std::move(schedule_result.multiDim()));
122 result.insert(potres);
126 _freeData_(tables, ops_plus_res.first);
132 template <
class TABLE >
133 INLINE
void MultiDimCombineAndProjectDefault< TABLE >::setCombinationFunction(
134 TABLE (*combine)(
const TABLE&,
const TABLE&)) {
135 _combination_->setCombinationFunction(combine);
139 template <
class TABLE >
140 INLINE TABLE (*MultiDimCombineAndProjectDefault< TABLE >::combinationFunction())(
const TABLE&,
142 return _combination_->combinationFunction();
146 template <
class TABLE >
147 INLINE
void MultiDimCombineAndProjectDefault< TABLE >::setCombinationClass(
148 const MultiDimCombination< TABLE >& comb_class) {
149 delete _combination_;
150 _combination_ = comb_class.clone();
154 template <
class TABLE >
155 INLINE
void MultiDimCombineAndProjectDefault< TABLE >::setProjectionFunction(
157 _projection_->setProjectionFunction(proj);
161 template <
class TABLE >
162 INLINE TABLE (*MultiDimCombineAndProjectDefault< TABLE >::projectionFunction())(
165 return _projection_->projectionFunction();
169 template <
class TABLE >
170 INLINE
void MultiDimCombineAndProjectDefault< TABLE >::setProjectionClass(
171 const MultiDimProjection< TABLE >& proj_class) {
173 _projection_ = proj_class.clone();
178 template <
class TABLE >
179 double MultiDimCombineAndProjectDefault< TABLE >::nbOperations(
180 const Set<
const Sequence< const DiscreteVariable* >* >& table_set,
183 std::vector< const IScheduleMultiDim* > tables;
184 tables.reserve(table_set.size());
185 for (
const auto vars: table_set) {
186 tables.push_back(
new ScheduleMultiDim< TABLE >(*vars,
false));
190 auto ops_plus_res = operations(tables, del_vars,
false);
191 double nb_operations = 0.0;
192 for (
auto op: ops_plus_res.first) {
193 nb_operations += op->nbOperations();
197 _freeData_(tables, ops_plus_res.first);
199 return nb_operations;
204 template <
class TABLE >
205 double MultiDimCombineAndProjectDefault< TABLE >::nbOperations(
206 const Set< const TABLE* >& set,
209 Set< const Sequence< const DiscreteVariable* >* > var_set(set.size());
211 for (
const auto ptrTab: set) {
212 var_set << &(ptrTab->variablesSequence());
215 return nbOperations(var_set, del_vars);
220 template <
class TABLE >
221 std::pair< double, double > MultiDimCombineAndProjectDefault< TABLE >::memoryUsage(
222 const Set<
const Sequence< const DiscreteVariable* >* >& table_set,
225 std::vector< const IScheduleMultiDim* > tables;
226 tables.reserve(table_set.size());
227 for (
const auto vars: table_set) {
228 tables.push_back(
new ScheduleMultiDim< TABLE >(*vars,
false));
232 auto ops_plus_res = operations(tables, del_vars,
false);
235 double max_memory = 0.0;
236 double end_memory = 0.0;
237 for (
const auto op: ops_plus_res.first) {
238 const auto usage = op->memoryUsage();
239 if (end_memory + usage.first > max_memory) max_memory = end_memory + usage.first;
240 end_memory += usage.second;
244 _freeData_(tables, ops_plus_res.first);
246 return {max_memory, end_memory};
251 template <
class TABLE >
252 std::pair< double, double > MultiDimCombineAndProjectDefault< TABLE >::memoryUsage(
253 const Set< const TABLE* >& set,
256 Set< const Sequence< const DiscreteVariable* >* > var_set(set.size());
258 for (
const auto ptrTab: set) {
259 var_set << &(ptrTab->variablesSequence());
262 return memoryUsage(var_set, del_vars);
267 template <
class TABLE >
268 std::pair< std::vector< ScheduleOperator* >, Set< const IScheduleMultiDim* > >
269 MultiDimCombineAndProjectDefault< TABLE >::operations(
270 const std::vector< const IScheduleMultiDim* >& original_tables,
272 const bool is_result_persistent)
const {
273 Set< const IScheduleMultiDim* > tables_set(original_tables.size());
274 for (
const auto table: original_tables) {
275 tables_set.insert(table);
277 return operations(tables_set, del_vars, is_result_persistent);
282 template <
class TABLE >
283 std::pair< std::vector< ScheduleOperator* >, Set< const IScheduleMultiDim* > >
284 MultiDimCombineAndProjectDefault< TABLE >::operations(
285 const Set< const IScheduleMultiDim* >& original_tables,
287 const bool is_result_persistent)
const {
289 const Size tabsize = original_tables.size();
292 auto res = _projection_->operations(*original_tables.begin(), original_del_vars);
293 return std::pair< std::vector< ScheduleOperator* >, Set< const IScheduleMultiDim* > >(
298 for (
const auto& v: original_del_vars) {
299 names += v->name() +
", ";
302 "MultiDimCombineAndProject need at least one table to "
303 "have some work to do (original_del_vars ="
310 Set< const IScheduleMultiDim* > tables = original_tables;
326 for (
const auto table: tables) {
327 for (
const auto ptrVar: table->variablesSequence()) {
332 nb_vars = all_vars.
size();
336 HashTable< const DiscreteVariable*, Set< const IScheduleMultiDim* > > tables_per_var(nb_vars);
343 HashTable< const DiscreteVariable*, HashTable< const DiscreteVariable*, unsigned int > >
344 clique_vars_per_var(nb_vars);
348 Set< const IScheduleMultiDim* > empty_set(tables.size());
349 HashTable< const DiscreteVariable*, unsigned int > empty_hash(nb_vars);
351 for (
const auto ptrVar: del_vars) {
352 tables_per_var.insert(ptrVar, empty_set);
353 clique_vars_per_var.insert(ptrVar, empty_hash);
357 for (
const auto ptrTab: tables) {
358 const auto& vars = ptrTab->variablesSequence();
360 for (
const auto ptrVar: vars) {
361 if (del_vars.contains(ptrVar)) {
363 tables_per_var[ptrVar].insert(ptrTab);
366 auto& comb_vars = clique_vars_per_var[ptrVar];
367 for (
const auto xptrVar: vars) {
369 ++comb_vars[xptrVar];
370 }
catch (
const NotFound&) { comb_vars.insert(xptrVar, 1); }
379 std::vector< ScheduleOperator* > ops;
380 ops.reserve(2 * tables.size() + del_vars.size());
384 HashTable< const IScheduleMultiDim*, ScheduleOperator* > multidim2op(tables.size());
387 PriorityQueue< const DiscreteVariable*, double > product_size;
390 for (
const auto& elt: clique_vars_per_var) {
392 const auto ptrVar = elt.first;
393 const auto& hashvars = elt.second;
395 if (!hashvars.empty()) {
396 for (
const auto& xelt: hashvars) {
397 size *= (
double)xelt.first->domainSize();
400 product_size.insert(ptrVar, size);
406 while (!product_size.empty()) {
408 const DiscreteVariable* del_var = product_size.pop();
409 del_vars.erase(del_var);
412 auto& tables_to_combine = tables_per_var[del_var];
415 if (tables_to_combine.empty())
continue;
420 const IScheduleMultiDim* joint =
nullptr;
421 bool joint_to_delete;
422 if (tables_to_combine.size() == 1) {
423 joint = *(tables_to_combine.begin());
424 joint_to_delete =
false;
428 auto comb_ops = _combination_->operations(tables_to_combine);
429 ops.insert(ops.cend(), comb_ops.first.begin(), comb_ops.first.end());
430 joint = comb_ops.second;
431 joint_to_delete =
true;
438 del_one_var << del_var;
439 auto proj_ops = _projection_->operations(joint, del_one_var);
440 ops.push_back(proj_ops.first);
441 const IScheduleMultiDim* marginal = proj_ops.second;
442 if (is_result_persistent) multidim2op.insert(marginal, proj_ops.first);
445 if (joint_to_delete) {
446 auto deletion =
new ScheduleDeletion< TABLE >(
447 static_cast< const ScheduleMultiDim< TABLE >&
>(*joint));
448 ops.push_back(deletion);
456 for (
const auto ptrTab: tables_to_combine) {
457 const auto& table_vars = ptrTab->variablesSequence();
458 const Size tab_vars_size = table_vars.size();
460 for (Size i = 0; i < tab_vars_size; ++i) {
461 if (del_vars.contains(table_vars[i])) {
465 auto& table_vars_of_var_i = clique_vars_per_var[table_vars[i]];
466 double div_size = 1.0;
468 for (Size j = 0; j < tab_vars_size; ++j) {
469 unsigned int k = --table_vars_of_var_i[table_vars[j]];
472 div_size *= table_vars[j]->domainSize();
473 table_vars_of_var_i.erase(table_vars[j]);
477 tables_per_var[table_vars[i]].erase(ptrTab);
479 if (div_size != 1.0) {
480 product_size.setPriority(table_vars[i],
481 product_size.priority(table_vars[i]) / div_size);
488 if (!original_tables.contains(ptrTab)) {
489 auto deletion =
new ScheduleDeletion< TABLE >(
490 static_cast< const ScheduleMultiDim< TABLE >&
>(*ptrTab));
491 ops.push_back(deletion);
494 tables.erase(ptrTab);
497 tables_per_var.erase(del_var);
500 const auto& marginal_vars = marginal->variablesSequence();
501 for (
const auto mvar: marginal_vars) {
502 if (del_vars.contains(mvar)) {
504 tables_per_var[mvar].insert(marginal);
507 auto& iter_vars = clique_vars_per_var[mvar];
508 double mult_size = 1.0;
509 for (
const auto var: marginal_vars) {
513 iter_vars.insert(var, 1);
514 mult_size *= (
double)var->domainSize();
518 if (mult_size != 1.0) {
519 product_size.setPriority(mvar, product_size.priority(mvar) * mult_size);
524 tables.insert(marginal);
534 if (is_result_persistent) {
535 for (
const auto table: tables) {
536 if (multidim2op.exists(table)) multidim2op[table]->makeResultsPersistent(
true);
540 return {ops, tables};
544 template <
class TABLE >
545 INLINE
void MultiDimCombineAndProjectDefault< TABLE >::_freeData_(
546 std::vector< const IScheduleMultiDim* >& tables,
547 std::vector< ScheduleOperator* >& operations)
const {
548 for (
auto op: operations)
551 for (
auto table: tables)
A class to combine efficiently several MultiDim tables.
MultiDimCombineAndProjectDefault(TABLE(*combine)(const TABLE &, const TABLE &), TABLE(*project)(const TABLE &, const gum::VariableSet &))
Default constructor.
A generic interface to combine and project efficiently MultiDim tables.
A generic class to project efficiently a MultiDim table over a subset of its variables.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
Size size() const noexcept
Returns the number of elements in the set.
void insert(const Key &k)
Inserts a new element into the set.
#define GUM_ERROR(type, msg)
gum is the global namespace for all aGrUM entities
Set< const DiscreteVariable * > VariableSet