41 #endif // GUM_NO_INLINE 43 #ifndef DOXYGEN_SHOULD_SKIP_THIS 49 const UnconstrainedTriangulation& triang_algo,
50 const UndiGraph* theGraph,
51 const NodeProperty< Size >* domsizes) :
52 Triangulation(domsizes),
53 __triangulation(triang_algo.newFactory()) {
55 GUM_CONSTRUCTOR(IncrementalTriangulation);
58 __triangulation->clear();
63 for (
const auto node : *theGraph)
64 addNode(node, (*domsizes)[node]);
68 for (
const auto& edge : theGraph->edges())
69 addEdge(edge.first(), edge.second());
74 const UnconstrainedTriangulation& triang_algo) :
77 GUM_CONSTRUCTOR(IncrementalTriangulation);
80 __triangulation->clear();
85 const IncrementalTriangulation& from) :
87 __graph(from.__graph), __junction_tree(from.__junction_tree),
88 __T_mpd(from.__T_mpd), __mps_of_node(from.__mps_of_node),
89 __cliques_of_mps(from.__cliques_of_mps),
90 __mps_of_clique(from.__mps_of_clique), __mps_affected(from.__mps_affected),
91 __triangulation(from.__triangulation->
newFactory()),
92 __require_update(from.__require_update),
93 __require_elimination_order(from.__require_elimination_order),
94 __elimination_order(from.__elimination_order),
95 __reverse_elimination_order(from.__reverse_elimination_order),
96 __require_created_JT_cliques(from.__require_created_JT_cliques),
97 __created_JT_cliques(from.__created_JT_cliques) {
99 GUM_CONS_CPY(IncrementalTriangulation);
101 __domain_sizes = from.__domain_sizes;
107 GUM_DESTRUCTOR(IncrementalTriangulation);
110 delete __triangulation;
115 return new IncrementalTriangulation(*__triangulation);
120 return new IncrementalTriangulation(*
this);
125 operator=(
const IncrementalTriangulation& from) {
129 GUM_OP_CPY(IncrementalTriangulation);
132 __graph = from.__graph;
133 __domain_sizes = from.__domain_sizes;
134 __junction_tree = from.__junction_tree;
135 __T_mpd = from.__T_mpd;
136 __mps_of_node = from.__mps_of_node;
137 __cliques_of_mps = from.__cliques_of_mps;
138 __mps_of_clique = from.__mps_of_clique;
139 __mps_affected = from.__mps_affected;
140 __require_update = from.__require_update;
141 __require_elimination_order = from.__require_elimination_order;
142 __elimination_order = from.__elimination_order;
143 __reverse_elimination_order = from.__reverse_elimination_order;
144 __require_created_JT_cliques = from.__require_created_JT_cliques;
145 __created_JT_cliques = from.__created_JT_cliques;
149 delete __triangulation;
150 __triangulation = from.__triangulation->newFactory();
159 if (__graph.existsNode(node))
return;
162 __graph.addNodeWithId(node);
163 __domain_sizes.insert(node, modal);
167 clique_nodes.insert(node);
169 NodeId MPS = __T_mpd.addNode(clique_nodes);
170 NodeId new_clique = __junction_tree.addNode(clique_nodes);
173 List< NodeId >& list_of_mps =
174 __mps_of_node.insert(node, List< NodeId >()).second;
175 list_of_mps.insert(MPS);
178 std::vector< NodeId >& cliquesMPS =
179 __cliques_of_mps.insert(MPS, std::vector< NodeId >()).second;
181 cliquesMPS.push_back(new_clique);
182 __mps_of_clique.insert(new_clique, MPS);
185 __mps_affected.insert(MPS,
false);
188 __elimination_order.push_back(node);
190 if (!__reverse_elimination_order.exists(node))
191 __reverse_elimination_order.insert(node,
Size(__elimination_order.size()));
193 if (!__created_JT_cliques.exists(node))
194 __created_JT_cliques.insert(node, new_clique);
203 __mps_affected[My] =
true;
206 for (
const auto nei : __T_mpd.neighbours(My))
208 const NodeSet& Syk = __T_mpd.separator(Edge(nei, My));
210 if (Syk.contains(edge.first()) && Syk.contains(edge.second()))
211 __markAffectedMPSsByRemoveLink(nei, My, edge);
219 if (!__graph.existsEdge(edge))
return;
222 const NodeId X = edge.first();
223 const NodeId Y = edge.second();
225 const List< NodeId >& mps1 = __mps_of_node[X];
226 const List< NodeId >& mps2 = __mps_of_node[Y];
230 if (mps1.size() <= mps2.size()) {
231 for (
const auto node : mps1)
232 if (__T_mpd.clique(node).contains(Y)) {
237 for (
const auto node : mps2)
238 if (__T_mpd.clique(node).contains(X)) {
245 __markAffectedMPSsByRemoveLink(Mx, Mx, edge);
247 __require_update =
true;
249 __require_elimination_order =
true;
251 __require_created_JT_cliques =
true;
254 __graph.eraseEdge(edge);
262 if (!__graph.existsNode(X))
return;
266 const NodeSet& neighbours = __graph.neighbours(X);
268 for (
auto neighbour_edge =
269 neighbours.beginSafe();
270 neighbour_edge != neighbours.endSafe();
272 eraseEdge(Edge(*neighbour_edge, X));
276 auto& MPS_of_X = __mps_of_node[X];
279 for (
const auto node : MPS_of_X) {
280 __T_mpd.eraseFromClique(node, X);
284 auto& neighbours = __T_mpd.neighbours(node);
286 for (
auto it_neighbour = neighbours.beginSafe();
287 it_neighbour != neighbours.endSafe();
289 Edge neigh(*it_neighbour, node);
291 if (__T_mpd.separator(neigh).size() == 0) __T_mpd.eraseEdge(neigh);
296 for (
const auto clique : MPS_of_X) {
297 const std::vector< NodeId >& cliques_of_X = __cliques_of_mps[clique];
299 for (
unsigned int i = 0; i < cliques_of_X.size(); ++i) {
300 __junction_tree.eraseFromClique(cliques_of_X[i], X);
305 auto& neighbours = __junction_tree.neighbours(cliques_of_X[i]);
307 for (
auto it_neighbour = neighbours.beginSafe();
308 it_neighbour != neighbours.endSafe();
310 Edge neigh(*it_neighbour, cliques_of_X[i]);
312 if (__junction_tree.separator(neigh).size() == 0) {
315 bool hasCommonEdge =
false;
317 for (
const auto node1 : __junction_tree.clique(neigh.first()))
318 for (
const auto node2 : __junction_tree.clique(neigh.second()))
319 if (__graph.existsEdge(node1, node2)) {
320 hasCommonEdge =
true;
324 if (!hasCommonEdge) { __junction_tree.eraseEdge(neigh); }
332 if ((MPS_of_X.size() == 1) && (__T_mpd.clique(MPS_of_X[0]).size() == 0)) {
333 __junction_tree.eraseNode(__cliques_of_mps[MPS_of_X[0]][0]);
334 __T_mpd.eraseNode(MPS_of_X[0]);
335 __mps_of_clique.erase(__cliques_of_mps[MPS_of_X[0]][0]);
336 __cliques_of_mps.erase(MPS_of_X[0]);
337 __mps_affected.erase(MPS_of_X[0]);
340 __mps_of_node.erase(X);
344 if (!__require_update) {
345 for (
Idx i = __reverse_elimination_order[X] + 1;
346 i < __reverse_elimination_order.size();
348 __elimination_order[i - 1] = __elimination_order[i];
350 __elimination_order.pop_back();
352 __reverse_elimination_order.erase(X);
354 __created_JT_cliques.erase(X);
358 __graph.eraseNode(X);
360 __domain_sizes.erase(X);
374 const NodeSet& cliqueMX = __T_mpd.clique(Mx);
376 if (cliqueMX.contains(Y)) {
377 __mps_affected[Mx] =
true;
379 if (cliqueMX.contains(X))
return 2;
385 for (
const auto other_node : __T_mpd.neighbours(Mx))
386 if (other_node != Mz) {
387 int neighbourStatus = __markAffectedMPSsByAddLink(other_node, Mx, X, Y);
389 if (neighbourStatus == 2)
391 else if (neighbourStatus == 1) {
392 __mps_affected[Mx] =
true;
394 if (cliqueMX.contains(X))
return 2;
408 if ((X == Y) || !__graph.existsNode(X) || !__graph.existsNode(Y)
409 || __graph.existsEdge(Edge(X, Y)))
413 __graph.addEdge(X, Y);
416 NodeId& mps_X = __mps_of_node[X][0];
418 int found = __markAffectedMPSsByAddLink(mps_X, mps_X, X, Y);
423 NodeId& mps_Y = __mps_of_node[Y][0];
428 const std::vector< NodeId >& cliques_X = __cliques_of_mps[mps_X];
429 const std::vector< NodeId >& cliques_Y = __cliques_of_mps[mps_Y];
432 for (
unsigned int i = 0; i < cliques_X.size(); ++i) {
433 if (__junction_tree.clique(cliques_X[i]).contains(X)) {
439 for (
unsigned int i = 0; i < cliques_Y.size(); ++i) {
440 if (__junction_tree.clique(cliques_Y[i]).contains(Y)) {
453 NodeId newNode = __junction_tree.addNode(nodes);
455 __junction_tree.addEdge(newNode, c_X);
456 __junction_tree.addEdge(newNode, c_Y);
458 NodeId newMPS = __T_mpd.addNode(nodes);
460 __T_mpd.addEdge(newMPS, mps_X);
461 __T_mpd.addEdge(newMPS, mps_Y);
467 if (__T_mpd.clique(mps_X).size() == 1) {
468 __junction_tree.eraseNode(c_X);
469 __T_mpd.eraseNode(mps_X);
470 __mps_affected.erase(mps_X);
471 __mps_of_clique.erase(c_X);
472 __cliques_of_mps.erase(mps_X);
473 __created_JT_cliques[X] = newNode;
476 __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;
488 __mps_of_node[Y].insert(newMPS);
490 std::vector< NodeId >& cl =
491 __cliques_of_mps.insert(newMPS, std::vector< NodeId >()).second;
493 cl.push_back(newNode);
495 __mps_of_clique.insert(newNode, newMPS);
497 __mps_affected.insert(newMPS,
false);
499 __require_update =
true;
500 __require_created_JT_cliques =
true;
504 __require_elimination_order =
true;
511 updateTriangulation();
517 NodeProperty< bool > nodesProp = __graph.nodesProperty<
bool >(
false);
519 for (
const auto cliq : __junction_tree.nodes())
520 for (
const auto node : __junction_tree.clique(cliq))
521 nodesProp[node] =
true;
523 for (
const auto& elt : nodesProp)
525 std::cerr <<
"check nodes" << std::endl
526 << __graph << std::endl
527 << __junction_tree << std::endl;
531 if (!OK)
return false;
536 std::pair< NodeId, NodeId > thePair;
537 EdgeProperty< bool > edgesProp = __graph.edgesProperty(
false);
539 for (
const auto cliq : __junction_tree.nodes()) {
540 const NodeSet& clique = __junction_tree.clique(cliq);
542 for (
auto iter2 = clique.begin(); iter2 != clique.end(); ++iter2) {
545 for (++iter3; iter3 != clique.end(); ++iter3) {
546 thePair.first = std::min(*iter2, *iter3);
547 thePair.second = std::max(*iter2, *iter3);
549 if (__graph.existsEdge(thePair.first, thePair.second))
550 edgesProp[Edge(thePair.first, thePair.second)] =
true;
555 for (
const auto& elt : edgesProp)
557 std::cerr <<
"check edges" << std::endl
558 << __graph << std::endl
559 << __junction_tree << std::endl;
563 if (!OK)
return false;
568 NodeProperty< bool > nodesProp = __graph.nodesProperty<
bool >(
false);
570 for (
const auto cliq : __T_mpd.nodes())
571 for (
const auto node : __T_mpd.clique(cliq))
572 nodesProp[node] =
true;
574 for (
const auto& elt : nodesProp)
576 std::cerr <<
"check nodes" << std::endl
577 << __graph << std::endl
578 << __T_mpd << std::endl;
582 if (!OK)
return false;
587 std::pair< NodeId, NodeId > thePair;
588 EdgeProperty< bool > edgesProp = __graph.edgesProperty(
false);
590 for (
const auto cliq : __T_mpd.nodes()) {
591 const NodeSet& clique = __T_mpd.clique(cliq);
593 for (
auto iter2 = clique.begin(); iter2 != clique.end(); ++iter2) {
596 for (++iter3; iter3 != clique.end(); ++iter3) {
597 thePair.first = std::min(*iter2, *iter3);
598 thePair.second = std::max(*iter2, *iter3);
600 if (__graph.existsEdge(thePair.first, thePair.second))
601 edgesProp[Edge(thePair.first, thePair.second)] =
true;
606 for (
const auto& elt : edgesProp)
608 std::cerr <<
"check edges" << std::endl
609 << __graph << std::endl
610 << __T_mpd << std::endl;
614 if (!OK)
return false;
619 NodeProperty< NodeProperty< bool > > chk;
621 for (
const auto node : __graph.nodes())
624 for (
const auto cliq : __T_mpd.nodes())
625 for (
auto node : __T_mpd.clique(cliq))
626 chk[node].insert(cliq,
false);
628 for (
const auto& elt : __mps_of_node) {
631 for (
const auto cell : elt.second) {
633 std::cerr <<
"check mps of nodes" << std::endl
634 << __T_mpd << std::endl
635 << __mps_of_node << std::endl;
643 for (
const auto& elt : chk)
644 for (
const auto& elt2 : elt.second)
646 std::cerr <<
"check mps of nodes2" << std::endl
647 << __T_mpd << std::endl
648 << __mps_of_node << std::endl;
652 if (!OK)
return false;
657 if (!__junction_tree.isJoinTree()) {
658 std::cerr <<
"check join tree __junction_tree" << std::endl
659 << __junction_tree << std::endl;
663 if (!__T_mpd.isJoinTree()) {
664 std::cerr <<
"check join tree __T_mpd" << std::endl
665 << __T_mpd << std::endl;
674 if (__elimination_order.size() != __graph.size()) {
675 std::cerr <<
"check elimination order" << std::endl
676 << __elimination_order << std::endl;
682 for (
const auto node : __graph.nodes()) {
683 if (nodes.exists(node)) {
684 std::cerr <<
"check elimination order" << std::endl
685 << __elimination_order << std::endl;
691 if (nodes.size() != __graph.size()) {
692 std::cerr <<
"check elimination order" << std::endl
693 << __elimination_order << std::endl;
697 if (__reverse_elimination_order.size() != __graph.size()) {
698 std::cerr <<
"check reverse elimination order" << std::endl
699 << __reverse_elimination_order << std::endl;
703 for (
const auto node : __graph.nodes()) {
704 if (!__reverse_elimination_order.exists(node)) {
705 std::cerr <<
"check reverse elimination order" << std::endl
706 << __reverse_elimination_order << std::endl;
714 createdJunctionTreeCliques();
716 if (__created_JT_cliques.size() != __graph.size()) {
717 std::cerr <<
"check creating JT cliques" << std::endl
718 << __created_JT_cliques << std::endl;
722 for (
const auto node : __graph.nodes()) {
723 if (!__created_JT_cliques.exists(node)
724 || !__junction_tree.existsNode(__created_JT_cliques[node])) {
725 std::cerr <<
"check created JT cliques" << std::endl
726 << __created_JT_cliques << std::endl;
741 std::vector< Edge >& notAffectedneighbourCliques,
744 cliques_affected[Mx] =
false;
747 for (
const auto node : __junction_tree.clique(Mx))
748 if (!theGraph.exists(node)) theGraph.addNodeWithId(node);
751 for (
const auto othernode : __junction_tree.neighbours(Mx))
752 if (othernode != Mfrom) {
753 if (cliques_affected.
exists(othernode)) {
754 __setUpConnectedTriangulation(othernode,
757 notAffectedneighbourCliques,
762 notAffectedneighbourCliques.push_back(Edge(othernode, Mx));
770 NodeProperty< bool >& all_cliques_affected,
771 NodeSet& new_nodes_in_junction_tree) {
779 std::vector< Edge > notAffectedneighbourCliques;
783 for (
const auto& elt : __mps_affected)
786 const std::vector< NodeId >& cliques = __cliques_of_mps[elt.first];
788 for (
unsigned int i = 0; i < cliques.size(); ++i)
789 all_cliques_affected.insert(cliques[i],
true);
794 for (
const auto& elt : all_cliques_affected) {
799 notAffectedneighbourCliques.clear();
800 __setUpConnectedTriangulation(elt.first,
803 notAffectedneighbourCliques,
804 all_cliques_affected);
807 for (
auto edge : __graph.edges()) {
809 tmp_graph.addEdge(edge.first(), edge.second());
810 }
catch (Exception&) {}
818 for (
const auto node : tmp_graph.nodes()) {
819 List< NodeId >& mps = __mps_of_node[node];
822 __mps_affected.beginSafe();
823 iter_mps != __mps_affected.endSafe();
825 if (iter_mps.val()) mps.eraseByVal(iter_mps.key());
831 __triangulation->setGraph(&tmp_graph, &__domain_sizes);
833 const CliqueGraph& tmp_junction_tree = __triangulation->junctionTree();
839 NodeProperty< NodeId > tmp2global_junction_tree(tmp_junction_tree.size());
841 for (
const auto cliq : tmp_junction_tree.nodes()) {
845 NodeId new_id = __junction_tree.addNode(tmp_junction_tree.clique(cliq));
847 tmp2global_junction_tree.insert(cliq, new_id);
848 new_nodes_in_junction_tree.insert(new_id);
852 for (
const auto edge : tmp_junction_tree.edges())
853 __junction_tree.addEdge(tmp2global_junction_tree[edge.first()],
854 tmp2global_junction_tree[edge.second()]);
866 for (
unsigned int i = 0; i < notAffectedneighbourCliques.size(); ++i) {
870 __junction_tree.separator(notAffectedneighbourCliques[i]);
872 if (sep.size() != 0) {
874 Size __elim_order = tmp_graph.bound() + 1;
877 for (
const auto id : sep) {
878 Size new_order = __triangulation->eliminationOrder(
id);
880 if (new_order < __elim_order) {
881 __elim_order = new_order;
892 tmp2global_junction_tree[__triangulation->createdJunctionTreeClique(
896 all_cliques_affected.exists(notAffectedneighbourCliques[i].first())
897 ? notAffectedneighbourCliques[i].second()
898 : notAffectedneighbourCliques[i].first();
900 __junction_tree.addEdge(not_affected, to_connect);
902 if (!new_nodes_in_junction_tree.contains(to_connect)) {
903 __T_mpd.addEdge(__mps_of_clique[to_connect],
904 __mps_of_clique[not_affected]);
910 if (__junction_tree.separator(not_affected, to_connect).size()
911 == __junction_tree.clique(to_connect).size()) {
912 __junction_tree.eraseEdge(Edge(not_affected, to_connect));
914 for (
const auto neighbour : __junction_tree.neighbours(to_connect)) {
915 __junction_tree.addEdge(neighbour, not_affected);
917 if (!new_nodes_in_junction_tree.contains(neighbour))
918 __T_mpd.addEdge(__mps_of_clique[neighbour],
919 __mps_of_clique[not_affected]);
922 __junction_tree.eraseNode(to_connect);
924 to_connect = not_affected;
932 for (
const auto& elt : all_cliques_affected) {
933 __mps_of_clique.erase(elt.first);
934 __junction_tree.eraseNode(elt.first);
937 for (
const auto& elt : __mps_affected)
939 __cliques_of_mps.erase(elt.first);
940 __T_mpd.eraseNode(elt.first);
949 std::vector< std::pair< NodeId, NodeId > >& merged_cliques,
951 const NodeSet& new_nodes_in_junction_tree)
const {
955 for (
const auto other_node : __junction_tree.neighbours(node))
956 if (other_node != from) {
958 __junction_tree.separator(Edge(other_node, node));
961 bool complete =
true;
963 for (
auto iter_sep1 = separator.begin();
964 iter_sep1 != separator.end() && complete;
966 auto iter_sep2 = iter_sep1;
968 for (++iter_sep2; iter_sep2 != separator.end(); ++iter_sep2) {
969 if (!__graph.existsEdge(*iter_sep1, *iter_sep2)) {
978 merged_cliques.push_back(std::pair< NodeId, NodeId >(other_node, node));
980 if (new_nodes_in_junction_tree.contains(other_node))
981 __computeMaxPrimeMergings(
982 other_node, node, merged_cliques, mark, new_nodes_in_junction_tree);
989 NodeProperty< bool >& all_cliques_affected,
990 const NodeSet& new_nodes_in_junction_tree) {
1001 for (
const auto clik : __junction_tree.nodes())
1002 if (new_nodes_in_junction_tree.contains(clik))
1003 T_mpd_cliques.
insert(clik, clik);
1007 std::vector< std::pair< NodeId, NodeId > > merged_cliques;
1011 for (
const auto& elt : mark)
1013 __computeMaxPrimeMergings(
1014 elt.first, elt.first, merged_cliques, mark, new_nodes_in_junction_tree);
1019 for (
unsigned int i = 0; i < merged_cliques.size(); ++i) {
1020 if (T_mpd_cliques.exists(merged_cliques[i].second))
1021 T_mpd_cliques[merged_cliques[i].first] =
1022 T_mpd_cliques[merged_cliques[i].second];
1024 T_mpd_cliques[merged_cliques[i].first] =
1025 __mps_of_clique[merged_cliques[i].second];
1032 NodeProperty< NodeId > clique2MPS(T_mpd_cliques.size());
1036 for (
const auto& elt : T_mpd_cliques)
1037 if (elt.first == elt.second) {
1038 NodeId newId = __T_mpd.addNode(__junction_tree.clique(elt.second));
1039 clique2MPS.insert(elt.second, newId);
1040 std::vector< NodeId >& vect_of_cliques =
1041 __cliques_of_mps.insert(newId, std::vector< NodeId >()).second;
1042 vect_of_cliques.push_back(elt.second);
1047 for (
const auto& elt : T_mpd_cliques)
1048 if ((elt.first != elt.second)
1049 && (new_nodes_in_junction_tree.contains(elt.second))) {
1050 const NodeId idMPS = clique2MPS[elt.second];
1052 for (
const auto node : __junction_tree.clique(elt.first)) {
1054 __T_mpd.addToClique(idMPS, node);
1055 }
catch (DuplicateElement&) {}
1058 __cliques_of_mps[idMPS].push_back(elt.first);
1062 for (
const auto& elt : T_mpd_cliques) {
1063 const NodeId idMPS = clique2MPS[elt.second];
1064 __mps_of_clique.insert(elt.first, idMPS);
1066 if (elt.first == elt.second)
1067 for (
const auto node : __T_mpd.clique(idMPS))
1068 __mps_of_node[node].insert(idMPS);
1072 for (
const auto& elt : T_mpd_cliques) {
1073 NodeId clique = clique2MPS[elt.second];
1075 for (
const auto othernode : __junction_tree.neighbours(elt.first))
1076 if (T_mpd_cliques.exists(othernode)) {
1079 NodeId otherClique = clique2MPS[T_mpd_cliques[othernode]];
1082 if (clique > otherClique) { __T_mpd.addEdge(clique, otherClique); }
1084 __T_mpd.addEdge(clique, __mps_of_clique[othernode]);
1092 if (!__require_update)
return;
1095 NodeProperty< bool > all_cliques_affected(__junction_tree.size());
1103 NodeSet new_nodes_in_junction_tree;
1105 __updateJunctionTree(all_cliques_affected, new_nodes_in_junction_tree);
1108 __updateMaxPrimeSubgraph(all_cliques_affected, new_nodes_in_junction_tree);
1111 __mps_affected.clear();
1113 for (
const auto node : __T_mpd.nodes())
1114 __mps_affected.insert(node,
false);
1117 __triangulation->clear();
1119 __require_update =
false;
1126 __domain_sizes.clear();
1127 __junction_tree.clear();
1129 __mps_of_node.clear();
1130 __cliques_of_mps.clear();
1131 __mps_of_clique.clear();
1132 __mps_affected.clear();
1133 __triangulation->clear();
1134 __require_update =
false;
1135 __require_elimination_order =
false;
1136 __elimination_order.clear();
1137 __reverse_elimination_order.clear();
1138 __require_created_JT_cliques =
false;
1139 __created_JT_cliques.clear();
1145 const NodeId clique,
const NodeId from, NodeProperty< bool >& examined) {
1147 for (
const auto otherclique : __junction_tree.neighbours(clique))
1148 if (otherclique != from) __collectJTCliques(otherclique, clique, examined);
1151 examined[clique] =
true;
1153 const NodeSet& cliquenodes = __junction_tree.clique(clique);
1155 if (from != clique) {
1156 const NodeSet& separator = __junction_tree.separator(clique, from);
1158 for (
const auto cli : cliquenodes)
1159 if (!separator.contains(cli)) __created_JT_cliques.
insert(cli, clique);
1161 for (
const auto cli : cliquenodes)
1162 __created_JT_cliques.insert(cli, clique);
1169 const NodeProperty< NodeId >&
1172 if (!__require_created_JT_cliques)
return __created_JT_cliques;
1175 updateTriangulation();
1177 __created_JT_cliques.clear();
1179 __require_created_JT_cliques =
false;
1181 if (__junction_tree.size() == 0) {
return __created_JT_cliques; }
1184 NodeProperty< bool > examined = __junction_tree.nodesProperty<
bool >(
false);
1186 for (
const auto& elt : examined)
1187 if (!elt.second) __collectJTCliques(elt.first, elt.first, examined);
1189 return __created_JT_cliques;
1195 createdJunctionTreeCliques();
1196 return __created_JT_cliques[id];
1204 return __mps_of_clique[createdJunctionTreeClique(
id)];
1210 const NodeProperty< Size >* dom_sizes) {
1213 if (((graph !=
nullptr) && (dom_sizes ==
nullptr))
1214 || ((graph ==
nullptr) && (dom_sizes !=
nullptr))) {
1216 "one of the graph or the set of domain sizes " 1217 "is a null pointer.");
1225 if (graph !=
nullptr) {
1226 for (
const auto node : *graph)
1227 addNode(node, (*dom_sizes)[node]);
1229 for (
const auto& edge : graph->edges())
1230 addEdge(edge.first(), edge.second());
1239 NodeProperty< bool >& examined,
1242 for (
const auto othernode : __junction_tree.neighbours(node))
1243 if (othernode != from)
1244 __collectEliminationOrder(othernode, node, examined, index);
1247 examined[node] =
true;
1249 const NodeSet& clique = __junction_tree.clique(node);
1252 const NodeSet& separator = __junction_tree.separator(node, from);
1254 for (
const auto cli : clique) {
1255 if (!separator.contains(cli)) {
1256 __elimination_order[index] = cli;
1257 __reverse_elimination_order.
insert(cli, index);
1262 for (
const auto cli : clique) {
1263 __elimination_order[index] = cli;
1264 __reverse_elimination_order.insert(cli, index);
1274 if (!__require_elimination_order)
return __elimination_order;
1277 updateTriangulation();
1279 __elimination_order.resize(__graph.size());
1281 __reverse_elimination_order.clear();
1283 __require_elimination_order =
false;
1285 if (__junction_tree.size() ==
Size(0)) {
return __elimination_order; }
1290 NodeProperty< bool > examined = __junction_tree.nodesProperty<
bool >(
false);
1292 for (
const auto& elt : examined)
1294 __collectEliminationOrder(elt.first, elt.first, examined, index);
1296 return __elimination_order;
1303 if (!__graph.existsNode(node)) {
1304 GUM_ERROR(NotFound,
"the node " << node <<
" does not exist");
1310 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)
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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...
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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