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