63#ifndef DOXYGEN_SHOULD_SKIP_THIS
71 Triangulation(domsizes), _triangulation_(triang_algo.newFactory()) {
72 GUM_CONSTRUCTOR(IncrementalTriangulation);
75 _triangulation_->clear();
80 for (
const auto node: *theGraph)
81 addNode(node, (*domsizes)[node]);
85 for (
const auto& edge: theGraph->edges())
86 addEdge(edge.first(), edge.second());
90 IncrementalTriangulation::IncrementalTriangulation(
91 const UnconstrainedTriangulation& triang_algo) : _triangulation_(triang_algo.newFactory()) {
92 GUM_CONSTRUCTOR(IncrementalTriangulation);
95 _triangulation_->clear();
99 IncrementalTriangulation::IncrementalTriangulation(
const IncrementalTriangulation& from) :
100 Triangulation(from), _graph_(from._graph_), _junction_tree_(from._junction_tree_),
101 _T_mpd_(from._T_mpd_), _mps_of_node_(from._mps_of_node_),
102 _cliques_of_mps_(from._cliques_of_mps_), _mps_of_clique_(from._mps_of_clique_),
103 _mps_affected_(from._mps_affected_), _triangulation_(from._triangulation_->newFactory()),
104 _require_update_(from._require_update_),
105 _require_elimination_order_(from._require_elimination_order_),
106 _elimination_order_(from._elimination_order_),
107 _reverse_elimination_order_(from._reverse_elimination_order_),
108 _require_created_JT_cliques_(from._require_created_JT_cliques_),
109 _created_JT_cliques_(from._created_JT_cliques_) {
110 GUM_CONS_CPY(IncrementalTriangulation);
112 _domain_sizes_ = from._domain_sizes_;
116 IncrementalTriangulation::~IncrementalTriangulation() {
117 GUM_DESTRUCTOR(IncrementalTriangulation);
120 delete _triangulation_;
124 IncrementalTriangulation* IncrementalTriangulation::newFactory()
const {
125 return new IncrementalTriangulation(*_triangulation_);
129 IncrementalTriangulation* IncrementalTriangulation::copyFactory()
const {
130 return new IncrementalTriangulation(*
this);
134 IncrementalTriangulation&
135 IncrementalTriangulation::operator=(
const IncrementalTriangulation& from) {
138 GUM_OP_CPY(IncrementalTriangulation)
141 _graph_ = from._graph_;
142 _domain_sizes_ = from._domain_sizes_;
143 _junction_tree_ = from._junction_tree_;
144 _T_mpd_ = from._T_mpd_;
145 _mps_of_node_ = from._mps_of_node_;
146 _cliques_of_mps_ = from._cliques_of_mps_;
147 _mps_of_clique_ = from._mps_of_clique_;
148 _mps_affected_ = from._mps_affected_;
149 _require_update_ = from._require_update_;
150 _require_elimination_order_ = from._require_elimination_order_;
151 _elimination_order_ = from._elimination_order_;
152 _reverse_elimination_order_ = from._reverse_elimination_order_;
153 _require_created_JT_cliques_ = from._require_created_JT_cliques_;
154 _created_JT_cliques_ = from._created_JT_cliques_;
158 delete _triangulation_;
159 _triangulation_ = from._triangulation_->newFactory();
166 void IncrementalTriangulation::addNode(
const NodeId node, Size modal) {
168 if (_graph_.existsNode(node))
return;
171 _graph_.addNodeWithId(node);
172 _domain_sizes_.insert(node, modal);
176 clique_nodes.insert(node);
178 NodeId MPS = _T_mpd_.addNode(clique_nodes);
179 NodeId new_clique = _junction_tree_.addNode(clique_nodes);
182 List< NodeId >& list_of_mps = _mps_of_node_.insert(node, List< NodeId >()).second;
183 list_of_mps.insert(MPS);
186 std::vector< NodeId >& cliquesMPS
187 = _cliques_of_mps_.insert(MPS, std::vector< NodeId >()).second;
189 cliquesMPS.push_back(new_clique);
190 _mps_of_clique_.insert(new_clique, MPS);
193 _mps_affected_.insert(MPS,
false);
196 _elimination_order_.push_back(node);
198 if (!_reverse_elimination_order_.exists(node))
199 _reverse_elimination_order_.insert(node, Size(_elimination_order_.size()));
201 if (!_created_JT_cliques_.exists(node)) _created_JT_cliques_.insert(node, new_clique);
206 void IncrementalTriangulation::_markAffectedMPSsByRemoveLink_(
const NodeId My,
210 _mps_affected_[My] =
true;
213 for (
const auto nei: _T_mpd_.neighbours(My))
215 const NodeSet& Syk = _T_mpd_.separator(Edge(nei, My));
217 if (Syk.contains(edge.first()) && Syk.contains(edge.second()))
218 _markAffectedMPSsByRemoveLink_(nei, My, edge);
224 void IncrementalTriangulation::eraseEdge(
const Edge& edge) {
226 if (!_graph_.existsEdge(edge))
return;
229 const NodeId X = edge.first();
230 const NodeId Y = edge.second();
232 const List< NodeId >& mps1 = _mps_of_node_[X];
233 const List< NodeId >& mps2 = _mps_of_node_[Y];
237 if (mps1.size() <= mps2.size()) {
238 for (
const auto node: mps1)
239 if (_T_mpd_.clique(node).contains(Y)) {
244 for (
const auto node: mps2)
245 if (_T_mpd_.clique(node).contains(X)) {
252 _markAffectedMPSsByRemoveLink_(Mx, Mx, edge);
254 _require_update_ =
true;
256 _require_elimination_order_ =
true;
258 _require_created_JT_cliques_ =
true;
261 _graph_.eraseEdge(edge);
267 void IncrementalTriangulation::eraseNode(
const NodeId X) {
269 if (!_graph_.existsNode(X))
return;
273 const NodeSet& neighbours = _graph_.neighbours(X);
275 for (
auto neighbour_edge = neighbours.beginSafe();
276 neighbour_edge != neighbours.endSafe();
278 eraseEdge(Edge(*neighbour_edge, X));
282 auto& MPS_of_X = _mps_of_node_[X];
285 for (
const auto node: MPS_of_X) {
286 _T_mpd_.eraseFromClique(node, X);
290 auto& neighbours = _T_mpd_.neighbours(node);
292 for (
auto it_neighbour = neighbours.beginSafe(); it_neighbour != neighbours.endSafe();
294 Edge neigh(*it_neighbour, node);
296 if (_T_mpd_.separator(neigh).size() == 0) _T_mpd_.eraseEdge(neigh);
301 for (
const auto clique: MPS_of_X) {
302 const std::vector< NodeId >& cliques_of_X = _cliques_of_mps_[clique];
304 for (
unsigned int i = 0; i < cliques_of_X.size(); ++i) {
305 _junction_tree_.eraseFromClique(cliques_of_X[i], X);
310 auto& neighbours = _junction_tree_.neighbours(cliques_of_X[i]);
312 for (
auto it_neighbour = neighbours.beginSafe(); it_neighbour != neighbours.endSafe();
314 Edge neigh(*it_neighbour, cliques_of_X[i]);
316 if (_junction_tree_.separator(neigh).size() == 0) {
319 bool hasCommonEdge =
false;
321 for (
const auto node1: _junction_tree_.clique(neigh.first()))
322 for (
const auto node2: _junction_tree_.clique(neigh.second()))
323 if (_graph_.existsEdge(node1, node2)) {
324 hasCommonEdge =
true;
328 if (!hasCommonEdge) { _junction_tree_.eraseEdge(neigh); }
336 if ((MPS_of_X.size() == 1) && (_T_mpd_.clique(MPS_of_X[0]).size() == 0)) {
337 _junction_tree_.eraseNode(_cliques_of_mps_[MPS_of_X[0]][0]);
338 _T_mpd_.eraseNode(MPS_of_X[0]);
339 _mps_of_clique_.erase(_cliques_of_mps_[MPS_of_X[0]][0]);
340 _cliques_of_mps_.erase(MPS_of_X[0]);
341 _mps_affected_.erase(MPS_of_X[0]);
344 _mps_of_node_.erase(X);
348 if (!_require_update_) {
349 for (Idx i = _reverse_elimination_order_[X] + 1; i < _reverse_elimination_order_.size(); ++i)
350 _elimination_order_[i - 1] = _elimination_order_[i];
352 _elimination_order_.pop_back();
354 _reverse_elimination_order_.erase(X);
356 _created_JT_cliques_.erase(X);
360 _graph_.eraseNode(X);
362 _domain_sizes_.erase(X);
367 int IncrementalTriangulation::_markAffectedMPSsByAddLink_(
const NodeId Mx,
376 const NodeSet& cliqueMX = _T_mpd_.clique(Mx);
378 if (cliqueMX.contains(Y)) {
379 _mps_affected_[Mx] =
true;
381 if (cliqueMX.contains(X))
return 2;
387 for (
const auto other_node: _T_mpd_.neighbours(Mx))
388 if (other_node != Mz) {
389 int neighbourStatus = _markAffectedMPSsByAddLink_(other_node, Mx, X, Y);
391 if (neighbourStatus == 2)
return 2;
392 else if (neighbourStatus == 1) {
393 _mps_affected_[Mx] =
true;
395 if (cliqueMX.contains(X))
return 2;
407 void IncrementalTriangulation::addEdge(
const NodeId X,
const NodeId Y) {
409 if ((X == Y) || !_graph_.existsNode(X) || !_graph_.existsNode(Y)
410 || _graph_.existsEdge(Edge(X, Y)))
414 _graph_.addEdge(X, Y);
417 NodeId& mps_X = _mps_of_node_[X][0];
419 int found = _markAffectedMPSsByAddLink_(mps_X, mps_X, X, Y);
424 NodeId& mps_Y = _mps_of_node_[Y][0];
429 const std::vector< NodeId >& cliques_X = _cliques_of_mps_[mps_X];
430 const std::vector< NodeId >& cliques_Y = _cliques_of_mps_[mps_Y];
431 NodeId c_X = 0, c_Y = 0;
433 for (
unsigned int i = 0; i < cliques_X.size(); ++i) {
434 if (_junction_tree_.clique(cliques_X[i]).contains(X)) {
440 for (
unsigned int i = 0; i < cliques_Y.size(); ++i) {
441 if (_junction_tree_.clique(cliques_Y[i]).contains(Y)) {
454 NodeId newNode = _junction_tree_.addNode(nodes);
456 _junction_tree_.addEdge(newNode, c_X);
457 _junction_tree_.addEdge(newNode, c_Y);
459 NodeId newMPS = _T_mpd_.addNode(nodes);
461 _T_mpd_.addEdge(newMPS, mps_X);
462 _T_mpd_.addEdge(newMPS, mps_Y);
468 if (_T_mpd_.clique(mps_X).size() == 1) {
469 _junction_tree_.eraseNode(c_X);
470 _T_mpd_.eraseNode(mps_X);
471 _mps_affected_.erase(mps_X);
472 _mps_of_clique_.erase(c_X);
473 _cliques_of_mps_.erase(mps_X);
474 _created_JT_cliques_[X] = newNode;
476 }
else _mps_of_node_[X].insert(newMPS);
479 if (_T_mpd_.clique(mps_Y).size() == 1) {
480 _junction_tree_.eraseNode(c_Y);
481 _T_mpd_.eraseNode(mps_Y);
482 _mps_affected_.erase(mps_Y);
483 _mps_of_clique_.erase(c_Y);
484 _cliques_of_mps_.erase(mps_Y);
485 _created_JT_cliques_[Y] = newNode;
487 }
else _mps_of_node_[Y].insert(newMPS);
489 std::vector< NodeId >& cl = _cliques_of_mps_.insert(newMPS, std::vector< NodeId >()).second;
491 cl.push_back(newNode);
493 _mps_of_clique_.insert(newNode, newMPS);
495 _mps_affected_.insert(newMPS,
false);
497 _require_update_ =
true;
498 _require_created_JT_cliques_ =
true;
502 _require_elimination_order_ =
true;
507 bool IncrementalTriangulation::_check_() {
509 updateTriangulation();
515 NodeProperty< bool > nodesProp = _graph_.nodesPropertyFromVal<
bool >(
false);
517 for (
const auto cliq: _junction_tree_.nodes())
518 for (
const auto node: _junction_tree_.clique(cliq))
519 nodesProp[node] =
true;
521 for (
const auto& elt: nodesProp)
523 std::cerr <<
"check nodes" << std::endl
524 << _graph_ << std::endl
525 << _junction_tree_ << std::endl;
529 if (!OK)
return false;
534 std::pair< NodeId, NodeId > thePair;
535 EdgeProperty< bool > edgesProp = _graph_.edgesProperty(
false);
537 for (
const auto cliq: _junction_tree_.nodes()) {
538 const NodeSet& clique = _junction_tree_.clique(cliq);
540 for (
auto iter2 = clique.begin(); iter2 != clique.end(); ++iter2) {
543 for (++iter3; iter3 != clique.end(); ++iter3) {
544 thePair.first = std::min(*iter2, *iter3);
545 thePair.second = std::max(*iter2, *iter3);
547 if (_graph_.existsEdge(thePair.first, thePair.second))
548 edgesProp[Edge(thePair.first, thePair.second)] =
true;
553 for (
const auto& elt: edgesProp)
555 std::cerr <<
"check edges" << std::endl
556 << _graph_ << std::endl
557 << _junction_tree_ << std::endl;
561 if (!OK)
return false;
566 NodeProperty< bool > nodesProp = _graph_.nodesPropertyFromVal<
bool >(
false);
568 for (
const auto cliq: _T_mpd_.nodes())
569 for (
const auto node: _T_mpd_.clique(cliq))
570 nodesProp[node] =
true;
572 for (
const auto& elt: nodesProp)
574 std::cerr <<
"check nodes" << std::endl << _graph_ << std::endl << _T_mpd_ << std::endl;
578 if (!OK)
return false;
583 std::pair< NodeId, NodeId > thePair;
584 EdgeProperty< bool > edgesProp = _graph_.edgesProperty(
false);
586 for (
const auto cliq: _T_mpd_.nodes()) {
587 const NodeSet& clique = _T_mpd_.clique(cliq);
589 for (
auto iter2 = clique.begin(); iter2 != clique.end(); ++iter2) {
592 for (++iter3; iter3 != clique.end(); ++iter3) {
593 thePair.first = std::min(*iter2, *iter3);
594 thePair.second = std::max(*iter2, *iter3);
596 if (_graph_.existsEdge(thePair.first, thePair.second))
597 edgesProp[Edge(thePair.first, thePair.second)] =
true;
602 for (
const auto& elt: edgesProp)
604 std::cerr <<
"check edges" << std::endl << _graph_ << std::endl << _T_mpd_ << std::endl;
608 if (!OK)
return false;
613 NodeProperty< NodeProperty< bool > > chk;
615 for (
const auto node: _graph_.nodes())
616 chk.insert(node, HashTable< NodeId, bool >());
618 for (
const auto cliq: _T_mpd_.nodes())
619 for (
auto node: _T_mpd_.clique(cliq))
620 chk[node].insert(cliq,
false);
622 for (
const auto& elt: _mps_of_node_) {
623 HashTable< NodeId, bool >& hash = chk[elt.first];
625 for (
const auto cell: elt.second) {
626 if (!hash.exists(cell)) {
627 std::cerr <<
"check mps of nodes" << std::endl
628 << _T_mpd_ << std::endl
629 << _mps_of_node_ << std::endl;
637 for (
const auto& elt: chk)
638 for (
const auto& elt2: elt.second)
640 std::cerr <<
"check mps of nodes2" << std::endl
641 << _T_mpd_ << std::endl
642 << _mps_of_node_ << std::endl;
646 if (!OK)
return false;
651 if (!_junction_tree_.isJoinTree()) {
652 std::cerr <<
"check join tree _junction_tree_" << std::endl
653 << _junction_tree_ << std::endl;
657 if (!_T_mpd_.isJoinTree()) {
658 std::cerr <<
"check join tree _T_mpd_" << std::endl << _T_mpd_ << std::endl;
667 if (_elimination_order_.size() != _graph_.size()) {
668 std::cerr <<
"check elimination order" << std::endl << _elimination_order_ << std::endl;
674 for (
const auto node: _graph_.nodes()) {
675 if (nodes.exists(node)) {
676 std::cerr <<
"check elimination order" << std::endl << _elimination_order_ << std::endl;
678 }
else nodes.insert(node);
681 if (nodes.size() != _graph_.size()) {
682 std::cerr <<
"check elimination order" << std::endl << _elimination_order_ << std::endl;
686 if (_reverse_elimination_order_.size() != _graph_.size()) {
687 std::cerr <<
"check reverse elimination order" << std::endl
688 << _reverse_elimination_order_ << std::endl;
692 for (
const auto node: _graph_.nodes()) {
693 if (!_reverse_elimination_order_.exists(node)) {
694 std::cerr <<
"check reverse elimination order" << std::endl
695 << _reverse_elimination_order_ << std::endl;
703 createdJunctionTreeCliques();
705 if (_created_JT_cliques_.size() != _graph_.size()) {
706 std::cerr <<
"check creating JT cliques" << std::endl << _created_JT_cliques_ << std::endl;
710 for (
const auto node: _graph_.nodes()) {
711 if (!_created_JT_cliques_.exists(node)
712 || !_junction_tree_.existsNode(_created_JT_cliques_[node])) {
713 std::cerr <<
"check created JT cliques" << std::endl << _created_JT_cliques_ << std::endl;
724 void IncrementalTriangulation::_setUpConnectedTriangulation_(
728 std::vector< Edge >& notAffectedneighbourCliques,
729 HashTable< NodeId, bool >& cliques_affected) {
731 cliques_affected[Mx] =
false;
734 for (
const auto node: _junction_tree_.clique(Mx))
735 if (!theGraph.exists(node)) theGraph.addNodeWithId(node);
738 for (
const auto othernode: _junction_tree_.neighbours(Mx))
739 if (othernode != Mfrom) {
740 if (cliques_affected.exists(othernode)) {
741 _setUpConnectedTriangulation_(othernode,
744 notAffectedneighbourCliques,
749 notAffectedneighbourCliques.push_back(Edge(othernode, Mx));
756 void IncrementalTriangulation::_updateJunctionTree_(NodeProperty< bool >& all_cliques_affected,
757 NodeSet& new_nodes_in_junction_tree) {
765 std::vector< Edge > notAffectedneighbourCliques;
769 for (
const auto& elt: _mps_affected_)
772 const std::vector< NodeId >& cliques = _cliques_of_mps_[elt.first];
774 for (
unsigned int i = 0; i < cliques.size(); ++i)
775 all_cliques_affected.insert(cliques[i],
true);
780 for (
const auto& elt: all_cliques_affected) {
785 notAffectedneighbourCliques.clear();
786 _setUpConnectedTriangulation_(elt.first,
789 notAffectedneighbourCliques,
790 all_cliques_affected);
793 for (
auto edge: _graph_.edges()) {
795 tmp_graph.addEdge(edge.first(), edge.second());
796 }
catch (Exception
const&) {}
804 for (
const auto node: tmp_graph.nodes()) {
805 List< NodeId >& mps = _mps_of_node_[node];
807 for (HashTableConstIteratorSafe< NodeId, bool > iter_mps
808 = _mps_affected_.beginSafe();
809 iter_mps != _mps_affected_.endSafe();
811 if (iter_mps.val()) mps.eraseByVal(iter_mps.key());
817 _triangulation_->setGraph(&tmp_graph, &_domain_sizes_);
819 const CliqueGraph& tmp_junction_tree = _triangulation_->junctionTree();
825 NodeProperty< NodeId > tmp2global_junction_tree(tmp_junction_tree.size());
827 for (
const auto cliq: tmp_junction_tree.nodes()) {
831 NodeId new_id = _junction_tree_.addNode(tmp_junction_tree.clique(cliq));
833 tmp2global_junction_tree.insert(cliq, new_id);
834 new_nodes_in_junction_tree.insert(new_id);
838 for (
const auto& edge: tmp_junction_tree.edges())
839 _junction_tree_.addEdge(tmp2global_junction_tree[edge.first()],
840 tmp2global_junction_tree[edge.second()]);
852 for (
unsigned int i = 0; i < notAffectedneighbourCliques.size(); ++i) {
855 const NodeSet& sep = _junction_tree_.separator(notAffectedneighbourCliques[i]);
857 if (sep.size() != 0) {
859 Size _elim_order_ = tmp_graph.bound() + 1;
860 NodeId elim_node = 0;
862 for (
const auto id: sep) {
863 Size new_order = _triangulation_->eliminationOrder(
id);
865 if (new_order < _elim_order_) {
866 _elim_order_ = new_order;
877 = tmp2global_junction_tree[_triangulation_->createdJunctionTreeClique(elim_node)];
880 = all_cliques_affected.exists(notAffectedneighbourCliques[i].first())
881 ? notAffectedneighbourCliques[i].second()
882 : notAffectedneighbourCliques[i].first();
884 _junction_tree_.addEdge(not_affected, to_connect);
886 if (!new_nodes_in_junction_tree.contains(to_connect)) {
887 _T_mpd_.addEdge(_mps_of_clique_[to_connect], _mps_of_clique_[not_affected]);
893 if (_junction_tree_.separator(not_affected, to_connect).size()
894 == _junction_tree_.clique(to_connect).size()) {
895 _junction_tree_.eraseEdge(Edge(not_affected, to_connect));
897 for (
const auto neighbour: _junction_tree_.neighbours(to_connect)) {
898 _junction_tree_.addEdge(neighbour, not_affected);
900 if (!new_nodes_in_junction_tree.contains(neighbour))
901 _T_mpd_.addEdge(_mps_of_clique_[neighbour], _mps_of_clique_[not_affected]);
904 _junction_tree_.eraseNode(to_connect);
906 to_connect = not_affected;
914 for (
const auto& elt: all_cliques_affected) {
915 _mps_of_clique_.erase(elt.first);
916 _junction_tree_.eraseNode(elt.first);
919 for (
const auto& elt: _mps_affected_)
921 _cliques_of_mps_.erase(elt.first);
922 _T_mpd_.eraseNode(elt.first);
928 void IncrementalTriangulation::_computeMaxPrimeMergings_(
931 std::vector< std::pair< NodeId, NodeId > >& merged_cliques,
932 HashTable< NodeId, bool >& mark,
933 const NodeSet& new_nodes_in_junction_tree)
const {
937 for (
const auto other_node: _junction_tree_.neighbours(node))
938 if (other_node != from) {
939 const NodeSet& separator = _junction_tree_.separator(Edge(other_node, node));
942 bool complete =
true;
944 for (
auto iter_sep1 = separator.begin(); iter_sep1 != separator.end() && complete;
946 auto iter_sep2 = iter_sep1;
948 for (++iter_sep2; iter_sep2 != separator.end(); ++iter_sep2) {
949 if (!_graph_.existsEdge(*iter_sep1, *iter_sep2)) {
957 if (!complete) merged_cliques.push_back(std::pair< NodeId, NodeId >(other_node, node));
959 if (new_nodes_in_junction_tree.contains(other_node))
960 _computeMaxPrimeMergings_(other_node,
964 new_nodes_in_junction_tree);
970 void IncrementalTriangulation::_updateMaxPrimeSubgraph_(
971 NodeProperty< bool >& all_cliques_affected,
972 const NodeSet& new_nodes_in_junction_tree) {
981 HashTable< NodeId, NodeId > T_mpd_cliques(all_cliques_affected.size());
983 for (
const auto clik: _junction_tree_.nodes())
984 if (new_nodes_in_junction_tree.contains(clik)) T_mpd_cliques.insert(clik, clik);
988 std::vector< std::pair< NodeId, NodeId > > merged_cliques;
990 HashTable< NodeId, bool > mark = T_mpd_cliques.map(
false);
992 for (
const auto& elt: mark)
994 _computeMaxPrimeMergings_(elt.first,
998 new_nodes_in_junction_tree);
1003 for (
unsigned int i = 0; i < merged_cliques.size(); ++i) {
1004 if (T_mpd_cliques.exists(merged_cliques[i].second))
1005 T_mpd_cliques[merged_cliques[i].first] = T_mpd_cliques[merged_cliques[i].second];
1006 else T_mpd_cliques[merged_cliques[i].first] = _mps_of_clique_[merged_cliques[i].second];
1013 NodeProperty< NodeId > clique2MPS(T_mpd_cliques.size());
1017 for (
const auto& elt: T_mpd_cliques)
1018 if (elt.first == elt.second) {
1019 NodeId newId = _T_mpd_.addNode(_junction_tree_.clique(elt.second));
1020 clique2MPS.insert(elt.second, newId);
1021 std::vector< NodeId >& vect_of_cliques
1022 = _cliques_of_mps_.insert(newId, std::vector< NodeId >()).second;
1023 vect_of_cliques.push_back(elt.second);
1028 for (
const auto& elt: T_mpd_cliques)
1029 if ((elt.first != elt.second) && (new_nodes_in_junction_tree.contains(elt.second))) {
1030 const NodeId idMPS = clique2MPS[elt.second];
1032 for (
const auto node: _junction_tree_.clique(elt.first)) {
1034 _T_mpd_.addToClique(idMPS, node);
1038 _cliques_of_mps_[idMPS].push_back(elt.first);
1042 for (
const auto& elt: T_mpd_cliques) {
1043 const NodeId idMPS = clique2MPS[elt.second];
1044 _mps_of_clique_.insert(elt.first, idMPS);
1046 if (elt.first == elt.second)
1047 for (
const auto node: _T_mpd_.clique(idMPS))
1048 _mps_of_node_[node].insert(idMPS);
1052 for (
const auto& elt: T_mpd_cliques) {
1053 NodeId clique = clique2MPS[elt.second];
1055 for (
const auto othernode: _junction_tree_.neighbours(elt.first))
1056 if (T_mpd_cliques.exists(othernode)) {
1059 NodeId otherClique = clique2MPS[T_mpd_cliques[othernode]];
1062 if (clique > otherClique) { _T_mpd_.addEdge(clique, otherClique); }
1064 _T_mpd_.addEdge(clique, _mps_of_clique_[othernode]);
1071 void IncrementalTriangulation::updateTriangulation() {
1072 if (!_require_update_)
return;
1075 NodeProperty< bool > all_cliques_affected(_junction_tree_.size());
1083 NodeSet new_nodes_in_junction_tree;
1085 _updateJunctionTree_(all_cliques_affected, new_nodes_in_junction_tree);
1088 _updateMaxPrimeSubgraph_(all_cliques_affected, new_nodes_in_junction_tree);
1091 _mps_affected_.clear();
1093 for (
const auto node: _T_mpd_.nodes())
1094 _mps_affected_.insert(node,
false);
1097 _triangulation_->clear();
1099 _require_update_ =
false;
1104 void IncrementalTriangulation::clear() {
1106 _domain_sizes_.clear();
1107 _junction_tree_.clear();
1109 _mps_of_node_.clear();
1110 _cliques_of_mps_.clear();
1111 _mps_of_clique_.clear();
1112 _mps_affected_.clear();
1113 _triangulation_->clear();
1114 _require_update_ =
false;
1115 _require_elimination_order_ =
false;
1116 _elimination_order_.clear();
1117 _reverse_elimination_order_.clear();
1118 _require_created_JT_cliques_ =
false;
1119 _created_JT_cliques_.clear();
1124 void IncrementalTriangulation::_collectJTCliques_(
const NodeId clique,
1126 NodeProperty< bool >& examined) {
1128 for (
const auto otherclique: _junction_tree_.neighbours(clique))
1129 if (otherclique != from) _collectJTCliques_(otherclique, clique, examined);
1132 examined[clique] =
true;
1134 const NodeSet& cliquenodes = _junction_tree_.clique(clique);
1136 if (from != clique) {
1137 const NodeSet& separator = _junction_tree_.separator(clique, from);
1139 for (
const auto cli: cliquenodes)
1140 if (!separator.contains(cli)) _created_JT_cliques_.
insert(cli, clique);
1142 for (
const auto cli: cliquenodes)
1143 _created_JT_cliques_.insert(cli, clique);
1150 const NodeProperty< NodeId >& IncrementalTriangulation::createdJunctionTreeCliques() {
1152 if (!_require_created_JT_cliques_)
return _created_JT_cliques_;
1155 updateTriangulation();
1157 _created_JT_cliques_.clear();
1159 _require_created_JT_cliques_ =
false;
1161 if (_junction_tree_.size() == 0) {
return _created_JT_cliques_; }
1164 NodeProperty< bool > examined = _junction_tree_.nodesPropertyFromVal<
bool >(
false);
1166 for (
const auto& elt: examined)
1167 if (!elt.second) _collectJTCliques_(elt.first, elt.first, examined);
1169 return _created_JT_cliques_;
1174 NodeId IncrementalTriangulation::createdJunctionTreeClique(NodeId
id) {
1175 createdJunctionTreeCliques();
1176 return _created_JT_cliques_[id];
1182 NodeId IncrementalTriangulation::createdMaxPrimeSubgraph(
const NodeId
id) {
1184 return _mps_of_clique_[createdJunctionTreeClique(
id)];
1189 void IncrementalTriangulation::setGraph(
const UndiGraph* graph,
1190 const NodeProperty< Size >* dom_sizes) {
1193 if (((graph !=
nullptr) && (dom_sizes ==
nullptr))
1194 || ((graph ==
nullptr) && (dom_sizes !=
nullptr))) {
1196 "one of the graph or the set of domain sizes "
1197 "is a null pointer.");
1205 if (graph !=
nullptr) {
1206 for (
const auto node: *graph)
1207 addNode(node, (*dom_sizes)[node]);
1209 for (
const auto& edge: graph->edges())
1210 addEdge(edge.first(), edge.second());
1216 void IncrementalTriangulation::_collectEliminationOrder_(
const NodeId node,
1218 NodeProperty< bool >& examined,
1221 for (
const auto othernode: _junction_tree_.neighbours(node))
1222 if (othernode != from) _collectEliminationOrder_(othernode, node, examined, index);
1225 examined[node] =
true;
1227 const NodeSet& clique = _junction_tree_.clique(node);
1230 const NodeSet& separator = _junction_tree_.separator(node, from);
1232 for (
const auto cli: clique) {
1233 if (!separator.contains(cli)) {
1234 _elimination_order_[index] = cli;
1235 _reverse_elimination_order_.insert(cli, index);
1240 for (
const auto cli: clique) {
1241 _elimination_order_[index] = cli;
1242 _reverse_elimination_order_.insert(cli, index);
1250 const std::vector< NodeId >& IncrementalTriangulation::eliminationOrder() {
1252 if (!_require_elimination_order_)
return _elimination_order_;
1255 updateTriangulation();
1257 _elimination_order_.resize(_graph_.size());
1259 _reverse_elimination_order_.clear();
1261 _require_elimination_order_ =
false;
1263 if (_junction_tree_.size() == Size(0)) {
return _elimination_order_; }
1268 NodeProperty< bool > examined = _junction_tree_.nodesPropertyFromVal<
bool >(
false);
1270 for (
const auto& elt: examined)
1271 if (!elt.second) _collectEliminationOrder_(elt.first, elt.first, examined, index);
1273 return _elimination_order_;
1279 Idx IncrementalTriangulation::eliminationOrder(
const NodeId node) {
1280 if (!_graph_.existsNode(node)) {
GUM_ERROR(
NotFound,
"the node " << node <<
" does not exist") }
1285 return _reverse_elimination_order_[node];
Exception : a similar element already exists.
Exception base for graph error.
IncrementalTriangulation(const UnconstrainedTriangulation &triang_algo, const UndiGraph *theGraph, const NodeProperty< Size > *modal)
constructor
Exception : the element we looked for cannot be found.
void insert(const Key &k)
Inserts a new element into the set.
Interface for all the triangulation methods.
Interface for all triangulation methods without constraints on node elimination orderings.
Base class for undirected graphs.
#define GUM_ERROR(type, msg)
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
Class for computing default triangulations of graphs.
Inline implementations for computing default triangulations of graphs.
Generic class for manipulating lists.
gum is the global namespace for all aGrUM entities
Base classes for undirected graphs.