51#ifndef DOXYGEN_SHOULD_SKIP_THIS
60 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
63 INVARIABLE_CONSTRAINT_TYPE& invariable_constraints,
64 VARIABLE_CONSTRAINT_TYPE& variable_constraints) :
65 _score_(&score), _invariable_constraints_(&invariable_constraints),
66 _variable_constraints_(&variable_constraints) {
67 GUM_CONSTRUCTOR(GraphChangesSelector4DiGraph);
71 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
72 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
73 GraphChangesSelector4DiGraph(
74 const GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
75 VARIABLE_CONSTRAINT_TYPE >& from) :
76 _score_(from._score_), _invariable_constraints_(from._invariable_constraints_),
77 _variable_constraints_(from._variable_constraints_), _graph_(from._graph_),
78 _node_scores_(from._node_scores_), _node_parents_(from._node_parents_),
79 _sorted_changes_(from._sorted_changes_), _removed_nodes_(from._removed_nodes_),
80 _use_arc_additions_(from._use_arc_additions_),
81 _use_arc_deletions_(from._use_arc_deletions_),
82 _use_arc_reversals_(from._use_arc_reversals_),
83 _use_arc_triangle_deletions_(from._use_arc_triangle_deletions_) {
85 GUM_CONS_CPY(GraphChangesSelector4DiGraph);
89 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
90 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
91 GraphChangesSelector4DiGraph(
92 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >&&
94 _score_(from._score_), _invariable_constraints_(from._invariable_constraints_),
95 _variable_constraints_(from._variable_constraints_), _graph_(from._graph_),
96 _node_scores_(
std::move(from._node_scores_)),
97 _node_parents_(
std::move(from._node_parents_)),
98 _sorted_changes_(
std::move(from._sorted_changes_)),
99 _removed_nodes_(
std::move(from._removed_nodes_)),
100 _use_arc_additions_(from._use_arc_additions_),
101 _use_arc_deletions_(from._use_arc_deletions_),
102 _use_arc_reversals_(from._use_arc_reversals_),
103 _use_arc_triangle_deletions_(from._use_arc_triangle_deletions_) {
105 GUM_CONS_MOV(GraphChangesSelector4DiGraph);
109 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
110 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
111 VARIABLE_CONSTRAINT_TYPE >::~GraphChangesSelector4DiGraph() {
112 GUM_DESTRUCTOR(GraphChangesSelector4DiGraph);
116 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
117 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >&
118 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
119 operator=(
const GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
120 VARIABLE_CONSTRAINT_TYPE >& from) {
122 _score_ = from._score_;
123 _invariable_constraints_ = from._invariable_constraints_;
124 _variable_constraints_ = from._variable_constraints_;
125 _graph_ = from._graph_;
126 _node_scores_ = from._node_scores_;
127 _node_parents_ = from._node_parents_;
128 _sorted_changes_ = from._sorted_changes_;
129 _removed_nodes_ = from._removed_nodes_;
130 _use_arc_additions_ = from._use_arc_additions_;
131 _use_arc_deletions_ = from._use_arc_deletions_;
132 _use_arc_reversals_ = from._use_arc_reversals_;
133 _use_arc_triangle_deletions_ = from._use_arc_triangle_deletions_;
140 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
141 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >&
142 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
143 operator=(GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
144 VARIABLE_CONSTRAINT_TYPE >&& from) {
146 _score_ = from._score_;
147 _invariable_constraints_ = from._invariable_constraints_;
148 _variable_constraints_ = from._variable_constraints_;
149 _graph_ = from._graph_;
150 _node_scores_ = std::move(from._node_scores_);
151 _node_parents_ = std::move(from._node_parents_);
152 _sorted_changes_ = std::move(from._sorted_changes_);
153 _removed_nodes_ = std::move(from._removed_nodes_);
154 _use_arc_additions_ = from._use_arc_additions_;
155 _use_arc_deletions_ = from._use_arc_deletions_;
156 _use_arc_reversals_ = from._use_arc_reversals_;
157 _use_arc_triangle_deletions_ = from._use_arc_triangle_deletions_;
164 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
165 INVARIABLE_CONSTRAINT_TYPE&
166 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
167 VARIABLE_CONSTRAINT_TYPE >::invariableConstraints() {
168 return *_invariable_constraints_;
172 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
173 VARIABLE_CONSTRAINT_TYPE&
174 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
175 VARIABLE_CONSTRAINT_TYPE >::variableConstraints() {
176 return *_variable_constraints_;
180 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
181 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
182 VARIABLE_CONSTRAINT_TYPE >::setGraph(DiGraph& graph) {
186 const DatabaseTable& database = _score_->database();
187 const auto& nodeId2Columns = _score_->nodeId2Columns();
189 _removed_nodes_.clear();
190 if (nodeId2Columns.empty()) {
191 const auto nb_nodes = NodeId(database.nbVariables());
192 for (
auto node: graph) {
193 if (node >= nb_nodes) {
194 graph.eraseNode(node);
195 _removed_nodes_.insert(node);
199 for (
auto node: graph) {
200 if (!nodeId2Columns.existsFirst(node)) {
201 graph.eraseNode(node);
202 _removed_nodes_.insert(node);
209 if (nodeId2Columns.empty()) {
210 const auto nb_nodes = NodeId(database.nbVariables());
211 for (
auto i = NodeId(0); i < nb_nodes; ++i) {
212 if (!graph.existsNode(i)) { graph.addNodeWithId(i); }
215 for (
auto iter = nodeId2Columns.cbegin(); iter != nodeId2Columns.cend(); ++iter) {
216 const NodeId
id = iter.first();
217 if (!graph.existsNode(
id)) { graph.addNodeWithId(
id); }
222 _invariable_constraints_->setGraph(graph);
223 _variable_constraints_->setGraph(graph);
226 const auto nb_nodes = graph.size();
227 _node_parents_.clear();
228 _node_parents_.resize(nb_nodes);
230 const std::vector< NodeId > empty_pars;
231 for (
const auto node: graph) {
232 auto& node_parents = _node_parents_.insert(node, empty_pars).second;
233 const NodeSet& dag_parents = graph.parents(node);
234 if (!dag_parents.empty()) {
235 node_parents.resize(dag_parents.size());
237 for (
const auto par: dag_parents) {
238 node_parents[j++] = par;
245 _score_->clearCache();
246 _node_scores_.clear();
247 _node_scores_.resize(nb_nodes);
248 for (
const auto node: graph) {
249 _node_scores_.insert(node, _score_->score(node, _node_parents_[node]));
253 _sorted_changes_.clear();
254 _sorted_changes_.resize(nb_nodes * nb_nodes);
256 if (_use_arc_additions_) _initSortedChangesWithArcAdditions_(graph);
257 if (_use_arc_deletions_) _initSortedChangesWithArcDeletions_(graph);
258 if (_use_arc_reversals_) _initSortedChangesWithArcReversals_(graph);
259 if (_use_arc_triangle_deletions_) _initSortedChangesWithArcTriangleDeletions_(graph);
263 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
264 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
265 VARIABLE_CONSTRAINT_TYPE >::useArcAdditions(
bool use) {
268 if (!_use_arc_additions_) {
270 if (_graph_ !=
nullptr) _initSortedChangesWithArcAdditions_(*_graph_);
271 _use_arc_additions_ =
true;
275 if (_use_arc_additions_) {
277 for (
auto& change: _sorted_changes_) {
278 if (change.type() == GraphChangeType::ARC_ADDITION) {
279 _sorted_changes_.erase(change,
true);
282 _use_arc_additions_ =
false;
288 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
289 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
290 VARIABLE_CONSTRAINT_TYPE >::useArcDeletions(
bool use) {
293 if (!_use_arc_deletions_) {
295 if (_graph_ !=
nullptr) _initSortedChangesWithArcDeletions_(*_graph_);
296 _use_arc_deletions_ =
true;
300 if (_use_arc_deletions_) {
302 for (
auto& change: _sorted_changes_) {
303 if (change.type() == GraphChangeType::ARC_DELETION) {
304 _sorted_changes_.erase(change,
true);
307 _use_arc_deletions_ =
false;
313 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
314 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
315 VARIABLE_CONSTRAINT_TYPE >::useArcReversals(
bool use) {
318 if (!_use_arc_reversals_) {
320 if (_graph_ !=
nullptr) _initSortedChangesWithArcReversals_(*_graph_);
321 _use_arc_reversals_ =
true;
325 if (_use_arc_reversals_) {
327 for (
auto& change: _sorted_changes_) {
328 if (change.type() == GraphChangeType::ARC_REVERSAL) {
329 _sorted_changes_.erase(change,
true);
332 _use_arc_reversals_ =
false;
338 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
339 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
340 useArcTriangleDeletions(
bool use) {
343 if (!_use_arc_triangle_deletions_) {
345 if (_graph_ !=
nullptr) _initSortedChangesWithArcTriangleDeletions_(*_graph_);
346 _use_arc_triangle_deletions_ =
true;
350 if (_use_arc_triangle_deletions_) {
352 for (
auto& change: _sorted_changes_) {
353 if ((change.type() == GraphChangeType::ARC_TRIANGLE_DELETION1)
354 || (change.type() == GraphChangeType::ARC_TRIANGLE_DELETION2)) {
355 _sorted_changes_.erase(change,
true);
358 _use_arc_triangle_deletions_ =
false;
364 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
365 bool GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
366 VARIABLE_CONSTRAINT_TYPE >::arcAdditionsEnabled()
const {
367 return _use_arc_additions_;
371 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
372 bool GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
373 VARIABLE_CONSTRAINT_TYPE >::arcDeletionsEnabled()
const {
374 return _use_arc_deletions_;
378 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
379 bool GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
380 VARIABLE_CONSTRAINT_TYPE >::arcReversalsEnabled()
const {
381 return _use_arc_reversals_;
385 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
386 bool GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
387 VARIABLE_CONSTRAINT_TYPE >::arcTriangleDeletionsEnabled()
389 return _use_arc_triangle_deletions_;
393 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
394 double GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
395 _scoreAfterAddingParent_(
const NodeId node,
const NodeId new_parent) {
396 auto& parents = _node_parents_[node];
397 parents.push_back(new_parent);
398 const double new_score = _score_->score(node, parents);
404 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
405 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
406 VARIABLE_CONSTRAINT_TYPE >::finalizeGraph(DiGraph& graph) {
407 for (
const auto node: _removed_nodes_) {
408 graph.addNodeWithId(node);
413 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
414 double GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
415 _scoreAfterRemovingParent_(
const NodeId node,
const NodeId parent) {
416 auto& parents = _node_parents_[node];
417 for (
auto& par: parents) {
419 par = *(parents.rbegin());
424 const double new_score = _score_->score(node, parents);
425 parents.push_back(parent);
430 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
431 double GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
432 _scoreAfterAddingParents_(
const NodeId node,
433 const NodeId new_parent1,
434 const NodeId new_parent2) {
435 auto& parents = _node_parents_[node];
436 parents.push_back(new_parent1);
437 parents.push_back(new_parent2);
438 const double new_score = _score_->score(node, parents);
445 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
446 double GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
447 _scoreAfterRemovingParents_(
const NodeId node,
const NodeId parent1,
const NodeId parent2) {
448 auto& parents = _node_parents_[node];
449 for (
auto& par: parents) {
450 if (par == parent1) {
451 par = *(parents.rbegin());
456 for (
auto& par: parents) {
457 if (par == parent2) {
458 par = *(parents.rbegin());
463 const double new_score = _score_->score(node, parents);
464 parents.push_back(parent1);
465 parents.push_back(parent2);
470 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
471 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
472 _addArcAdditionToSortedChanges_(
const ArcAddition& change) {
474 if (!_invariable_constraints_->isAlwaysInvalid(change)) {
475 const NodeId node1 = change.node1();
476 const NodeId node2 = change.node2();
481 const double delta = !_graph_->existsArc(
Arc(node1, node2))
482 ? _scoreAfterAddingParent_(node2, node1) - _node_scores_[node2]
483 : std::numeric_limits< double >::lowest();
484 _sorted_changes_.insert(change, delta);
489 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
490 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
491 _addArcDeletionToSortedChanges_(
const ArcDeletion& change) {
493 if (!_invariable_constraints_->isAlwaysInvalid(change)) {
494 const NodeId tail = change.node1();
495 const NodeId head = change.node2();
500 const double delta = _graph_->existsArc(
Arc(tail, head))
501 ? _scoreAfterRemovingParent_(head, tail) - _node_scores_[head]
502 : std::numeric_limits< double >::lowest();
503 _sorted_changes_.insert(change, delta);
508 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
509 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
510 _addArcReversalToSortedChanges_(
const ArcReversal& change) {
512 if (!_invariable_constraints_->isAlwaysInvalid(change)) {
513 const NodeId tail = change.node1();
514 const NodeId head = change.node2();
521 = _graph_->existsArc(
Arc(tail, head)) && !_graph_->existsArc(
Arc(head, tail))
522 ? _scoreAfterRemovingParent_(head, tail) - _node_scores_[head]
523 + _scoreAfterAddingParent_(tail, head) - _node_scores_[tail]
524 : std::numeric_limits< double >::lowest();
525 _sorted_changes_.insert(change, delta);
530 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
531 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
532 _addArcTriangleDeletion1ToSortedChanges_(
const ArcTriangleDeletion1& change) {
534 if (!_invariable_constraints_->isAlwaysInvalid(change)) {
535 const auto node1 = change.node1();
536 const auto node2 = change.node2();
537 const auto node3 = change.node3();
549 = _graph_->existsArc(
Arc(node1, node2)) && _graph_->existsArc(
Arc(node2, node3))
550 && _graph_->existsArc(
Arc(node1, node3))
551 && !_graph_->existsArc(
Arc(node2, node1))
552 && !_graph_->existsArc(
Arc(node3, node1))
553 ? _scoreAfterAddingParents_(node1, node2, node3) - _node_scores_[node1]
554 + _scoreAfterRemovingParent_(node2, node1) - _node_scores_[node2]
555 + _scoreAfterRemovingParents_(node3, node1, node2) - _node_scores_[node3]
556 : std::numeric_limits< double >::lowest();
557 _sorted_changes_.insert(change, delta);
562 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
563 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
564 _addArcTriangleDeletion2ToSortedChanges_(
const ArcTriangleDeletion2& change) {
566 if (!_invariable_constraints_->isAlwaysInvalid(change)) {
567 const auto node1 = change.node1();
568 const auto node2 = change.node2();
569 const auto node3 = change.node3();
580 = _graph_->existsArc(
Arc(node1, node2)) && _graph_->existsArc(
Arc(node2, node3))
581 && _graph_->existsArc(
Arc(node1, node3))
582 && !_graph_->existsArc(
Arc(node3, node2))
583 ? _scoreAfterAddingParent_(node2, node3) - _node_scores_[node2]
584 + _scoreAfterRemovingParents_(node3, node1, node2) - _node_scores_[node3]
585 : std::numeric_limits< double >::lowest();
586 _sorted_changes_.insert(change, delta);
591 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
592 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
593 _updateArcAdditionScore_(
const NodeId tail,
const NodeId head) {
594 const auto addition = _sorted_changes_.tryGet(ArcAddition(tail, head));
595 if (addition.has_value()) {
597 const double delta = !_graph_->existsArc(tail, head)
598 ? _scoreAfterAddingParent_(head, tail) - _node_scores_[head]
599 : std::numeric_limits< double >::lowest();
600 _sorted_changes_.setPriority(addition.value(), delta,
true);
605 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
606 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
607 _updateArcDeletionScore_(
const NodeId tail,
const NodeId head) {
608 const auto deletion = _sorted_changes_.tryGet(ArcDeletion(tail, head));
609 if (deletion.has_value()) {
611 const double delta = _graph_->existsArc(tail, head)
612 ? _scoreAfterRemovingParent_(head, tail) - _node_scores_[head]
613 : std::numeric_limits< double >::lowest();
614 _sorted_changes_.setPriority(deletion.value(), delta,
true);
619 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
620 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
621 _updateArcReversalScore_(
const NodeId tail,
const NodeId head) {
622 const auto reversal = _sorted_changes_.tryGet(ArcReversal(tail, head));
623 if (reversal.has_value()) {
624 const double delta = _graph_->existsArc(tail, head) && !_graph_->existsArc(head, tail)
625 ? _scoreAfterRemovingParent_(head, tail) - _node_scores_[head]
626 + _scoreAfterAddingParent_(tail, head) - _node_scores_[tail]
627 : std::numeric_limits< double >::lowest();
628 _sorted_changes_.setPriority(reversal.value(), delta,
true);
634 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
635 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
636 _updateTriangleDeletionsScoresFromNeighborhood_(
const NodeId changed_node) {
637 const auto& children_changed_node = _graph_->children(changed_node);
638 const auto& parents_changed_node = _graph_->parents(changed_node);
639 const auto score_changed_node = _node_scores_[changed_node];
644 for (
const auto node2: children_changed_node) {
645 for (
const auto node3: children_changed_node) {
646 if (_graph_->parents(node3).contains(node2)) {
647 double delta3 = std::numeric_limits< double >::lowest();
652 = _sorted_changes_.tryGet(ArcTriangleDeletion1(changed_node, node2, node3));
653 if (change.has_value()) {
654 const bool is_valid = !_graph_->existsArc(node2, changed_node)
655 && !_graph_->existsArc(node3, changed_node);
657 delta3 = is_valid ? _scoreAfterRemovingParents_(node3, changed_node, node2)
658 - _node_scores_[node3]
664 const double delta = is_valid
665 ? _scoreAfterAddingParents_(changed_node, node3, node2)
667 + _scoreAfterRemovingParent_(node2, changed_node)
668 - _node_scores_[node2] + delta3
669 : std::numeric_limits< double >::lowest();
670 _sorted_changes_.setPriority(change.value(), delta,
true);
677 = _sorted_changes_.tryGet(ArcTriangleDeletion2(changed_node, node2, node3));
678 if (change.has_value()) {
680 = !_graph_->existsArc(changed_node, node2) && !_graph_->existsArc(node3, node2);
681 delta3 = is_valid && (delta3 == std::numeric_limits< double >::lowest())
682 ? _scoreAfterRemovingParents_(node3, changed_node, node2)
683 - _node_scores_[node3]
685 const double delta = is_valid ? _scoreAfterAddingParent_(node2, node3)
686 - _node_scores_[node2] + delta3
687 : std::numeric_limits< double >::lowest();
688 _sorted_changes_.setPriority(change.value(), delta,
true);
696 for (
const auto node1: parents_changed_node) {
697 for (
const auto node3: children_changed_node) {
698 if (_graph_->parents(node3).contains(node1)) {
699 double delta3 = std::numeric_limits< double >::lowest();
704 = _sorted_changes_.tryGet(ArcTriangleDeletion1(node1, changed_node, node3));
705 if (change.has_value()) {
707 = !_graph_->existsArc(changed_node, node1) && !_graph_->existsArc(node3, node1);
709 delta3 = is_valid ? _scoreAfterRemovingParents_(node3, node1, changed_node)
710 - _node_scores_[node3]
712 const double delta = is_valid
713 ? _scoreAfterAddingParents_(node1, changed_node, node3)
714 - _node_scores_[node1]
715 + _scoreAfterRemovingParent_(changed_node, node1)
716 - score_changed_node + delta3
717 : std::numeric_limits< double >::lowest();
718 _sorted_changes_.setPriority(change.value(), delta,
true);
725 = _sorted_changes_.tryGet(ArcTriangleDeletion2(node1, changed_node, node3));
726 if (change.has_value()) {
727 const bool is_valid = !_graph_->existsArc(node1, changed_node)
728 && !_graph_->existsArc(node3, changed_node);
729 delta3 = is_valid && (delta3 == std::numeric_limits< double >::lowest())
730 ? _scoreAfterRemovingParents_(node3, node1, changed_node)
731 - _node_scores_[node3]
733 const double delta = is_valid ? _scoreAfterAddingParent_(changed_node, node3)
734 - score_changed_node + delta3
735 : std::numeric_limits< double >::lowest();
736 _sorted_changes_.setPriority(change.value(), delta,
true);
744 for (
const auto node1: parents_changed_node) {
745 for (
const auto node2: parents_changed_node) {
746 if (_graph_->parents(node2).contains(node1)) {
747 double delta3 = std::numeric_limits< double >::lowest();
752 = _sorted_changes_.tryGet(ArcTriangleDeletion1(node1, node2, changed_node));
753 if (change.has_value()) {
755 = !_graph_->existsArc(node2, node1) && !_graph_->existsArc(changed_node, node1);
757 delta3 = is_valid ? _scoreAfterRemovingParents_(changed_node, node1, node2)
760 const double delta = is_valid
761 ? _scoreAfterAddingParents_(node1, changed_node, node2)
762 - _node_scores_[node1]
763 + _scoreAfterRemovingParent_(node2, node1)
764 - _node_scores_[node2] + delta3
765 : std::numeric_limits< double >::lowest();
766 _sorted_changes_.setPriority(change.value(), delta,
true);
773 = _sorted_changes_.tryGet(ArcTriangleDeletion2(node1, node2, changed_node));
774 if (change.has_value()) {
776 = !_graph_->existsArc(node1, node2) && !_graph_->existsArc(changed_node, node2);
777 delta3 = is_valid && (delta3 == std::numeric_limits< double >::lowest())
778 ? _scoreAfterRemovingParents_(changed_node, node1, node2)
781 const double delta = is_valid ? _scoreAfterAddingParent_(node2, changed_node)
782 - _node_scores_[node2] + delta3
783 : std::numeric_limits< double >::lowest();
784 _sorted_changes_.setPriority(change.value(), delta,
true);
793 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
794 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
795 _initSortedChangesWithArcAdditions_(
const DiGraph& graph) {
798 for (
auto iter1 = graph.begin(); iter1 != graph.end(); ++iter1) {
799 const NodeId node1 = *iter1;
804 for (++iter2; iter2 != graph.end(); ++iter2) {
805 const NodeId node2 = *iter2;
806 if (!graph.existsArc(node1, node2)) {
807 _addArcAdditionToSortedChanges_(ArcAddition(node1, node2));
809 if (!graph.existsArc(node2, node1)) {
810 _addArcAdditionToSortedChanges_(ArcAddition(node2, node1));
817 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
818 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
819 _initSortedChangesWithArcDeletions_(
const DiGraph& graph) {
821 for (
const auto& arc: graph.arcs()) {
822 _addArcDeletionToSortedChanges_(ArcDeletion(arc.tail(), arc.head()));
827 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
828 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
829 _initSortedChangesWithArcReversals_(
const DiGraph& graph) {
831 for (
const auto& arc: graph.arcs()) {
832 _addArcReversalToSortedChanges_(ArcReversal(arc.tail(), arc.head()));
837 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
838 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
839 _initSortedChangesWithArcTriangleDeletions_(
const DiGraph& graph) {
842 for (
const auto node1: graph) {
843 const auto& children1 = graph.children(node1);
844 for (
const auto node2: children1) {
845 const auto& children2 = graph.children(node2);
846 for (
const auto node3: children2) {
847 if (children1.exists(node3)) {
852 _addArcTriangleDeletion1ToSortedChanges_(ArcTriangleDeletion1(node1, node2, node3));
853 _addArcTriangleDeletion2ToSortedChanges_(ArcTriangleDeletion2(node1, node2, node3));
861 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
862 const GraphChange& GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
863 VARIABLE_CONSTRAINT_TYPE >::bestChange() {
864 for (
const auto& _sorted_change: _sorted_changes_) {
865 if (_variable_constraints_->checkModification(_sorted_change)) {
return _sorted_change; }
872 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
873 double GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE,
874 VARIABLE_CONSTRAINT_TYPE >::bestDeltaScore() {
875 for (
auto iter = _sorted_changes_.begin(); iter != _sorted_changes_.end(); ++iter) {
876 if (_variable_constraints_->checkModification(*iter)) {
return iter.priority(); }
883 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
884 double GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
885 deltaScore(
const GraphChange& change,
const bool internal_change)
const {
887 return _sorted_changes_.priority(change, internal_change);
889 GUM_ERROR(
NotFound,
"Change " << change.toString() <<
" will never be applicable")
894 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
896 GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::score(
897 const NodeId node)
const {
898 return _node_scores_[node];
902 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
903 bool GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
904 isChangeValid(
const GraphChange& change)
const {
905 return !_invariable_constraints_->isAlwaysInvalid(change)
906 && _variable_constraints_->checkModification(change);
910 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
911 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
912 _applyArcAddition_(
const ArcAddition& change,
bool update_contraints) {
914 const auto tail = change.node1();
915 const auto head = change.node2();
916 const auto delta_score = _sorted_changes_.priority(change);
917 _node_scores_[head] += delta_score;
920 _graph_->addArc(tail, head);
921 _node_parents_[head].push_back(tail);
922 const auto& children_head = _graph_->children(head);
923 const auto& parents_head = _graph_->parents(head);
926 if (update_contraints) {
927 _invariable_constraints_->modifyGraph(change);
928 _variable_constraints_->modifyGraph(change);
950 _sorted_changes_.erase(change,
true);
953 if (_use_arc_additions_) {
954 for (
const auto node: *_graph_) {
957 _updateArcAdditionScore_(node, head);
962 if (_use_arc_deletions_) {
964 for (
const auto node: parents_head) {
969 _updateArcDeletionScore_(node, head);
973 const ArcDeletion deletion(tail, head);
974 if (!_invariable_constraints_->isAlwaysInvalid(deletion)) {
975 _sorted_changes_.insert(deletion, -delta_score);
980 if (_use_arc_reversals_) {
982 for (
const auto node: parents_head) {
986 _updateArcReversalScore_(node, head);
990 for (
const auto node: children_head) {
991 _updateArcReversalScore_(head, node);
996 _addArcReversalToSortedChanges_(ArcReversal(tail, head));
1000 if (_use_arc_triangle_deletions_) {
1002 _updateTriangleDeletionsScoresFromNeighborhood_(head);
1009 const auto& children_tail = _graph_->children(tail);
1010 const auto& parents_tail = _graph_->parents(tail);
1011 for (
const auto node: parents_head) {
1012 if (children_tail.contains(node)) {
1013 _addArcTriangleDeletion1ToSortedChanges_(ArcTriangleDeletion1(tail, node, head));
1014 _addArcTriangleDeletion2ToSortedChanges_(ArcTriangleDeletion2(tail, node, head));
1015 }
else if (parents_tail.contains(node)) {
1016 _addArcTriangleDeletion1ToSortedChanges_(ArcTriangleDeletion1(node, tail, head));
1017 _addArcTriangleDeletion2ToSortedChanges_(ArcTriangleDeletion2(node, tail, head));
1022 for (
const auto node: children_tail) {
1023 if (children_head.exists(node)) {
1024 _addArcTriangleDeletion1ToSortedChanges_(ArcTriangleDeletion1(tail, head, node));
1025 _addArcTriangleDeletion2ToSortedChanges_(ArcTriangleDeletion2(tail, head, node));
1032 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
1033 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
1034 _applyArcDeletion_(
const ArcDeletion& change,
bool update_contraints) {
1036 const auto tail = change.node1();
1037 const auto head = change.node2();
1038 const auto delta_score = _sorted_changes_.priority(change);
1039 _node_scores_[head] += delta_score;
1042 _graph_->eraseArc(
Arc(tail, head));
1043 auto& parents = _node_parents_[head];
1044 for (
auto& par: parents) {
1046 par = *(parents.rbegin());
1051 const auto& children_head = _graph_->children(head);
1052 const auto& parents_head = _graph_->parents(head);
1055 if (update_contraints) {
1056 _invariable_constraints_->modifyGraph(change);
1057 _variable_constraints_->modifyGraph(change);
1078 _sorted_changes_.erase(change);
1081 if (_use_arc_additions_) {
1083 for (
const auto node: *_graph_) {
1087 _updateArcAdditionScore_(node, head);
1091 const ArcAddition addition(tail, head);
1092 if (!_invariable_constraints_->isAlwaysInvalid(addition)) {
1093 _sorted_changes_.insert(addition, -delta_score);
1098 if (_use_arc_deletions_) {
1099 for (
const auto node: parents_head) {
1102 _updateArcDeletionScore_(node, head);
1107 if (_use_arc_reversals_) {
1108 _sorted_changes_.erase(ArcReversal(tail, head));
1111 for (
const auto node: parents_head) {
1114 _updateArcReversalScore_(node, head);
1118 for (
const auto node: children_head) {
1119 _updateArcReversalScore_(head, node);
1124 if (_use_arc_triangle_deletions_) {
1130 const auto& children_tail = _graph_->children(tail);
1131 const auto& parents_tail = _graph_->parents(tail);
1132 for (
const auto node: parents_head) {
1133 if (children_tail.contains(node)) {
1134 _sorted_changes_.erase(ArcTriangleDeletion1(tail, node, head));
1135 _sorted_changes_.erase(ArcTriangleDeletion2(tail, node, head));
1137 if (parents_tail.contains(node)) {
1138 _sorted_changes_.erase(ArcTriangleDeletion1(node, tail, head));
1139 _sorted_changes_.erase(ArcTriangleDeletion2(node, tail, head));
1144 for (
const auto node: children_tail) {
1145 if (children_head.contains(node)) {
1146 _sorted_changes_.erase(ArcTriangleDeletion1(tail, head, node));
1147 _sorted_changes_.erase(ArcTriangleDeletion2(tail, head, node));
1152 _updateTriangleDeletionsScoresFromNeighborhood_(head);
1157 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
1158 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
1159 _applyArcReversal_(
const ArcReversal& change,
bool update_contraints) {
1161 const auto tail = change.node1();
1162 const auto head = change.node2();
1163 _graph_->eraseArc(
Arc(tail, head));
1164 _graph_->addArc(head, tail);
1165 const auto& children_head = _graph_->children(head);
1166 const auto& parents_head = _graph_->parents(head);
1167 const auto& children_tail = _graph_->children(tail);
1168 const auto& parents_tail = _graph_->parents(tail);
1170 auto& node_parents_tail = _node_parents_[tail];
1171 node_parents_tail.push_back(head);
1172 auto& node_parents_head = _node_parents_[head];
1173 for (
auto& par: node_parents_head) {
1175 par = *(node_parents_head.rbegin());
1176 node_parents_head.pop_back();
1182 const auto overall_delta_score = _sorted_changes_.priority(change);
1183 const auto delta_score_tail = _score_->score(tail, node_parents_tail) - _node_scores_[tail];
1185 _node_scores_[head] += overall_delta_score - delta_score_tail;
1186 _node_scores_[tail] += delta_score_tail;
1189 if (update_contraints) {
1190 _invariable_constraints_->modifyGraph(change);
1191 _variable_constraints_->modifyGraph(change);
1221 _sorted_changes_.erase(change);
1224 if (_use_arc_additions_) {
1226 _sorted_changes_.erase(ArcAddition(head, tail));
1229 for (
const auto node: *_graph_) {
1230 _updateArcAdditionScore_(node, head);
1231 _updateArcAdditionScore_(node, tail);
1235 _addArcAdditionToSortedChanges_(ArcAddition(tail, head));
1239 if (_use_arc_deletions_) {
1241 _sorted_changes_.erase(ArcDeletion(tail, head));
1244 for (
const auto node: parents_head) {
1245 _updateArcDeletionScore_(node, head);
1249 for (
const auto node: parents_tail) {
1250 _updateArcDeletionScore_(node, tail);
1254 const ArcDeletion deletion(head, tail);
1255 if (!_invariable_constraints_->isAlwaysInvalid(deletion)) {
1256 _sorted_changes_.insert(deletion, -delta_score_tail);
1261 if (_use_arc_reversals_) {
1263 for (
const auto node: parents_head) {
1264 _updateArcReversalScore_(node, head);
1268 for (
const auto node: children_head) {
1269 _updateArcReversalScore_(head, node);
1273 for (
const auto node: parents_tail) {
1274 _updateArcReversalScore_(node, tail);
1278 for (
const auto node: children_tail) {
1279 _updateArcReversalScore_(tail, node);
1283 const ArcReversal reversal(head, tail);
1284 if (!_invariable_constraints_->isAlwaysInvalid(reversal)) {
1285 _sorted_changes_.insert(reversal, -overall_delta_score);
1290 if (_use_arc_triangle_deletions_) {
1294 for (
const auto node: parents_head) {
1295 if (children_tail.contains(node)) {
1296 _sorted_changes_.erase(ArcTriangleDeletion1(tail, node, head));
1297 _sorted_changes_.erase(ArcTriangleDeletion2(tail, node, head));
1299 if (parents_tail.exists(node)) {
1300 _sorted_changes_.erase(ArcTriangleDeletion1(node, tail, head));
1301 _sorted_changes_.erase(ArcTriangleDeletion2(node, tail, head));
1305 for (
const auto node: children_tail) {
1306 if (children_head.contains(node)) {
1307 _sorted_changes_.erase(ArcTriangleDeletion1(tail, head, node));
1308 _sorted_changes_.erase(ArcTriangleDeletion2(tail, head, node));
1313 _updateTriangleDeletionsScoresFromNeighborhood_(head);
1314 _updateTriangleDeletionsScoresFromNeighborhood_(tail);
1319 for (
const auto node: parents_tail) {
1320 if (children_head.contains(node)) {
1321 _addArcTriangleDeletion1ToSortedChanges_(ArcTriangleDeletion1(head, node, tail));
1322 _addArcTriangleDeletion2ToSortedChanges_(ArcTriangleDeletion2(head, node, tail));
1324 if (parents_head.exists(node)) {
1325 _addArcTriangleDeletion1ToSortedChanges_(ArcTriangleDeletion1(node, head, tail));
1326 _addArcTriangleDeletion2ToSortedChanges_(ArcTriangleDeletion2(node, head, tail));
1331 for (
const auto node: children_head) {
1332 if (children_tail.contains(node)) {
1333 _addArcTriangleDeletion1ToSortedChanges_(ArcTriangleDeletion1(head, tail, node));
1334 _addArcTriangleDeletion2ToSortedChanges_(ArcTriangleDeletion2(head, tail, node));
1341 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
1342 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
1343 _applyArcTriangleDeletion1_(
const ArcTriangleDeletion1& xchange,
bool update_contraints) {
1346 ArcTriangleDeletion1 change(xchange);
1348 const auto node1 = change.node1();
1349 const auto node2 = change.node2();
1350 const auto node3 = change.node3();
1353 _sorted_changes_.erase(xchange);
1357 _applyArcDeletion_(ArcDeletion(node2, node3),
false);
1360 _applyArcReversal_(ArcReversal(node1, node2),
false);
1363 _applyArcReversal_(ArcReversal(node1, node3),
false);
1365 if (update_contraints) {
1366 _invariable_constraints_->modifyGraph(change);
1367 _variable_constraints_->modifyGraph(change);
1372 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
1373 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
1374 _applyArcTriangleDeletion2_(
const ArcTriangleDeletion2& xchange,
bool update_contraints) {
1377 ArcTriangleDeletion2 change(xchange);
1379 const auto node1 = change.node1();
1380 const auto node2 = change.node2();
1381 const auto node3 = change.node3();
1384 _sorted_changes_.erase(change);
1388 _applyArcDeletion_(ArcDeletion(node1, node3),
false);
1391 _applyArcReversal_(ArcReversal(node2, node3),
false);
1393 if (update_contraints) {
1394 _invariable_constraints_->modifyGraph(change);
1395 _variable_constraints_->modifyGraph(change);
1400 template <
typename INVARIABLE_CONSTRAINT_TYPE,
typename VARIABLE_CONSTRAINT_TYPE >
1401 void GraphChangesSelector4DiGraph< INVARIABLE_CONSTRAINT_TYPE, VARIABLE_CONSTRAINT_TYPE >::
1402 applyChange(
const GraphChange& change) {
1403 switch (change.type()) {
1404 case GraphChangeType::ARC_ADDITION :
1405 _applyArcAddition_(
static_cast< const ArcAddition&
>(change),
true);
1408 case GraphChangeType::ARC_DELETION :
1409 _applyArcDeletion_(
static_cast< const ArcDeletion&
>(change),
true);
1412 case GraphChangeType::ARC_REVERSAL :
1413 _applyArcReversal_(
static_cast< const ArcReversal&
>(change),
true);
1416 case GraphChangeType::ARC_TRIANGLE_DELETION1 :
1417 _applyArcTriangleDeletion1_(
static_cast< const ArcTriangleDeletion1&
>(change),
true);
1420 case GraphChangeType::ARC_TRIANGLE_DELETION2 :
1421 _applyArcTriangleDeletion2_(
static_cast< const ArcTriangleDeletion2&
>(change),
true);
1426 "Method applyChange of GraphChangesSelector4DiGraph "
1427 <<
"does not handle yet graph change of type " << change.typeAsString());
Exception : the element we looked for cannot be found.
Exception : there is something wrong with an implementation.
GraphChangesSelector4DiGraph(Score &score, INVARIABLE_CONSTRAINT_TYPE &invariable_constraints, VARIABLE_CONSTRAINT_TYPE &variable_constraints)
default constructor
The base class for all the scores used for learning (BIC, BDeu, etc).
#define GUM_ERROR(type, msg)
The mecanism to compute the next available graph changes for directed structure learning search algor...
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
include the inlined functions if necessary
gum is the global namespace for all aGrUM entities