80 for (
auto node:
graph) {
84 pdag.
addEdge(edge.first(), edge.second());
87 pdag.
addArc(arc.tail(), arc.head());
106 for (
auto node:
graph.nodes()) {
109 for (
const Arc& arc:
graph.arcs()) {
110 dag.
addArc(arc.tail(), arc.head());
134 bool withdrawFlag_L =
false;
135 for (
auto& arc:
ArcSet(L)) {
138 bool withdrawFlag_arc =
false;
141 if (tail_head && !head_tail) {
144 withdrawFlag_arc =
true;
147 }
else if (!tail_head && head_tail) {
150 withdrawFlag_arc =
true;
153 }
else if (!tail_head && !head_tail) {
157 withdrawFlag_arc =
true;
161 if (withdrawFlag_arc) {
163 withdrawFlag_L =
true;
167 if (L.
empty()) {
break; }
172 if (!withdrawFlag_L) {
186 bool newOrientation =
true;
187 while (newOrientation) {
188 newOrientation =
false;
198 bool newOrientation =
true;
199 while (newOrientation) {
200 newOrientation =
false;
214 const auto neighbours =
graph.neighbours(xj);
215 for (
auto& xi: neighbours) {
224 graph.addArc(xi, xj);
228 graph.addArc(xj, xi);
243 if (
graph.parents(x).size() <
graph.parents(y).size()) {
247 }
else if (
graph.parents(x).size() >
graph.parents(y).size()) {
250 if (
graph.neighbours(x).size() <
graph.neighbours(y).size()) {
265 if (!(
graph.parents(xi) -
graph.boundary(xj)).empty()) {
277 std::vector< NodeId > qualifying;
278 for (
const auto p:
graph.parents(xj)) {
279 if (
graph.neighbours(xi).contains(p)) { qualifying.push_back(p); }
281 for (std::size_t i = 0; i < qualifying.size(); ++i)
282 for (std::size_t j = i + 1; j < qualifying.size(); ++j)
283 if (!
graph.boundary(qualifying[i]).contains(qualifying[j])) {
290 for (
const auto xk:
graph.neighbours(xj)) {
291 if (
graph.boundary(xi).contains(xk))
continue;
292 if (
graph.existsArc(xi, xk) ||
graph.existsArc(xk, xi))
continue;
305 const auto& edge = *(essentialGraph.
edges().begin());
306 NodeId root = edge.first();
312 while (!stack.
empty()) {
315 if (visited.
contains(next))
continue;
316 if (essentialGraph.
children(next).
size() > size_children_root) {
317 size_children_root = essentialGraph.
children(next).
size();
320 for (
const auto n: essentialGraph.
neighbours(next))
329 while (!stack.
empty()) {
334 if (visited.
contains(next))
continue;
335 const auto nei = essentialGraph.
neighbours(next);
336 for (
const auto n: nei) {
343 if (!essentialGraph.
existsArc(next, n)) {
346 essentialGraph.
addArc(n, next);
350 essentialGraph.
addArc(next, n);
372 while (!nodeFIFO.
empty()) {
373 current = nodeFIFO.
front();
377 for (
const auto new_one:
graph.parents(current)) {
378 if (
graph.existsArc(current,
382 if (new_one == n1) {
return true; }
Meek rules for orienting edges in a mixed graph.
Inline implementations of MeekRules.
bool existsArc(const Arc &arc) const
indicates whether a given arc exists
const NodeSet & parents(NodeId id) const
returns the set of nodes with arc ingoing to a given node
NodeSet children(const NodeSet &ids) const
returns the set of nodes which consists in the node and its parents returns the set of children of a ...
virtual void eraseArc(const Arc &arc)
removes an arc from the ArcGraphPart
The base class for all directed edges.
void addArc(NodeId tail, NodeId head) final
insert a new arc into the directed graph
void addArc(const NodeId tail, const NodeId head) override
insert a new arc into the directed graph
virtual void eraseEdge(const Edge &edge)
removes an edge from the EdgeGraphPart
const EdgeSet & edges() const
returns the set of edges stored within the EdgeGraphPart
const NodeSet & neighbours(NodeId id) const
returns the set of node neighbours to a given node
The base class for all undirected edges.
Generic doubly linked lists.
Val & front() const
Returns a reference to first element of a list, if any.
Val & pushBack(const Val &val)
Inserts a new element (a copy) at the end of the chained list.
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
void popFront()
Removes the first element of a List, if any.
MixedGraph _propagates_(const MixedGraph &graph)
Applies Meek rules R1–R4 exhaustively and returns the resulting graph.
PDAG propagateToCPDAG(const MixedGraph &mg)
Applies Meek rules and returns a CPDAG (completed PDAG).
static bool _isOrientable_(const MixedGraph &graph, NodeId xi, NodeId xj)
Returns true if the edge xi–xj can be oriented as xi→xj under Meek rules R1–R3.
MixedGraph propagate(const MixedGraph &mg)
Applies Meek rules to a MixedGraph and returns the partially oriented result.
std::vector< Arc > _choices_
static bool _existsDirectedPath_(const MixedGraph &graph, NodeId n1, NodeId n2)
Returns true if there is a directed path from n1 to n2 (BFS, double arcs ignored).
bool _applyMeekRules_(MixedGraph &graph, NodeId xj)
Tries to orient edges incident to xj using Meek rules R1–R4.
static Arc _selectArcToEraseByMinParents_(const MixedGraph &graph, NodeId x, NodeId y)
Returns the arc to erase when resolving a double-headed arc, using a min-parents heuristic.
virtual ~MeekRules()
destructor
void _complete_(MixedGraph &graph)
Orients all remaining undirected edges, applying Meek rules then a chain heuristic.
static void _orientDoubleHeadedArcs_(MixedGraph &mg)
Resolves double-headed arcs (x→y and y→x simultaneously) to avoid cycles.
DAG propagateToDAG(const MixedGraph &mg)
Applies Meek rules and completes the result into a DAG.
void _propagatesOrientationInChainOfRemainingEdges_(MixedGraph &graph)
Arbitrarily orients remaining undirected edges when no Meek rule applies.
MeekRules()
default constructor
Base class for mixed graphs.
const NodeGraphPart & nodes() const
return *this as a NodeGraphPart
virtual void addNodeWithId(const NodeId id)
try to insert a node with the given id
Base class for partially directed acyclic graphs.
void addEdge(NodeId first, NodeId second) final
insert a new edge into the partially directed graph
void addArc(NodeId tail, NodeId head) final
insert a new arc into the directed graph
bool contains(const Key &k) const
Indicates whether a given elements belong to the set.
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
void clear()
Removes all the elements, if any, from the set.
bool empty() const noexcept
Indicates whether the set is the empty set.
iterator begin() const
The usual unsafe begin iterator to parse the set.
void insert(const Key &k)
Inserts a new element into the set.
void erase(const Key &k)
Erases an element from the set.
Size size() const noexcept
Returns the number of elements in the set.
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Size NodeId
Type for node ids.
Set< Arc > ArcSet
Some typdefs and define for shortcuts ...
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
gum is the global namespace for all aGrUM entities