52#ifndef DOXYGEN_SHOULD_SKIP_THIS
63 template <
class TABLE >
65 TABLE (*combine)(
const TABLE&,
const TABLE&),
71 GUM_CONSTRUCTOR(MultiDimCombineAndProjectDefault);
75 template <
class TABLE >
76 MultiDimCombineAndProjectDefault< TABLE >::MultiDimCombineAndProjectDefault(
77 const MultiDimCombineAndProjectDefault< TABLE >& from) :
78 MultiDimCombineAndProject< TABLE >(), _combination_(from._combination_->clone()),
79 _projection_(from._projection_->clone()) {
81 GUM_CONS_CPY(MultiDimCombineAndProjectDefault);
85 template <
class TABLE >
86 MultiDimCombineAndProjectDefault< TABLE >::~MultiDimCombineAndProjectDefault() {
88 GUM_DESTRUCTOR(MultiDimCombineAndProjectDefault);
94 template <
class TABLE >
95 MultiDimCombineAndProjectDefault< TABLE >*
96 MultiDimCombineAndProjectDefault< TABLE >::clone()
const {
97 return new MultiDimCombineAndProjectDefault< TABLE >(*
this);
101 template <
class TABLE >
103 MultiDimCombineAndProjectDefault< TABLE >::execute(
const Set< const TABLE* >& table_set,
106 std::vector< const IScheduleMultiDim* > tables;
107 tables.reserve(table_set.size());
108 for (
const auto table: table_set) {
109 tables.push_back(
new ScheduleMultiDim< TABLE >(*table,
false));
113 auto ops_plus_res = operations(tables, del_vars,
false);
114 for (
auto op: ops_plus_res.first) {
119 Set< const TABLE* > result(ops_plus_res.second.size());
120 for (
const auto pot: ops_plus_res.second) {
121 auto& schedule_result =
const_cast< ScheduleMultiDim< TABLE >&
>(
122 static_cast< const ScheduleMultiDim< TABLE >&
>(*pot));
123 auto potres =
new TABLE(std::move(schedule_result.multiDim()));
124 result.insert(potres);
128 _freeData_(tables, ops_plus_res.first);
134 template <
class TABLE >
135 void MultiDimCombineAndProjectDefault< TABLE >::setCombinationFunction(
136 TABLE (*combine)(
const TABLE&,
const TABLE&)) {
137 _combination_->setCombinationFunction(combine);
141 template <
class TABLE >
142 TABLE (*MultiDimCombineAndProjectDefault< TABLE >::combinationFunction())(
const TABLE&,
144 return _combination_->combinationFunction();
148 template <
class TABLE >
149 void MultiDimCombineAndProjectDefault< TABLE >::setCombinationClass(
150 const MultiDimCombination< TABLE >& comb_class) {
151 delete _combination_;
152 _combination_ = comb_class.clone();
156 template <
class TABLE >
157 void MultiDimCombineAndProjectDefault< TABLE >::setProjectionFunction(
159 _projection_->setProjectionFunction(proj);
163 template <
class TABLE >
164 TABLE (*MultiDimCombineAndProjectDefault< TABLE >::projectionFunction())(
167 return _projection_->projectionFunction();
171 template <
class TABLE >
172 void MultiDimCombineAndProjectDefault< TABLE >::setProjectionClass(
173 const MultiDimProjection< TABLE >& proj_class) {
175 _projection_ = proj_class.clone();
180 template <
class TABLE >
181 double MultiDimCombineAndProjectDefault< TABLE >::nbOperations(
182 const Set<
const Sequence< const DiscreteVariable* >* >& table_set,
185 std::vector< const IScheduleMultiDim* > tables;
186 tables.reserve(table_set.size());
187 for (
const auto vars: table_set) {
188 tables.push_back(
new ScheduleMultiDim< TABLE >(*vars,
false));
192 auto ops_plus_res = operations(tables, del_vars,
false);
193 double nb_operations = 0.0;
194 for (
auto op: ops_plus_res.first) {
195 nb_operations += op->nbOperations();
199 _freeData_(tables, ops_plus_res.first);
201 return nb_operations;
206 template <
class TABLE >
207 double MultiDimCombineAndProjectDefault< TABLE >::nbOperations(
208 const Set< const TABLE* >& set,
211 Set< const Sequence< const DiscreteVariable* >* > var_set(set.size());
213 for (
const auto ptrTab: set) {
214 var_set << &(ptrTab->variablesSequence());
217 return nbOperations(var_set, del_vars);
222 template <
class TABLE >
223 std::pair< double, double > MultiDimCombineAndProjectDefault< TABLE >::memoryUsage(
224 const Set<
const Sequence< const DiscreteVariable* >* >& table_set,
227 std::vector< const IScheduleMultiDim* > tables;
228 tables.reserve(table_set.size());
229 for (
const auto vars: table_set) {
230 tables.push_back(
new ScheduleMultiDim< TABLE >(*vars,
false));
234 auto ops_plus_res = operations(tables, del_vars,
false);
237 double max_memory = 0.0;
238 double end_memory = 0.0;
239 for (
const auto op: ops_plus_res.first) {
240 const auto usage = op->memoryUsage();
241 if (end_memory + usage.first > max_memory) max_memory = end_memory + usage.first;
242 end_memory += usage.second;
246 _freeData_(tables, ops_plus_res.first);
248 return {max_memory, end_memory};
253 template <
class TABLE >
254 std::pair< double, double > MultiDimCombineAndProjectDefault< TABLE >::memoryUsage(
255 const Set< const TABLE* >& set,
258 Set< const Sequence< const DiscreteVariable* >* > var_set(set.size());
260 for (
const auto ptrTab: set) {
261 var_set << &(ptrTab->variablesSequence());
264 return memoryUsage(var_set, del_vars);
269 template <
class TABLE >
270 std::pair< std::vector< ScheduleOperator* >, Set< const IScheduleMultiDim* > >
271 MultiDimCombineAndProjectDefault< TABLE >::operations(
272 const std::vector< const IScheduleMultiDim* >& original_tables,
274 const bool is_result_persistent)
const {
275 Set< const IScheduleMultiDim* > tables_set(original_tables.size());
276 for (
const auto table: original_tables) {
277 tables_set.insert(table);
279 return operations(tables_set, del_vars, is_result_persistent);
284 template <
class TABLE >
285 std::pair< std::vector< ScheduleOperator* >, Set< const IScheduleMultiDim* > >
286 MultiDimCombineAndProjectDefault< TABLE >::operations(
287 const Set< const IScheduleMultiDim* >& original_tables,
289 const bool is_result_persistent)
const {
291 const Size tabsize = original_tables.size();
294 auto res = _projection_->operations(*original_tables.begin(), original_del_vars);
295 return std::pair< std::vector< ScheduleOperator* >, Set< const IScheduleMultiDim* > >(
300 for (
const auto& v: original_del_vars) {
301 names += v->name() +
", ";
304 "MultiDimCombineAndProject need at least one table to "
305 "have some work to do (original_del_vars ="
312 Set< const IScheduleMultiDim* > tables = original_tables;
328 for (
const auto table: tables) {
329 for (
const auto ptrVar: table->variablesSequence()) {
334 nb_vars = all_vars.
size();
338 HashTable< const DiscreteVariable*, Set< const IScheduleMultiDim* > > tables_per_var(nb_vars);
345 HashTable< const DiscreteVariable*, HashTable< const DiscreteVariable*, unsigned int > >
346 clique_vars_per_var(nb_vars);
350 Set< const IScheduleMultiDim* > empty_set(tables.size());
351 HashTable< const DiscreteVariable*, unsigned int > empty_hash(nb_vars);
353 for (
const auto ptrVar: del_vars) {
354 tables_per_var.insert(ptrVar, empty_set);
355 clique_vars_per_var.insert(ptrVar, empty_hash);
359 for (
const auto ptrTab: tables) {
360 const auto& vars = ptrTab->variablesSequence();
362 for (
const auto ptrVar: vars) {
363 if (del_vars.contains(ptrVar)) {
365 tables_per_var[ptrVar].insert(ptrTab);
368 auto& comb_vars = clique_vars_per_var[ptrVar];
369 for (
const auto xptrVar: vars) {
370 if (
auto ptr = comb_vars.tryGet(xptrVar)) ++(*ptr);
371 else comb_vars.insert(xptrVar, 1);
380 std::vector< ScheduleOperator* > ops;
381 ops.reserve(2 * tables.size() + del_vars.size());
385 HashTable< const IScheduleMultiDim*, ScheduleOperator* > multidim2op(tables.size());
388 PriorityQueue< const DiscreteVariable*, double > product_size;
391 for (
const auto& elt: clique_vars_per_var) {
393 const auto ptrVar = elt.first;
394 const auto& hashvars = elt.second;
396 if (!hashvars.empty()) {
397 for (
const auto& xelt: hashvars) {
398 size *= (
double)xelt.first->domainSize();
401 product_size.insert(ptrVar, size);
407 while (!product_size.empty()) {
409 const DiscreteVariable* del_var = product_size.pop();
410 del_vars.erase(del_var);
413 auto& tables_to_combine = tables_per_var[del_var];
416 if (tables_to_combine.empty())
continue;
421 const IScheduleMultiDim* joint =
nullptr;
422 bool joint_to_delete;
423 if (tables_to_combine.size() == 1) {
424 joint = *(tables_to_combine.begin());
425 joint_to_delete =
false;
429 auto comb_ops = _combination_->operations(tables_to_combine);
430 ops.insert(ops.cend(), comb_ops.first.begin(), comb_ops.first.end());
431 joint = comb_ops.second;
432 joint_to_delete =
true;
439 del_one_var << del_var;
440 auto proj_ops = _projection_->operations(joint, del_one_var);
441 ops.push_back(proj_ops.first);
442 const IScheduleMultiDim* marginal = proj_ops.second;
443 if (is_result_persistent) multidim2op.insert(marginal, proj_ops.first);
446 if (joint_to_delete) {
447 auto deletion =
new ScheduleDeletion< TABLE >(
448 static_cast< const ScheduleMultiDim< TABLE >&
>(*joint));
449 ops.push_back(deletion);
457 for (
const auto ptrTab: tables_to_combine) {
458 const auto& table_vars = ptrTab->variablesSequence();
459 const Size tab_vars_size = table_vars.size();
461 for (Size i = 0; i < tab_vars_size; ++i) {
462 if (del_vars.contains(table_vars[i])) {
466 auto& table_vars_of_var_i = clique_vars_per_var[table_vars[i]];
467 double div_size = 1.0;
469 for (Size j = 0; j < tab_vars_size; ++j) {
470 unsigned int k = --table_vars_of_var_i[table_vars[j]];
473 div_size *= table_vars[j]->domainSize();
474 table_vars_of_var_i.erase(table_vars[j]);
478 tables_per_var[table_vars[i]].erase(ptrTab);
480 if (div_size != 1.0) {
481 product_size.setPriority(table_vars[i],
482 product_size.priority(table_vars[i]) / div_size);
489 if (!original_tables.contains(ptrTab)) {
490 auto deletion =
new ScheduleDeletion< TABLE >(
491 static_cast< const ScheduleMultiDim< TABLE >&
>(*ptrTab));
492 ops.push_back(deletion);
495 tables.erase(ptrTab);
498 tables_per_var.erase(del_var);
501 const auto& marginal_vars = marginal->variablesSequence();
502 for (
const auto mvar: marginal_vars) {
503 if (del_vars.contains(mvar)) {
505 tables_per_var[mvar].insert(marginal);
508 auto& iter_vars = clique_vars_per_var[mvar];
509 double mult_size = 1.0;
510 for (
const auto var: marginal_vars) {
511 if (
auto ptr = iter_vars.tryGet(var)) {
514 iter_vars.insert(var, 1);
515 mult_size *= (
double)var->domainSize();
519 if (mult_size != 1.0) {
520 product_size.setPriority(mvar, product_size.priority(mvar) * mult_size);
525 tables.insert(marginal);
535 if (is_result_persistent) {
536 for (
const auto table: tables) {
537 if (multidim2op.exists(table)) multidim2op[table]->makeResultsPersistent(
true);
541 return {ops, tables};
545 template <
class TABLE >
546 void MultiDimCombineAndProjectDefault< TABLE >::_freeData_(
547 std::vector< const IScheduleMultiDim* >& tables,
548 std::vector< ScheduleOperator* >& operations)
const {
549 for (
auto op: operations)
552 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 : operation not allowed.
void insert(const Key &k)
Inserts a new element into the set.
Size size() const noexcept
Returns the number of elements in the set.
#define GUM_ERROR(type, msg)
gum is the global namespace for all aGrUM entities
Set< const DiscreteVariable * > VariableSet