aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
scheduleBinaryCombination_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2025 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40#pragma once
41
42
48
49#ifndef DOXYGEN_SHOULD_SKIP_THIS
50
51# include <limits>
52
53# include <agrum/agrum.h>
54
56
57namespace gum {
58
60 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
62 const ScheduleMultiDim< TABLE1 >& table1,
63 const ScheduleMultiDim< TABLE2 >& table2,
64 TABLE_RES (*combine)(const TABLE1&, const TABLE2&),
65 const bool is_result_persistent) :
66 ScheduleOperator(ScheduleOperatorType::COMBINE_MULTIDIM, false, is_result_persistent),
67 _arg1_(&table1), _arg2_(&table2), _combine_(combine) {
68 // compute the variables of the resulting table
69 Sequence< const DiscreteVariable* > vars = table1.variablesSequence();
70 const Sequence< const DiscreteVariable* >& vars2 = table2.variablesSequence();
71 for (const auto var: vars2) {
72 if (!vars.exists(var)) { vars.insert(var); }
73 }
74
75 // create the scheduleMultiDim that should result from the combination of
76 // table1 and table2
77 _result_ = new ScheduleMultiDim< TABLE_RES >(vars, Idx(0));
78
79 // save the args and result into _args_ and _results_
80 _args_ << _arg1_ << _arg2_;
81 _results_ << _result_;
82
83 // for debugging purposes
84 GUM_CONSTRUCTOR(ScheduleBinaryCombination);
85 }
86
88 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
89 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::ScheduleBinaryCombination(
90 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& from) :
91 ScheduleOperator(from), _arg1_(from._arg1_), _arg2_(from._arg2_), _combine_(from._combine_) {
92 // copy the result of the from operator
93 _result_ = from._result_->clone();
94
95 // save the args and result into _args_ and _results_
96 _args_ << _arg1_ << _arg2_;
97 _results_ << _result_;
98
99 // for debugging purposes
100 GUM_CONS_CPY(ScheduleBinaryCombination);
101 }
102
104 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
105 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::ScheduleBinaryCombination(
106 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >&& from) :
107 ScheduleOperator(std::move(from)), _arg1_(from._arg1_), _arg2_(from._arg2_),
108 _result_(from._result_), _combine_(from._combine_) {
109 // indicate that from does not contain anything anymore
110 from.makeResultsPersistent(true); // prevent deleting nullptr
111 from._result_ = nullptr;
112
113 // save the args and result into _args_ and _results_
114 _args_ = std::move(from._args_);
115 _results_ << _result_;
116
117 // for debugging purposes
118 GUM_CONS_MOV(ScheduleBinaryCombination);
119 }
120
122 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
123 INLINE ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >*
124 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::clone() const {
125 return new ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >(*this);
126 }
127
129 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
130 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::~ScheduleBinaryCombination() {
131 // if the result is not persistent, we should remove it
132 if (!this->hasPersistentResults()) { delete _result_; }
133
134 // for debugging purposes
135 GUM_DESTRUCTOR(ScheduleBinaryCombination);
136 }
137
139 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
140 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >&
141 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator=(
142 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& from) {
143 if (this != &from) {
144 // try to copy result (no need to update _results_)
145 *_result_ = *(from._result_);
146 ScheduleOperator::operator=(from);
147
148 _arg1_ = from._arg1_;
149 _arg2_ = from._arg2_;
150 _args_ = from._args_;
151 _combine_ = from._combine_;
152 }
153 return *this;
154 }
155
157 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
158 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >&
159 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator=(
160 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >&& from) {
161 if (this != &from) {
162 if (!this->hasPersistentResults()) delete _result_;
163 _result_ = from._result_;
164 ScheduleOperator::operator=(std::move(from));
165
166 _arg1_ = from._arg1_;
167 _arg2_ = from._arg2_;
168 _args_ = std::move(from._args_);
169 _combine_ = from._combine_;
170
171 from.makeResultsPersistent(true); // prevent deleting nullptr
172 from._result_ = nullptr;
173 }
174 return *this;
175 }
176
178 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
179 INLINE bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(
180 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
181 return (_combine_ == op._combine_) && (*_arg1_ == *op._arg1_) && (*_arg2_ == *op._arg2_);
182 }
183
185 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
186 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(
187 const ScheduleOperator& op) const {
188 if (ScheduleOperator::operator!=(op)) return false;
189
190 try {
191 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& real_op
192 = dynamic_cast< const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& >(op);
193 return ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(real_op);
194 } catch (std::bad_cast&) { return false; }
195 }
196
198 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
199 INLINE bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator!=(
200 const ScheduleOperator& op) const {
201 return !ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(op);
202 }
203
205 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
206 INLINE bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator!=(
207 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
208 return !ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(op);
209 }
210
212 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
213 INLINE bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSameArguments(
214 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
215 return (_arg1_->hasSameVariables(*op._arg1_) && _arg2_->hasSameVariables(*op._arg2_)
216 && _arg1_->hasSameContent(*op._arg1_) && _arg2_->hasSameContent(*op._arg2_));
217 }
218
220 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
221 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSameArguments(
222 const ScheduleOperator& op) const {
223 try {
224 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& real_op
225 = dynamic_cast< const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& >(op);
226 return ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSameArguments(real_op);
227 } catch (std::bad_cast&) { return false; }
228 }
229
231 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
232 INLINE bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSimilarArguments(
233 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
234 return (_arg1_->hasSameVariables(*op._arg1_) && _arg2_->hasSameVariables(*op._arg2_));
235 }
236
238 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
239 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSimilarArguments(
240 const ScheduleOperator& op) const {
241 try {
242 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& real_op
243 = dynamic_cast< const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& >(op);
244 return ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSimilarArguments(real_op);
245 } catch (std::bad_cast&) { return false; }
246 }
247
249 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
250 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::isSameOperator(
251 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
252 return _combine_ == op._combine_;
253 }
254
256 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
257 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::isSameOperator(
258 const ScheduleOperator& op) const {
259 try {
260 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& real_op
261 = dynamic_cast< const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& >(op);
262 return ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::isSameOperator(real_op);
263 } catch (std::bad_cast&) { return false; }
264 }
265
267 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
268 INLINE const ScheduleMultiDim< TABLE1 >&
269 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::arg1() const {
270 return *_arg1_;
271 }
272
274 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
275 INLINE const ScheduleMultiDim< TABLE2 >&
276 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::arg2() const {
277 return *_arg2_;
278 }
279
281 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
282 INLINE const Sequence< const IScheduleMultiDim* >&
283 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::args() const {
284 return _args_;
285 }
286
288 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
289 INLINE const ScheduleMultiDim< TABLE_RES >&
290 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::result() const {
291 return *_result_;
292 }
293
295 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
296 INLINE const Sequence< const IScheduleMultiDim* >&
297 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::results() const {
298 return _results_;
299 }
300
302 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
303 void ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::updateArgs(
304 const Sequence< const IScheduleMultiDim* >& new_args) {
305 // check that there are exactly two arguments in new_args and that their
306 // types are compatible with TABLE1 and TABLE2
307 if (new_args.size() != Size(2)) {
309 "Method ScheduleBinaryCombination::updateArgs expects 2 new "
310 << "arguments, but " << new_args.size() << " were passed.");
311 }
312 const ScheduleMultiDim< TABLE1 >* arg1;
313 const ScheduleMultiDim< TABLE2 >* arg2;
314 try {
315 arg1 = dynamic_cast< const ScheduleMultiDim< TABLE1 >* >(new_args[0]);
316 } catch (std::bad_cast&) {
318 "The type of the first argument passed to "
319 << "ScheduleBinaryCombination::updateArgs does not match what "
320 << "the ScheduleOperator expects");
321 }
322 try {
323 arg2 = dynamic_cast< const ScheduleMultiDim< TABLE2 >* >(new_args[1]);
324 } catch (std::bad_cast&) {
326 "The type of the second argument passed to "
327 << "ScheduleBinaryCombination::updateArgs does not match what "
328 << "the ScheduleOperator expects");
329 }
330
331 // save the new arguments
332 _arg1_ = arg1;
333 _arg2_ = arg2;
334 _args_ = {_arg1_, _arg2_};
335
336 // now the result is obsolete, so make it abstract
337 _result_->makeAbstract();
338 }
339
341 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
342 INLINE bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::isExecuted() const {
343 return !_result_->isAbstract();
344 }
345
347 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
348 void ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::execute() {
349 if (_result_->isAbstract()) {
350 // first, get the tables to combine
351 const TABLE1& t1 = _arg1_->multiDim();
352 const TABLE2& t2 = _arg2_->multiDim();
353
354 // perform the combination and store the result
355 TABLE_RES res = _combine_(t1, t2);
356 _result_->setMultiDim(std::move(res));
357 }
358 }
359
361 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
362 void ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::undo() {
363 _result_->makeAbstract();
364 }
365
368 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
369 double ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::nbOperations() const {
370 return double(_result_->domainSize());
371 }
372
374 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
375 INLINE std::pair< double, double >
376 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::memoryUsage() const {
377 const double domsize
378 = double(_result_->domainSize()) * _result_->sizeOfContent() + sizeof(TABLE_RES);
379 return {domsize, domsize};
380 }
381
383 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
384 std::string ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::toString() const {
385 return _result_->toString() + " = combine ( " + _arg1_->toString() + " , " + _arg2_->toString()
386 + " )";
387 }
388
390 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
391 void ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::setCombinationFunction(
392 TABLE_RES (*combine)(const TABLE1&, const TABLE2&)) {
393 _combine_ = combine;
394 _result_->makeAbstract();
395 }
396
397
398} // namespace gum
399
400#endif /* DOXYGEN_SHOULD_SKIP_THIS */
ScheduleBinaryCombination(const ScheduleMultiDim< TABLE1 > &table1, const ScheduleMultiDim< TABLE2 > &table2, TABLE_RES(*combine)(const TABLE1 &, const TABLE2 &), const bool is_result_persistent=false)
default constructor
the base class for "low-level" operators used to schedule inferences
Exception : problem with size.
Exception : wrong type for this operation.
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
ScheduleOperatorType
the currently supported types of "low-level" operators
@ COMBINE_MULTIDIM
combine 2 ScheduleMultiDims
STL namespace.
a binary Combination operator class used for scheduling inferences