aGrUM 3.1.1
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-2026 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-2026 *
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
41#pragma once
42
43
49
51#ifndef DOXYGEN_SHOULD_SKIP_THIS
52
53# include <limits>
54
55# include <agrum/agrum.h>
56
58
59namespace gum {
60
62 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
64 const ScheduleMultiDim< TABLE1 >& table1,
65 const ScheduleMultiDim< TABLE2 >& table2,
66 TABLE_RES (*combine)(const TABLE1&, const TABLE2&),
67 const bool is_result_persistent) :
68 ScheduleOperator(ScheduleOperatorType::COMBINE_MULTIDIM, false, is_result_persistent),
69 _arg1_(&table1), _arg2_(&table2), _combine_(combine) {
70 // compute the variables of the resulting table
71 Sequence< const DiscreteVariable* > vars = table1.variablesSequence();
72 const Sequence< const DiscreteVariable* >& vars2 = table2.variablesSequence();
73 for (const auto var: vars2) {
74 if (!vars.exists(var)) { vars.insert(var); }
75 }
76
77 // create the scheduleMultiDim that should result from the combination of
78 // table1 and table2
79 _result_ = new ScheduleMultiDim< TABLE_RES >(vars, Idx(0));
80
81 // save the args and result into _args_ and _results_
82 _args_ << _arg1_ << _arg2_;
83 _results_ << _result_;
84
85 // for debugging purposes
86 GUM_CONSTRUCTOR(ScheduleBinaryCombination);
87 }
88
90 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
91 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::ScheduleBinaryCombination(
92 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& from) :
93 ScheduleOperator(from), _arg1_(from._arg1_), _arg2_(from._arg2_), _combine_(from._combine_) {
94 // copy the result of the from operator
95 _result_ = from._result_->clone();
96
97 // save the args and result into _args_ and _results_
98 _args_ << _arg1_ << _arg2_;
99 _results_ << _result_;
100
101 // for debugging purposes
102 GUM_CONS_CPY(ScheduleBinaryCombination);
103 }
104
106 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
107 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::ScheduleBinaryCombination(
108 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >&& from) :
109 ScheduleOperator(std::move(from)), _arg1_(from._arg1_), _arg2_(from._arg2_),
110 _result_(from._result_), _combine_(from._combine_) {
111 // indicate that from does not contain anything anymore
112 from.makeResultsPersistent(true); // prevent deleting nullptr
113 from._result_ = nullptr;
114
115 // save the args and result into _args_ and _results_
116 _args_ = std::move(from._args_);
117 _results_ << _result_;
118
119 // for debugging purposes
120 GUM_CONS_MOV(ScheduleBinaryCombination);
121 }
122
124 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
125 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >*
126 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::clone() const {
127 return new ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >(*this);
128 }
129
131 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
132 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::~ScheduleBinaryCombination() {
133 // if the result is not persistent, we should remove it
134 if (!this->hasPersistentResults()) { delete _result_; }
135
136 // for debugging purposes
137 GUM_DESTRUCTOR(ScheduleBinaryCombination);
138 }
139
141 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
142 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >&
143 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator=(
144 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& from) {
145 if (this != &from) {
146 // try to copy result (no need to update _results_)
147 *_result_ = *(from._result_);
148 ScheduleOperator::operator=(from);
149
150 _arg1_ = from._arg1_;
151 _arg2_ = from._arg2_;
152 _args_ = from._args_;
153 _combine_ = from._combine_;
154 }
155 return *this;
156 }
157
159 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
160 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >&
161 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator=(
162 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >&& from) {
163 if (this != &from) {
164 if (!this->hasPersistentResults()) delete _result_;
165 _result_ = from._result_;
166 ScheduleOperator::operator=(std::move(from));
167
168 _arg1_ = from._arg1_;
169 _arg2_ = from._arg2_;
170 _args_ = std::move(from._args_);
171 _combine_ = from._combine_;
172
173 from.makeResultsPersistent(true); // prevent deleting nullptr
174 from._result_ = nullptr;
175 }
176 return *this;
177 }
178
180 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
181 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(
182 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
183 return (_combine_ == op._combine_) && (*_arg1_ == *op._arg1_) && (*_arg2_ == *op._arg2_);
184 }
185
187 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
188 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(
189 const ScheduleOperator& op) const {
190 if (ScheduleOperator::operator!=(op)) return false;
191
192 try {
193 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& real_op
194 = dynamic_cast< const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& >(op);
195 return ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(real_op);
196 } catch (std::bad_cast&) { return false; }
197 }
198
200 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
201 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator!=(
202 const ScheduleOperator& op) const {
203 return !ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(op);
204 }
205
207 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
208 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator!=(
209 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
210 return !ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::operator==(op);
211 }
212
214 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
215 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSameArguments(
216 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
217 return (_arg1_->hasSameVariables(*op._arg1_) && _arg2_->hasSameVariables(*op._arg2_)
218 && _arg1_->hasSameContent(*op._arg1_) && _arg2_->hasSameContent(*op._arg2_));
219 }
220
222 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
223 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSameArguments(
224 const ScheduleOperator& op) const {
225 try {
226 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& real_op
227 = dynamic_cast< const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& >(op);
228 return ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSameArguments(real_op);
229 } catch (std::bad_cast&) { return false; }
230 }
231
233 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
234 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSimilarArguments(
235 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
236 return (_arg1_->hasSameVariables(*op._arg1_) && _arg2_->hasSameVariables(*op._arg2_));
237 }
238
240 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
241 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSimilarArguments(
242 const ScheduleOperator& op) const {
243 try {
244 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& real_op
245 = dynamic_cast< const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& >(op);
246 return ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::hasSimilarArguments(real_op);
247 } catch (std::bad_cast&) { return false; }
248 }
249
251 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
252 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::isSameOperator(
253 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& op) const {
254 return _combine_ == op._combine_;
255 }
256
258 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
259 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::isSameOperator(
260 const ScheduleOperator& op) const {
261 try {
262 const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& real_op
263 = dynamic_cast< const ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >& >(op);
264 return ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::isSameOperator(real_op);
265 } catch (std::bad_cast&) { return false; }
266 }
267
269 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
270 const ScheduleMultiDim< TABLE1 >&
271 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::arg1() const {
272 return *_arg1_;
273 }
274
276 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
277 const ScheduleMultiDim< TABLE2 >&
278 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::arg2() const {
279 return *_arg2_;
280 }
281
283 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
284 const Sequence< const IScheduleMultiDim* >&
285 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::args() const {
286 return _args_;
287 }
288
290 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
291 const ScheduleMultiDim< TABLE_RES >&
292 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::result() const {
293 return *_result_;
294 }
295
297 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
298 const Sequence< const IScheduleMultiDim* >&
299 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::results() const {
300 return _results_;
301 }
302
304 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
305 void ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::updateArgs(
306 const Sequence< const IScheduleMultiDim* >& new_args) {
307 // check that there are exactly two arguments in new_args and that their
308 // types are compatible with TABLE1 and TABLE2
309 if (new_args.size() != Size(2)) {
311 "Method ScheduleBinaryCombination::updateArgs expects 2 new "
312 << "arguments, but " << new_args.size() << " were passed.");
313 }
314 const ScheduleMultiDim< TABLE1 >* arg1;
315 const ScheduleMultiDim< TABLE2 >* arg2;
316 try {
317 arg1 = dynamic_cast< const ScheduleMultiDim< TABLE1 >* >(new_args[0]);
318 } catch (std::bad_cast&) {
320 "The type of the first argument passed to "
321 << "ScheduleBinaryCombination::updateArgs does not match what "
322 << "the ScheduleOperator expects");
323 }
324 try {
325 arg2 = dynamic_cast< const ScheduleMultiDim< TABLE2 >* >(new_args[1]);
326 } catch (std::bad_cast&) {
328 "The type of the second argument passed to "
329 << "ScheduleBinaryCombination::updateArgs does not match what "
330 << "the ScheduleOperator expects");
331 }
332
333 // save the new arguments
334 _arg1_ = arg1;
335 _arg2_ = arg2;
336 _args_ = {_arg1_, _arg2_};
337
338 // now the result is obsolete, so make it abstract
339 _result_->makeAbstract();
340 }
341
343 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
344 bool ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::isExecuted() const {
345 return !_result_->isAbstract();
346 }
347
349 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
350 void ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::execute() {
351 if (_result_->isAbstract()) {
352 // first, get the tables to combine
353 const TABLE1& t1 = _arg1_->multiDim();
354 const TABLE2& t2 = _arg2_->multiDim();
355
356 // perform the combination and store the result
357 TABLE_RES res = _combine_(t1, t2);
358 _result_->setMultiDim(std::move(res));
359 }
360 }
361
363 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
364 void ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::undo() {
365 _result_->makeAbstract();
366 }
367
370 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
371 double ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::nbOperations() const {
372 return double(_result_->domainSize());
373 }
374
376 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
377 std::pair< double, double >
378 ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::memoryUsage() const {
379 const double domsize
380 = double(_result_->domainSize()) * _result_->sizeOfContent() + sizeof(TABLE_RES);
381 return {domsize, domsize};
382 }
383
385 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
386 std::string ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::toString() const {
387 return _result_->toString() + " = combine ( " + _arg1_->toString() + " , " + _arg2_->toString()
388 + " )";
389 }
390
392 template < typename TABLE1, typename TABLE2, typename TABLE_RES >
393 void ScheduleBinaryCombination< TABLE1, TABLE2, TABLE_RES >::setCombinationFunction(
394 TABLE_RES (*combine)(const TABLE1&, const TABLE2&)) {
395 _combine_ = combine;
396 _result_->makeAbstract();
397 }
398
399
400} // namespace gum
401
402#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:76
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