aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
graphChangesGeneratorOnSubDiGraph_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
49#ifndef DOXYGEN_SHOULD_SKIP_THIS
50
51namespace gum {
52
53 namespace learning {
54
56 template < typename STRUCT_CONSTRAINT >
58 STRUCT_CONSTRAINT& constraint) : constraint_(&constraint) {
59 GUM_CONSTRUCTOR(GraphChangesGeneratorOnSubDiGraph);
60 }
61
63 template < typename STRUCT_CONSTRAINT >
64 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::GraphChangesGeneratorOnSubDiGraph(
65 const GraphChangesGeneratorOnSubDiGraph& from) :
66 constraint_(from.constraint_), target_nodes_(from.target_nodes_),
67 tail_nodes_(from.tail_nodes_), legal_changes_(from.legal_changes_),
68 _max_threads_number_(from._max_threads_number_) {
69 GUM_CONS_CPY(GraphChangesGeneratorOnSubDiGraph);
70 }
71
73 template < typename STRUCT_CONSTRAINT >
74 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::GraphChangesGeneratorOnSubDiGraph(
75 GraphChangesGeneratorOnSubDiGraph&& from) :
76 constraint_(from.constraint_), target_nodes_(std::move(from.target_nodes_)),
77 tail_nodes_(std::move(from.tail_nodes_)), legal_changes_(std::move(from.legal_changes_)),
78 _max_threads_number_(from._max_threads_number_) {
79 GUM_CONS_MOV(GraphChangesGeneratorOnSubDiGraph);
80 }
81
83 template < typename STRUCT_CONSTRAINT >
84 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::~GraphChangesGeneratorOnSubDiGraph() {
85 GUM_DESTRUCTOR(GraphChangesGeneratorOnSubDiGraph);
86 }
87
89 template < typename STRUCT_CONSTRAINT >
90 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >&
91 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::operator=(
92 const GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >& from) {
93 if (this != &from) {
94 constraint_ = from.constraint_;
95 target_nodes_ = from.target_nodes_;
96 tail_nodes_ = from.tail_nodes_;
97 legal_changes_ = from.legal_changes_;
98 _max_threads_number_ = from._max_threads_number_;
99 }
100 return *this;
101 }
102
104 template < typename STRUCT_CONSTRAINT >
105 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >&
106 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::operator=(
107 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >&& from) {
108 if (this != &from) {
109 constraint_ = std::move(from.constraint_);
110 target_nodes_ = std::move(from.target_nodes_);
111 tail_nodes_ = std::move(from.tail_nodes_);
112 legal_changes_ = std::move(from.legal_changes_);
113 _max_threads_number_ = from._max_threads_number_;
114 }
115 return *this;
116 }
117
119 template < typename STRUCT_CONSTRAINT >
120 void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::createChanges_() {
121 legal_changes_.clear();
122
123 // for all the pairs of nodes, consider adding, reverse and removing arcs
124 // do it for each thread
125 const Size nb_threads = _max_threads_number_;
126 std::vector< Set< GraphChange > > legal_changes(nb_threads);
127
128 // create the lambda that will be used to fill the legal changes
129 auto threadedLegalSet = [this, &legal_changes](const std::size_t this_thread,
130 const std::size_t nb_threads) -> void {
131 Idx i = 0;
132 for (const auto node1: this->tail_nodes_) {
133 if (i == this_thread) {
134 for (const auto node2: this->target_nodes_) {
135 if (node1 != node2) {
136 // try arc additions
137 ArcAddition arc_add(node1, node2);
138 if (!this->constraint_->isAlwaysInvalid(arc_add)) {
139 legal_changes[this_thread].insert(std::move(arc_add));
140 }
141
142 // try arc deletion
143 ArcDeletion arc_del(node1, node2);
144 if (!this->constraint_->isAlwaysInvalid(arc_del)) {
145 legal_changes[this_thread].insert(std::move(arc_del));
146 }
147
148 // try arc reversal
149 ArcReversal arc_rev(node1, node2);
150 if (!this->constraint_->isAlwaysInvalid(arc_rev)) {
151 legal_changes[this_thread].insert(std::move(arc_rev));
152 }
153 }
154 }
155 }
156 ++i;
157 i %= nb_threads;
158 }
159 };
160
161 // launch the threads
162 ThreadExecutor::execute(nb_threads, threadedLegalSet);
163
164
165 // now store the changes into the protected vectors of the
166 // GraphChangesGeneratorOnSubDiGraph
167 for (const auto& changes: legal_changes) {
168 for (const auto& change: changes) {
169 legal_changes_.insert(std::move(change));
170 }
171 }
172 }
173
175 template < typename STRUCT_CONSTRAINT >
176 INLINE void
177 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::setGraph(const DiGraph& graph) {
178 // generate the set of all changes
179 createChanges_();
180 }
181
183 template < typename STRUCT_CONSTRAINT >
184 INLINE void
185 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::setTargets(const NodeSet& nodes) {
186 target_nodes_ = nodes;
187 }
188
190 template < typename STRUCT_CONSTRAINT >
191 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::addTarget(NodeId node) {
192 target_nodes_.insert(node);
193 }
194
196 template < typename STRUCT_CONSTRAINT >
197 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::eraseTarget(NodeId node) {
198 target_nodes_.erase(node);
199 }
200
202 template < typename STRUCT_CONSTRAINT >
203 INLINE void
204 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::setTails(const NodeSet& nodes) {
205 tail_nodes_ = nodes;
206 }
207
209 template < typename STRUCT_CONSTRAINT >
210 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::setTails(Size nb_nodes) {
211 tail_nodes_.clear();
212 for (Idx i = 0; i < nb_nodes; ++i) {
213 tail_nodes_.insert(i);
214 }
215 }
216
218 template < typename STRUCT_CONSTRAINT >
219 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::addTail(NodeId node) {
220 tail_nodes_.insert(node);
221 }
222
224 template < typename STRUCT_CONSTRAINT >
225 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::eraseTail(NodeId node) {
226 tail_nodes_.erase(node);
227 }
228
230 template < typename STRUCT_CONSTRAINT >
231 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::clearChanges() noexcept {
232 legal_changes_.clear();
233 }
234
236 template < typename STRUCT_CONSTRAINT >
237 INLINE typename GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::iterator
238 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::begin() const {
239 return legal_changes_.cbegin();
240 }
241
243 template < typename STRUCT_CONSTRAINT >
244 INLINE const typename GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::iterator&
245 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::end() const {
246 return legal_changes_.cend();
247 }
248
250 template < typename STRUCT_CONSTRAINT >
251 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::modifyGraph(
252 const ArcAddition& change) {}
253
255 template < typename STRUCT_CONSTRAINT >
256 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::modifyGraph(
257 const ArcDeletion& change) {}
258
260 template < typename STRUCT_CONSTRAINT >
261 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::modifyGraph(
262 const ArcReversal& change) {}
263
265 template < typename STRUCT_CONSTRAINT >
266 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::modifyGraph(
267 const GraphChange& change) {}
268
270 template < typename STRUCT_CONSTRAINT >
271 INLINE void GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::notifyGetCompleted() {
272 if (legal_changes_.size()) legal_changes_.clear();
273 }
274
276 template < typename STRUCT_CONSTRAINT >
277 INLINE void
278 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::setMaxNbThreads(Size nb) noexcept {
279 if (nb == 0) nb = gum::getNumberOfThreads();
280 _max_threads_number_ = nb;
281 }
282
284 template < typename STRUCT_CONSTRAINT >
285 INLINE STRUCT_CONSTRAINT&
286 GraphChangesGeneratorOnSubDiGraph< STRUCT_CONSTRAINT >::constraint() const noexcept {
287 return *constraint_;
288 }
289
290 } /* namespace learning */
291
292} /* namespace gum */
293
294#endif /* DOXYGEN_SHOULD_SKIP_THIS */
GraphChangesGeneratorOnSubDiGraph(STRUCT_CONSTRAINT &constraint)
default constructor
include the inlined functions if necessary
Definition CSVParser.h:54
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
unsigned int getNumberOfThreads()
returns the max number of threads used by default when entering the next parallel region
STL namespace.