50#ifndef DOXYGEN_SHOULD_SKIP_THIS
62 template <
class TABLE >
66 GUM_CONSTRUCTOR(MultiDimCombinationDefault);
70 template <
class TABLE >
71 MultiDimCombinationDefault< TABLE >::MultiDimCombinationDefault(
72 const MultiDimCombinationDefault< TABLE >& from) :
73 MultiDimCombination< TABLE >(), _combine_(from._combine_) {
75 GUM_CONS_CPY(MultiDimCombinationDefault);
79 template <
class TABLE >
80 MultiDimCombinationDefault< TABLE >::~MultiDimCombinationDefault() {
82 GUM_DESTRUCTOR(MultiDimCombinationDefault);
86 template <
class TABLE >
87 MultiDimCombinationDefault< TABLE >* MultiDimCombinationDefault< TABLE >::clone()
const {
88 return new MultiDimCombinationDefault< TABLE >(_combine_);
92 template <
class TABLE >
93 void MultiDimCombinationDefault< TABLE >::setCombinationFunction(TABLE (*combine)(
const TABLE&,
99 template <
class TABLE >
100 INLINE TABLE (*MultiDimCombinationDefault< TABLE >::combinationFunction())(
const TABLE&,
106 template <
class TABLE >
107 INLINE
void MultiDimCombinationDefault< TABLE >::execute(TABLE& container,
108 const Set< const TABLE* >& set)
const {
109 TABLE* res = execute(set);
110 container = std::move(*res);
115 template <
class TABLE >
116 TABLE* MultiDimCombinationDefault< TABLE >::execute(
const Set< const TABLE* >& set)
const {
118 if (set.size() < 2) {
120 "the set passed to a MultiDimCombinationDefault"
121 " should at least contain two elements");
125 std::vector< const IScheduleMultiDim* > tables;
126 tables.reserve(set.size());
127 for (
const auto table: set) {
128 tables.push_back(
new ScheduleMultiDim< TABLE >(*table,
false));
132 auto ops_plus_res = operations(tables);
133 for (
auto op: ops_plus_res.first) {
138 auto& schedule_result =
const_cast< ScheduleMultiDim< TABLE >&
>(
139 static_cast< const ScheduleMultiDim< TABLE >&
>(*ops_plus_res.second));
143 auto result = schedule_result.exportMultiDim();
146 _freeData_(tables, ops_plus_res.first);
152 template <
class TABLE >
153 double MultiDimCombinationDefault< TABLE >::nbOperations(
154 const Set<
const Sequence< const DiscreteVariable* >* >& set)
const {
156 if (set.size() < 2)
return 0.0;
159 std::vector< const IScheduleMultiDim* > tables;
160 tables.reserve(set.size());
161 for (
const auto ptrVars: set) {
162 tables.push_back(
new ScheduleMultiDim< TABLE >(*ptrVars));
166 auto ops_plus_res = operations(tables);
167 double nb_operations = 0.0;
168 for (
const auto op: ops_plus_res.first) {
169 nb_operations += op->nbOperations();
173 _freeData_(tables, ops_plus_res.first);
175 return nb_operations;
179 template <
class TABLE >
180 double MultiDimCombinationDefault< TABLE >::nbOperations(
const Set< const TABLE* >& set)
const {
182 if (set.size() < 2)
return 0.0;
185 Set< const Sequence< const DiscreteVariable* >* > var_set(set.size());
187 for (
const auto ptrTab: set) {
188 var_set << &(ptrTab->variablesSequence());
191 return nbOperations(var_set);
195 template <
class TABLE >
196 std::pair< double, double > MultiDimCombinationDefault< TABLE >::memoryUsage(
197 const Set<
const Sequence< const DiscreteVariable* >* >& set)
const {
199 if (set.size() < 2)
return {0.0, 0.0};
202 std::vector< const IScheduleMultiDim* > tables;
203 tables.reserve(set.size());
204 for (
const auto ptrVars: set) {
205 tables.push_back(
new ScheduleMultiDim< TABLE >(*ptrVars));
209 auto ops_plus_res = operations(tables);
211 double max_memory = 0.0;
212 double end_memory = 0.0;
214 for (
const auto op: ops_plus_res.first) {
215 const auto usage = op->memoryUsage();
216 if (end_memory + usage.first > max_memory) max_memory = end_memory + usage.first;
217 end_memory += usage.second;
221 _freeData_(tables, ops_plus_res.first);
223 return {max_memory, end_memory};
227 template <
class TABLE >
228 std::pair< double, double >
229 MultiDimCombinationDefault< TABLE >::memoryUsage(
const Set< const TABLE* >& set)
const {
231 if (set.size() < 2)
return {0.0, 0.0};
234 Set< const Sequence< const DiscreteVariable* >* > var_set(set.size());
236 for (
const auto ptrTab: set) {
237 var_set << &(ptrTab->variablesSequence());
240 return memoryUsage(var_set);
245 template <
class TABLE >
247 MultiDimCombinationDefault< TABLE >::_combinedSize_(
const IScheduleMultiDim& table1,
248 const IScheduleMultiDim& table2)
const {
249 auto size =
double(table1.domainSize());
250 const auto& vars1 = table1.variablesSequence();
251 const auto& vars2 = table2.variablesSequence();
252 for (
const auto ptrVar: vars2)
253 if (!vars1.exists(ptrVar)) size *=
double(ptrVar->domainSize());
259 template <
class TABLE >
260 std::pair< std::vector< ScheduleOperator* >,
const IScheduleMultiDim* >
261 MultiDimCombinationDefault< TABLE >::operations(
262 const std::vector< const IScheduleMultiDim* >& original_tables,
263 const bool is_result_persistent)
const {
265 const Size tabsize = original_tables.size();
266 if (tabsize < 2)
return {};
270 std::vector< const IScheduleMultiDim* > tables = original_tables;
273 std::vector< ScheduleOperator* > operations;
274 operations.reserve(2 * tables.size());
280 std::vector< bool > is_t_new(tabsize,
false);
285 std::pair< Size, Size > pair;
286 PriorityQueue< std::pair< Size, Size >,
double > queue;
288 for (Size i = Size(0); i < tabsize; ++i) {
291 for (Size j = i + 1; j < tabsize; ++j) {
293 queue.insert(pair, _combinedSize_(*tables[i], *tables[j]));
299 const IScheduleMultiDim* resulting_table =
nullptr;
300 ScheduleOperator* resulting_op =
nullptr;
306 for (Size k = 1; k < tabsize; ++k) {
309 const Size ti = pair.first;
310 const Size tj = pair.second;
313 auto combination =
new ScheduleBinaryCombination< TABLE, TABLE, TABLE >(
314 static_cast< const ScheduleMultiDim< TABLE >&
>(*tables[ti]),
315 static_cast< const ScheduleMultiDim< TABLE >&
>(*tables[tj]),
317 operations.push_back(combination);
318 resulting_table = &combination->result();
319 resulting_op = combination;
323 auto deletion =
new ScheduleDeletion< TABLE >(
324 static_cast< const ScheduleMultiDim< TABLE >&
>(*tables[ti]));
325 operations.push_back(deletion);
328 auto deletion =
new ScheduleDeletion< TABLE >(
329 static_cast< const ScheduleMultiDim< TABLE >&
>(*tables[tj]));
330 operations.push_back(deletion);
334 tables[ti] = resulting_table;
336 tables[tj] =
nullptr;
339 for (Size ind = 0; ind < tj; ++ind) {
340 if (tables[ind] !=
nullptr) {
347 for (Size ind = tj + 1; ind < tabsize; ++ind) {
348 if (tables[ind] !=
nullptr) {
357 for (Size ind = 0; ind < ti; ++ind) {
358 if (tables[ind] !=
nullptr) {
360 queue.setPriority(pair, _combinedSize_(*resulting_table, *(tables[ind])));
365 for (Size ind = ti + 1; ind < tabsize; ++ind) {
366 if (tables[ind] !=
nullptr) {
368 queue.setPriority(pair, _combinedSize_(*resulting_table, *(tables[ind])));
375 if (is_result_persistent) { resulting_op->makeResultsPersistent(
true); }
377 return {operations, resulting_table};
381 template <
class TABLE >
382 std::pair< std::vector< ScheduleOperator* >,
const IScheduleMultiDim* >
383 MultiDimCombinationDefault< TABLE >::operations(
const Set< const IScheduleMultiDim* >& set,
384 const bool is_result_persistent)
const {
385 std::vector< const IScheduleMultiDim* > vect;
386 vect.reserve(set.size());
387 for (
const auto elt: set) {
390 return operations(vect, is_result_persistent);
394 template <
class TABLE >
395 INLINE
void MultiDimCombinationDefault< TABLE >::_freeData_(
396 std::vector< const IScheduleMultiDim* >& tables,
397 std::vector< ScheduleOperator* >& operations)
const {
398 for (
auto op: operations)
401 for (
auto table: tables)
Exception: the number of arguments passed to a function is not what was expected.
MultiDimCombinationDefault(TABLE(*combine)(const TABLE &, const TABLE &))
Default constructor.
A generic interface to combine efficiently several MultiDim tables.
#define GUM_ERROR(type, msg)
gum is the global namespace for all aGrUM entities
priority queues (in which an element cannot appear more than once)