docs: def pdag_to_dag(pdag):
          """Completes a PDAG to a DAG, without adding v-structures, if such a
          completion exists. If no faithful extension is possible, some fully
          oriented DAG that corresponds to the PDAG is returned and a warning is
          generated. This is a static method.
  
          Parameters
          ----------
          pdag: DAG
              A directed acyclic graph pattern, consisting in (acyclic) directed edges
              as well as "undirected" edges, represented as both-way edges between
              nodes.
  
          Returns
          -------
          dag: DAG
              A faithful orientation of pdag, if one exists. Otherwise any
              fully orientated DAG/BayesianModel with the structure of pdag.
  
          References
          ----------
          [1] Chickering, Learning Equivalence Classes of Bayesian-Network Structures,
              2002; See page 454 (last paragraph) for the algorithm pdag_to_dag
              http://www.jmlr.org/papers/volume2/chickering02a/chickering02a.pdf
          [2] Dor & Tarsi, A simple algorithm to construct a consistent extension
              of a partially oriented graph, 1992,
              http://ftp.cs.ucla.edu/pub/stat_ser/r185-dor-tarsi.pdf
  
          Examples
          --------
          >>> import pandas as pd
          >>> import numpy as np
          >>> from pgmpy.base import DAG
          >>> from pgmpy.estimators import ConstraintBasedEstimator
          >>> data = pd.DataFrame(np.random.randint(0, 4, size=(5000, 3)), columns=list('ABD'))
          >>> data['C'] = data['A'] - data['B']
          >>> data['D'] += data['A']
          >>> c = ConstraintBasedEstimator(data)
          >>> pdag = c.skeleton_to_pdag(*c.estimate_skeleton())
          >>> pdag.edges()
          [('B', 'C'), ('D', 'A'), ('A', 'D'), ('A', 'C')]
          >>> c.pdag_to_dag(pdag).edges()
          [('B', 'C'), ('A', 'D'), ('A', 'C')]
  
          >>> # pdag_to_dag is static:
          ... pdag1 = DAG([('A', 'B'), ('C', 'B'), ('C', 'D'), ('D', 'C'), ('D', 'A'), ('A', 'D')])
          >>> ConstraintBasedEstimator.pdag_to_dag(pdag1).edges()
          [('D', 'C'), ('C', 'B'), ('A', 'B'), ('A', 'D')]
  
          >>> # example of a pdag with no faithful extension:
          ... pdag2 = DAG([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'B')])
          >>> ConstraintBasedEstimator.pdag_to_dag(pdag2).edges()
          UserWarning: PDAG has no faithful extension (= no oriented DAG with the same v-structures as PDAG).
          Remaining undirected PDAG edges oriented arbitrarily.
          [('B', 'C'), ('A', 'B'), ('A', 'C')]
          """
  
          pdag = pdag.copy()
          dag = DAG()
          dag.add_nodes_from(pdag.nodes())
  
          # add already directed edges of pdag to dag
          for X, Y in pdag.edges():
              if not pdag.has_edge(Y, X):
                  dag.add_edge(X, Y)
  
          while pdag.number_of_nodes() > 0:
              # find node with (1) no directed outgoing edges and
              #                (2) the set of undirected neighbors is either empty or
              #                    undirected neighbors + parents of X are a clique
              found = False
              for X in pdag.nodes():
                  directed_outgoing_edges = set(pdag.successors(X)) - set(pdag.predecessors(X))
                  undirected_neighbors = set(pdag.successors(X)) & set(pdag.predecessors(X))
                  neighbors_are_clique = all((pdag.has_edge(Y, Z)
                                              for Z in pdag.predecessors(X)
                                              for Y in undirected_neighbors if not Y == Z))
  
                  if not directed_outgoing_edges and \
                          (not undirected_neighbors or neighbors_are_clique):
                      found = True
                      # add all edges of X as outgoing edges to dag
                      for Y in pdag.predecessors(X):
                          dag.add_edge(Y, X)
  
                      pdag.remove_node(X)
                      break
  
              if not found:
                  warn("PDAG has no faithful extension (= no oriented DAG with the " +
                       "same v-structures as PDAG). Remaining undirected PDAG edges " +
                       "oriented arbitrarily.")
                  for X, Y in pdag.edges():
                      if not dag.has_edge(Y, X):
                          try:
                              dag.add_edge(X, Y)
                          except ValueError:
                              pass
                  break
  
          return dag