39 #endif // GUM_NO_INLINE 41 #ifndef DOXYGEN_SHOULD_SKIP_THIS 47 const UnconstrainedTriangulation& triang_algo,
48 const UndiGraph* theGraph,
49 const NodeProperty< Size >* domsizes) :
50 Triangulation(domsizes),
51 __triangulation(triang_algo.newFactory()) {
53 GUM_CONSTRUCTOR(IncrementalTriangulation);
56 __triangulation->clear();
61 for (
const auto node : *theGraph)
62 addNode(node, (*domsizes)[node]);
66 for (
const auto& edge : theGraph->edges())
67 addEdge(edge.first(), edge.second());
72 const UnconstrainedTriangulation& triang_algo) :
75 GUM_CONSTRUCTOR(IncrementalTriangulation);
78 __triangulation->clear();
83 const IncrementalTriangulation& from) :
85 __graph(from.__graph), __junction_tree(from.__junction_tree),
86 __T_mpd(from.__T_mpd), __mps_of_node(from.__mps_of_node),
87 __cliques_of_mps(from.__cliques_of_mps),
88 __mps_of_clique(from.__mps_of_clique), __mps_affected(from.__mps_affected),
89 __triangulation(from.__triangulation->
newFactory()),
90 __require_update(from.__require_update),
91 __require_elimination_order(from.__require_elimination_order),
92 __elimination_order(from.__elimination_order),
93 __reverse_elimination_order(from.__reverse_elimination_order),
94 __require_created_JT_cliques(from.__require_created_JT_cliques),
95 __created_JT_cliques(from.__created_JT_cliques) {
97 GUM_CONS_CPY(IncrementalTriangulation);
99 __domain_sizes = from.__domain_sizes;
105 GUM_DESTRUCTOR(IncrementalTriangulation);
108 delete __triangulation;
113 return new IncrementalTriangulation(*__triangulation);
118 return new IncrementalTriangulation(*
this);
123 operator=(
const IncrementalTriangulation& from) {
127 GUM_OP_CPY(IncrementalTriangulation);
130 __graph = from.__graph;
131 __domain_sizes = from.__domain_sizes;
132 __junction_tree = from.__junction_tree;
133 __T_mpd = from.__T_mpd;
134 __mps_of_node = from.__mps_of_node;
135 __cliques_of_mps = from.__cliques_of_mps;
136 __mps_of_clique = from.__mps_of_clique;
137 __mps_affected = from.__mps_affected;
138 __require_update = from.__require_update;
139 __require_elimination_order = from.__require_elimination_order;
140 __elimination_order = from.__elimination_order;
141 __reverse_elimination_order = from.__reverse_elimination_order;
142 __require_created_JT_cliques = from.__require_created_JT_cliques;
143 __created_JT_cliques = from.__created_JT_cliques;
147 delete __triangulation;
148 __triangulation = from.__triangulation->newFactory();
157 if (__graph.existsNode(node))
return;
160 __graph.addNodeWithId(node);
161 __domain_sizes.insert(node, modal);
165 clique_nodes.insert(node);
167 NodeId MPS = __T_mpd.addNode(clique_nodes);
168 NodeId new_clique = __junction_tree.addNode(clique_nodes);
171 List< NodeId >& list_of_mps =
172 __mps_of_node.insert(node, List< NodeId >()).second;
173 list_of_mps.insert(MPS);
176 std::vector< NodeId >& cliquesMPS =
177 __cliques_of_mps.insert(MPS, std::vector< NodeId >()).second;
179 cliquesMPS.push_back(new_clique);
180 __mps_of_clique.insert(new_clique, MPS);
183 __mps_affected.insert(MPS,
false);
186 __elimination_order.push_back(node);
188 if (!__reverse_elimination_order.exists(node))
189 __reverse_elimination_order.insert(node,
Size(__elimination_order.size()));
191 if (!__created_JT_cliques.exists(node))
192 __created_JT_cliques.insert(node, new_clique);
201 __mps_affected[My] =
true;
204 for (
const auto nei : __T_mpd.neighbours(My))
206 const NodeSet& Syk = __T_mpd.separator(Edge(nei, My));
208 if (Syk.contains(edge.first()) && Syk.contains(edge.second()))
209 __markAffectedMPSsByRemoveLink(nei, My, edge);
217 if (!__graph.existsEdge(edge))
return;
220 const NodeId X = edge.first();
221 const NodeId Y = edge.second();
223 const List< NodeId >& mps1 = __mps_of_node[X];
224 const List< NodeId >& mps2 = __mps_of_node[Y];
228 if (mps1.size() <= mps2.size()) {
229 for (
const auto node : mps1)
230 if (__T_mpd.clique(node).contains(Y)) {
235 for (
const auto node : mps2)
236 if (__T_mpd.clique(node).contains(X)) {
243 __markAffectedMPSsByRemoveLink(Mx, Mx, edge);
245 __require_update =
true;
247 __require_elimination_order =
true;
249 __require_created_JT_cliques =
true;
252 __graph.eraseEdge(edge);
260 if (!__graph.existsNode(X))
return;
264 const NodeSet& neighbours = __graph.neighbours(X);
266 for (
auto neighbour_edge =
267 neighbours.beginSafe();
268 neighbour_edge != neighbours.endSafe();
270 eraseEdge(Edge(*neighbour_edge, X));
274 auto& MPS_of_X = __mps_of_node[X];
277 for (
const auto node : MPS_of_X) {
278 __T_mpd.eraseFromClique(node, X);
282 auto& neighbours = __T_mpd.neighbours(node);
284 for (
auto it_neighbour = neighbours.beginSafe();
285 it_neighbour != neighbours.endSafe();
287 Edge neigh(*it_neighbour, node);
289 if (__T_mpd.separator(neigh).size() == 0) __T_mpd.eraseEdge(neigh);
294 for (
const auto clique : MPS_of_X) {
295 const std::vector< NodeId >& cliques_of_X = __cliques_of_mps[clique];
297 for (
unsigned int i = 0; i < cliques_of_X.size(); ++i) {
298 __junction_tree.eraseFromClique(cliques_of_X[i], X);
303 auto& neighbours = __junction_tree.neighbours(cliques_of_X[i]);
305 for (
auto it_neighbour = neighbours.beginSafe();
306 it_neighbour != neighbours.endSafe();
308 Edge neigh(*it_neighbour, cliques_of_X[i]);
310 if (__junction_tree.separator(neigh).size() == 0) {
313 bool hasCommonEdge =
false;
315 for (
const auto node1 : __junction_tree.clique(neigh.first()))
316 for (
const auto node2 : __junction_tree.clique(neigh.second()))
317 if (__graph.existsEdge(node1, node2)) {
318 hasCommonEdge =
true;
322 if (!hasCommonEdge) { __junction_tree.eraseEdge(neigh); }
330 if ((MPS_of_X.size() == 1) && (__T_mpd.clique(MPS_of_X[0]).size() == 0)) {
331 __junction_tree.eraseNode(__cliques_of_mps[MPS_of_X[0]][0]);
332 __T_mpd.eraseNode(MPS_of_X[0]);
333 __mps_of_clique.erase(__cliques_of_mps[MPS_of_X[0]][0]);
334 __cliques_of_mps.erase(MPS_of_X[0]);
335 __mps_affected.erase(MPS_of_X[0]);
338 __mps_of_node.erase(X);
342 if (!__require_update) {
343 for (
Idx i = __reverse_elimination_order[X] + 1;
344 i < __reverse_elimination_order.size();
346 __elimination_order[i - 1] = __elimination_order[i];
348 __elimination_order.pop_back();
350 __reverse_elimination_order.erase(X);
352 __created_JT_cliques.erase(X);
356 __graph.eraseNode(X);
358 __domain_sizes.erase(X);
372 const NodeSet& cliqueMX = __T_mpd.clique(Mx);
374 if (cliqueMX.contains(Y)) {
375 __mps_affected[Mx] =
true;
377 if (cliqueMX.contains(X))
return 2;
383 for (
const auto other_node : __T_mpd.neighbours(Mx))
384 if (other_node != Mz) {
385 int neighbourStatus = __markAffectedMPSsByAddLink(other_node, Mx, X, Y);
387 if (neighbourStatus == 2)
389 else if (neighbourStatus == 1) {
390 __mps_affected[Mx] =
true;
392 if (cliqueMX.contains(X))
return 2;
406 if ((X == Y) || !__graph.existsNode(X) || !__graph.existsNode(Y)
407 || __graph.existsEdge(Edge(X, Y)))
411 __graph.addEdge(X, Y);
414 NodeId& mps_X = __mps_of_node[X][0];
416 int found = __markAffectedMPSsByAddLink(mps_X, mps_X, X, Y);
421 NodeId& mps_Y = __mps_of_node[Y][0];
426 const std::vector< NodeId >& cliques_X = __cliques_of_mps[mps_X];
427 const std::vector< NodeId >& cliques_Y = __cliques_of_mps[mps_Y];
430 for (
unsigned int i = 0; i < cliques_X.size(); ++i) {
431 if (__junction_tree.clique(cliques_X[i]).contains(X)) {
437 for (
unsigned int i = 0; i < cliques_Y.size(); ++i) {
438 if (__junction_tree.clique(cliques_Y[i]).contains(Y)) {
451 NodeId newNode = __junction_tree.addNode(nodes);
453 __junction_tree.addEdge(newNode, c_X);
454 __junction_tree.addEdge(newNode, c_Y);
456 NodeId newMPS = __T_mpd.addNode(nodes);
458 __T_mpd.addEdge(newMPS, mps_X);
459 __T_mpd.addEdge(newMPS, mps_Y);
465 if (__T_mpd.clique(mps_X).size() == 1) {
466 __junction_tree.eraseNode(c_X);
467 __T_mpd.eraseNode(mps_X);
468 __mps_affected.erase(mps_X);
469 __mps_of_clique.erase(c_X);
470 __cliques_of_mps.erase(mps_X);
471 __created_JT_cliques[X] = newNode;
474 __mps_of_node[X].insert(newMPS);
477 if (__T_mpd.clique(mps_Y).size() == 1) {
478 __junction_tree.eraseNode(c_Y);
479 __T_mpd.eraseNode(mps_Y);
480 __mps_affected.erase(mps_Y);
481 __mps_of_clique.erase(c_Y);
482 __cliques_of_mps.erase(mps_Y);
483 __created_JT_cliques[Y] = newNode;
486 __mps_of_node[Y].insert(newMPS);
488 std::vector< NodeId >& cl =
489 __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;
509 updateTriangulation();
515 NodeProperty< bool > nodesProp = __graph.nodesProperty<
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.nodesProperty<
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
575 << __graph << std::endl
576 << __T_mpd << std::endl;
580 if (!OK)
return false;
585 std::pair< NodeId, NodeId > thePair;
586 EdgeProperty< bool > edgesProp = __graph.edgesProperty(
false);
588 for (
const auto cliq : __T_mpd.nodes()) {
589 const NodeSet& clique = __T_mpd.clique(cliq);
591 for (
auto iter2 = clique.begin(); iter2 != clique.end(); ++iter2) {
594 for (++iter3; iter3 != clique.end(); ++iter3) {
595 thePair.first = std::min(*iter2, *iter3);
596 thePair.second = std::max(*iter2, *iter3);
598 if (__graph.existsEdge(thePair.first, thePair.second))
599 edgesProp[Edge(thePair.first, thePair.second)] =
true;
604 for (
const auto& elt : edgesProp)
606 std::cerr <<
"check edges" << std::endl
607 << __graph << std::endl
608 << __T_mpd << std::endl;
612 if (!OK)
return false;
617 NodeProperty< NodeProperty< bool > > chk;
619 for (
const auto node : __graph.nodes())
622 for (
const auto cliq : __T_mpd.nodes())
623 for (
auto node : __T_mpd.clique(cliq))
624 chk[node].insert(cliq,
false);
626 for (
const auto& elt : __mps_of_node) {
629 for (
const auto cell : elt.second) {
631 std::cerr <<
"check mps of nodes" << std::endl
632 << __T_mpd << std::endl
633 << __mps_of_node << std::endl;
641 for (
const auto& elt : chk)
642 for (
const auto& elt2 : elt.second)
644 std::cerr <<
"check mps of nodes2" << std::endl
645 << __T_mpd << std::endl
646 << __mps_of_node << std::endl;
650 if (!OK)
return false;
655 if (!__junction_tree.isJoinTree()) {
656 std::cerr <<
"check join tree __junction_tree" << std::endl
657 << __junction_tree << std::endl;
661 if (!__T_mpd.isJoinTree()) {
662 std::cerr <<
"check join tree __T_mpd" << std::endl
663 << __T_mpd << std::endl;
672 if (__elimination_order.size() != __graph.size()) {
673 std::cerr <<
"check elimination order" << std::endl
674 << __elimination_order << std::endl;
680 for (
const auto node : __graph.nodes()) {
681 if (nodes.exists(node)) {
682 std::cerr <<
"check elimination order" << std::endl
683 << __elimination_order << std::endl;
689 if (nodes.size() != __graph.size()) {
690 std::cerr <<
"check elimination order" << std::endl
691 << __elimination_order << std::endl;
695 if (__reverse_elimination_order.size() != __graph.size()) {
696 std::cerr <<
"check reverse elimination order" << std::endl
697 << __reverse_elimination_order << std::endl;
701 for (
const auto node : __graph.nodes()) {
702 if (!__reverse_elimination_order.exists(node)) {
703 std::cerr <<
"check reverse elimination order" << std::endl
704 << __reverse_elimination_order << std::endl;
712 createdJunctionTreeCliques();
714 if (__created_JT_cliques.size() != __graph.size()) {
715 std::cerr <<
"check creating JT cliques" << std::endl
716 << __created_JT_cliques << std::endl;
720 for (
const auto node : __graph.nodes()) {
721 if (!__created_JT_cliques.exists(node)
722 || !__junction_tree.existsNode(__created_JT_cliques[node])) {
723 std::cerr <<
"check created JT cliques" << std::endl
724 << __created_JT_cliques << std::endl;
739 std::vector< Edge >& notAffectedneighbourCliques,
742 cliques_affected[Mx] =
false;
745 for (
const auto node : __junction_tree.clique(Mx))
746 if (!theGraph.exists(node)) theGraph.addNodeWithId(node);
749 for (
const auto othernode : __junction_tree.neighbours(Mx))
750 if (othernode != Mfrom) {
751 if (cliques_affected.
exists(othernode)) {
752 __setUpConnectedTriangulation(othernode,
755 notAffectedneighbourCliques,
760 notAffectedneighbourCliques.push_back(Edge(othernode, Mx));
768 NodeProperty< bool >& all_cliques_affected,
769 NodeSet& new_nodes_in_junction_tree) {
777 std::vector< Edge > notAffectedneighbourCliques;
781 for (
const auto& elt : __mps_affected)
784 const std::vector< NodeId >& cliques = __cliques_of_mps[elt.first];
786 for (
unsigned int i = 0; i < cliques.size(); ++i)
787 all_cliques_affected.insert(cliques[i],
true);
792 for (
const auto& elt : all_cliques_affected) {
797 notAffectedneighbourCliques.clear();
798 __setUpConnectedTriangulation(elt.first,
801 notAffectedneighbourCliques,
802 all_cliques_affected);
805 for (
auto edge : __graph.edges()) {
807 tmp_graph.addEdge(edge.first(), edge.second());
808 }
catch (Exception&) {}
816 for (
const auto node : tmp_graph.nodes()) {
817 List< NodeId >& mps = __mps_of_node[node];
820 __mps_affected.beginSafe();
821 iter_mps != __mps_affected.endSafe();
823 if (iter_mps.val()) mps.eraseByVal(iter_mps.key());
829 __triangulation->setGraph(&tmp_graph, &__domain_sizes);
831 const CliqueGraph& tmp_junction_tree = __triangulation->junctionTree();
837 NodeProperty< NodeId > tmp2global_junction_tree(tmp_junction_tree.size());
839 for (
const auto cliq : tmp_junction_tree.nodes()) {
843 NodeId new_id = __junction_tree.addNode(tmp_junction_tree.clique(cliq));
845 tmp2global_junction_tree.insert(cliq, new_id);
846 new_nodes_in_junction_tree.insert(new_id);
850 for (
const auto edge : tmp_junction_tree.edges())
851 __junction_tree.addEdge(tmp2global_junction_tree[edge.first()],
852 tmp2global_junction_tree[edge.second()]);
864 for (
unsigned int i = 0; i < notAffectedneighbourCliques.size(); ++i) {
868 __junction_tree.separator(notAffectedneighbourCliques[i]);
870 if (sep.size() != 0) {
872 Size __elim_order = tmp_graph.bound() + 1;
875 for (
const auto id : sep) {
876 Size new_order = __triangulation->eliminationOrder(
id);
878 if (new_order < __elim_order) {
879 __elim_order = new_order;
890 tmp2global_junction_tree[__triangulation->createdJunctionTreeClique(
894 all_cliques_affected.exists(notAffectedneighbourCliques[i].first())
895 ? notAffectedneighbourCliques[i].second()
896 : notAffectedneighbourCliques[i].first();
898 __junction_tree.addEdge(not_affected, to_connect);
900 if (!new_nodes_in_junction_tree.contains(to_connect)) {
901 __T_mpd.addEdge(__mps_of_clique[to_connect],
902 __mps_of_clique[not_affected]);
908 if (__junction_tree.separator(not_affected, to_connect).size()
909 == __junction_tree.clique(to_connect).size()) {
910 __junction_tree.eraseEdge(Edge(not_affected, to_connect));
912 for (
const auto neighbour : __junction_tree.neighbours(to_connect)) {
913 __junction_tree.addEdge(neighbour, not_affected);
915 if (!new_nodes_in_junction_tree.contains(neighbour))
916 __T_mpd.addEdge(__mps_of_clique[neighbour],
917 __mps_of_clique[not_affected]);
920 __junction_tree.eraseNode(to_connect);
922 to_connect = not_affected;
930 for (
const auto& elt : all_cliques_affected) {
931 __mps_of_clique.erase(elt.first);
932 __junction_tree.eraseNode(elt.first);
935 for (
const auto& elt : __mps_affected)
937 __cliques_of_mps.erase(elt.first);
938 __T_mpd.eraseNode(elt.first);
947 std::vector< std::pair< NodeId, NodeId > >& merged_cliques,
949 const NodeSet& new_nodes_in_junction_tree)
const {
953 for (
const auto other_node : __junction_tree.neighbours(node))
954 if (other_node != from) {
956 __junction_tree.separator(Edge(other_node, node));
959 bool complete =
true;
961 for (
auto iter_sep1 = separator.begin();
962 iter_sep1 != separator.end() && complete;
964 auto iter_sep2 = iter_sep1;
966 for (++iter_sep2; iter_sep2 != separator.end(); ++iter_sep2) {
967 if (!__graph.existsEdge(*iter_sep1, *iter_sep2)) {
976 merged_cliques.push_back(std::pair< NodeId, NodeId >(other_node, node));
978 if (new_nodes_in_junction_tree.contains(other_node))
979 __computeMaxPrimeMergings(
980 other_node, node, merged_cliques, mark, new_nodes_in_junction_tree);
987 NodeProperty< bool >& all_cliques_affected,
988 const NodeSet& new_nodes_in_junction_tree) {
999 for (
const auto clik : __junction_tree.nodes())
1000 if (new_nodes_in_junction_tree.contains(clik))
1001 T_mpd_cliques.
insert(clik, clik);
1005 std::vector< std::pair< NodeId, NodeId > > merged_cliques;
1009 for (
const auto& elt : mark)
1011 __computeMaxPrimeMergings(
1012 elt.first, elt.first, merged_cliques, mark, new_nodes_in_junction_tree);
1017 for (
unsigned int i = 0; i < merged_cliques.size(); ++i) {
1018 if (T_mpd_cliques.exists(merged_cliques[i].second))
1019 T_mpd_cliques[merged_cliques[i].first] =
1020 T_mpd_cliques[merged_cliques[i].second];
1022 T_mpd_cliques[merged_cliques[i].first] =
1023 __mps_of_clique[merged_cliques[i].second];
1030 NodeProperty< NodeId > clique2MPS(T_mpd_cliques.size());
1034 for (
const auto& elt : T_mpd_cliques)
1035 if (elt.first == elt.second) {
1036 NodeId newId = __T_mpd.addNode(__junction_tree.clique(elt.second));
1037 clique2MPS.insert(elt.second, newId);
1038 std::vector< NodeId >& vect_of_cliques =
1039 __cliques_of_mps.insert(newId, std::vector< NodeId >()).second;
1040 vect_of_cliques.push_back(elt.second);
1045 for (
const auto& elt : T_mpd_cliques)
1046 if ((elt.first != elt.second)
1047 && (new_nodes_in_junction_tree.contains(elt.second))) {
1048 const NodeId idMPS = clique2MPS[elt.second];
1050 for (
const auto node : __junction_tree.clique(elt.first)) {
1052 __T_mpd.addToClique(idMPS, node);
1053 }
catch (DuplicateElement&) {}
1056 __cliques_of_mps[idMPS].push_back(elt.first);
1060 for (
const auto& elt : T_mpd_cliques) {
1061 const NodeId idMPS = clique2MPS[elt.second];
1062 __mps_of_clique.insert(elt.first, idMPS);
1064 if (elt.first == elt.second)
1065 for (
const auto node : __T_mpd.clique(idMPS))
1066 __mps_of_node[node].insert(idMPS);
1070 for (
const auto& elt : T_mpd_cliques) {
1071 NodeId clique = clique2MPS[elt.second];
1073 for (
const auto othernode : __junction_tree.neighbours(elt.first))
1074 if (T_mpd_cliques.exists(othernode)) {
1077 NodeId otherClique = clique2MPS[T_mpd_cliques[othernode]];
1080 if (clique > otherClique) { __T_mpd.addEdge(clique, otherClique); }
1082 __T_mpd.addEdge(clique, __mps_of_clique[othernode]);
1090 if (!__require_update)
return;
1093 NodeProperty< bool > all_cliques_affected(__junction_tree.size());
1101 NodeSet new_nodes_in_junction_tree;
1103 __updateJunctionTree(all_cliques_affected, new_nodes_in_junction_tree);
1106 __updateMaxPrimeSubgraph(all_cliques_affected, new_nodes_in_junction_tree);
1109 __mps_affected.clear();
1111 for (
const auto node : __T_mpd.nodes())
1112 __mps_affected.insert(node,
false);
1115 __triangulation->clear();
1117 __require_update =
false;
1124 __domain_sizes.clear();
1125 __junction_tree.clear();
1127 __mps_of_node.clear();
1128 __cliques_of_mps.clear();
1129 __mps_of_clique.clear();
1130 __mps_affected.clear();
1131 __triangulation->clear();
1132 __require_update =
false;
1133 __require_elimination_order =
false;
1134 __elimination_order.clear();
1135 __reverse_elimination_order.clear();
1136 __require_created_JT_cliques =
false;
1137 __created_JT_cliques.clear();
1143 const NodeId clique,
const NodeId from, NodeProperty< bool >& examined) {
1145 for (
const auto otherclique : __junction_tree.neighbours(clique))
1146 if (otherclique != from) __collectJTCliques(otherclique, clique, examined);
1149 examined[clique] =
true;
1151 const NodeSet& cliquenodes = __junction_tree.clique(clique);
1153 if (from != clique) {
1154 const NodeSet& separator = __junction_tree.separator(clique, from);
1156 for (
const auto cli : cliquenodes)
1157 if (!separator.contains(cli)) __created_JT_cliques.
insert(cli, clique);
1159 for (
const auto cli : cliquenodes)
1160 __created_JT_cliques.insert(cli, clique);
1167 const NodeProperty< NodeId >&
1170 if (!__require_created_JT_cliques)
return __created_JT_cliques;
1173 updateTriangulation();
1175 __created_JT_cliques.clear();
1177 __require_created_JT_cliques =
false;
1179 if (__junction_tree.size() == 0) {
return __created_JT_cliques; }
1182 NodeProperty< bool > examined = __junction_tree.nodesProperty<
bool >(
false);
1184 for (
const auto& elt : examined)
1185 if (!elt.second) __collectJTCliques(elt.first, elt.first, examined);
1187 return __created_JT_cliques;
1193 createdJunctionTreeCliques();
1194 return __created_JT_cliques[id];
1202 return __mps_of_clique[createdJunctionTreeClique(
id)];
1208 const NodeProperty< Size >* dom_sizes) {
1211 if (((graph !=
nullptr) && (dom_sizes ==
nullptr))
1212 || ((graph ==
nullptr) && (dom_sizes !=
nullptr))) {
1214 "one of the graph or the set of domain sizes " 1215 "is a null pointer.");
1223 if (graph !=
nullptr) {
1224 for (
const auto node : *graph)
1225 addNode(node, (*dom_sizes)[node]);
1227 for (
const auto& edge : graph->edges())
1228 addEdge(edge.first(), edge.second());
1237 NodeProperty< bool >& examined,
1240 for (
const auto othernode : __junction_tree.neighbours(node))
1241 if (othernode != from)
1242 __collectEliminationOrder(othernode, node, examined, index);
1245 examined[node] =
true;
1247 const NodeSet& clique = __junction_tree.clique(node);
1250 const NodeSet& separator = __junction_tree.separator(node, from);
1252 for (
const auto cli : clique) {
1253 if (!separator.contains(cli)) {
1254 __elimination_order[index] = cli;
1255 __reverse_elimination_order.
insert(cli, index);
1260 for (
const auto cli : clique) {
1261 __elimination_order[index] = cli;
1262 __reverse_elimination_order.insert(cli, index);
1272 if (!__require_elimination_order)
return __elimination_order;
1275 updateTriangulation();
1277 __elimination_order.resize(__graph.size());
1279 __reverse_elimination_order.clear();
1281 __require_elimination_order =
false;
1283 if (__junction_tree.size() ==
Size(0)) {
return __elimination_order; }
1288 NodeProperty< bool > examined = __junction_tree.nodesProperty<
bool >(
false);
1290 for (
const auto& elt : examined)
1292 __collectEliminationOrder(elt.first, elt.first, examined, index);
1294 return __elimination_order;
1301 if (!__graph.existsNode(node)) {
1302 GUM_ERROR(NotFound,
"the node " << node <<
" does not exist");
1308 return __reverse_elimination_order[node];
void __collectJTCliques(const NodeId clique, const NodeId from, NodeProperty< bool > &examined)
a collect algorithm to compute, for each node, one container JT's clique
void eraseEdge(const Edge &edge)
removes an edge from the graph (the join tree may need a retriangulation)
Inline implementations for computing default triangulations of graphs.
virtual void clear()
clears the sequence (to prepare, for instance, a new elimination sequence)
~IncrementalTriangulation()
destructor
void __markAffectedMPSsByRemoveLink(const NodeId My, const NodeId Mz, const Edge &edge)
mark the mps affected by the deletion of a given edge
void setGraph(const UndiGraph *theGraph, const NodeProperty< Size > *domain_sizes)
changes the current graph
void eraseNode(const NodeId node)
removes a node from the graph (the join tree may need a triangulation update)
void __updateMaxPrimeSubgraph(NodeProperty< bool > &cliques_affected, const NodeSet &new_nodes_in_junction_tree)
update the max prime subgraph
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
virtual IncrementalTriangulation * newFactory() const final
virtual clone constructor
const NodeProperty< NodeId > & createdJunctionTreeCliques()
returns the Ids of the cliques of the junction tree created by the elimination of the nodes ...
IncrementalTriangulation(const UnconstrainedTriangulation &triang_algo, const UndiGraph *theGraph, const NodeProperty< Size > *modal)
constructor
int __markAffectedMPSsByAddLink(const NodeId My, const NodeId Mz, const NodeId X, const NodeId Y)
mark the mps affected by the insertion of a new edge
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
IncrementalTriangulation & operator=(const IncrementalTriangulation &from)
copy operator
Base classes for undirected graphs.
gum is the global namespace for all aGrUM entities
UndiGraph * graph() const noexcept
returns the current graph
bool __check()
checks that the incremental triangulation works properly
void updateTriangulation()
updates the triangulated graph using the modif list
NodeId createdMaxPrimeSubgraph(const NodeId id)
returns the Id of the maximal prime subgraph created by the elimination of a given node during the tr...
Generic class for manipulating lists.
void __setUpConnectedTriangulation(NodeId Mx, NodeId Mfrom, UndiGraph &theGraph, std::vector< Edge > ¬AffectedneighborClique, HashTable< NodeId, bool > &cliques_affected)
set-up the connected subgraph that needs be retriangulated
const std::vector< NodeId > & eliminationOrder()
returns an elimination ordering compatible with the triangulated graph
void addNode(const NodeId node, Size modal)
adds a new node to the graph
NodeId createdJunctionTreeClique(const NodeId id)
returns the Id of the clique created by the elimination of a given node during the triangulation proc...
void __updateJunctionTree(NodeProperty< bool > &all_cliques_affected, NodeSet &new_nodes_in_junction_tree)
update the junction tree
void addEdge(const NodeId X, const NodeId Y)
adds a new edge to the graph (the join tree may need a triangulation update)
virtual UnconstrainedEliminationSequenceStrategy * newFactory() const =0
creates a new elimination sequence of the same type as the current object, but this sequence contains...
void __collectEliminationOrder(const NodeId node, const NodeId from, NodeProperty< bool > &examined, Idx &index)
a collect algorithm to compute elimination orderings
Class for computing default triangulations of graphs.
Size Idx
Type for indexes.
void clear()
sets the graph to the empty graph
std::size_t Size
In aGrUM, hashed values are unsigned long int.
void __computeMaxPrimeMergings(const NodeId node, const NodeId from, std::vector< std::pair< NodeId, NodeId > > &merged_cliques, NodeProperty< bool > &mark, const NodeSet &new_nodes_in_junction_tree) const
used for computing the junction tree of the maximal prime subgraphs
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
Size NodeId
Type for node ids.
void insert(const Key &k)
Inserts a new element into the set.
#define GUM_ERROR(type, msg)
HashTable< Key, Mount, OtherAlloc > map(Mount(*f)(Val), Size size=Size(0), bool resize_pol=HashTableConst::default_resize_policy, bool key_uniqueness_pol=HashTableConst::default_uniqueness_policy) const
Transforms a hashtable of vals into a hashtable of mountains.
virtual IncrementalTriangulation * copyFactory() const final
virtual copy constructor