class_docstr: Base class for graphical representation of Structural Equation Models(SEMs).
  
  All variables are by default assumed to have an associated error latent variable, therefore
  doesn't need to be specified.
  
  Parameters
  ----------
  ebunch: list/array-like
      List of edges in form of tuples. Each tuple can be of two possible shape:
          1. (u, v): This would add an edge from u to v without setting any parameter
                     for the edge.
          2. (u, v, parameter): This would add an edge from u to v and set the edge's
                      parameter to `parameter`.
  
  latents: list/array-like
      List of nodes which are latent. All other variables are considered observed.
  
  err_corr: list/array-like
      List of tuples representing edges between error terms. It can be of the following forms:
          1. (u, v): Add correlation between error terms of `u` and `v`. Doesn't set any variance or
                     covariance values.
          2. (u, v, covar): Adds correlation between the error terms of `u` and `v` and sets the
                            parameter to `covar`.
  
  err_var: dict (variable: variance)
      Sets variance for the error terms in the model.
  
  Examples
  --------
  Defining a model (Union sentiment model[1]) without setting any paramaters.
  >>> from pgmpy.models import SEMGraph
  >>> sem = SEMGraph(ebunch=[('deferenc', 'unionsen'), ('laboract', 'unionsen'),
  ...                        ('yrsmill', 'unionsen'), ('age', 'deferenc'),
  ...                        ('age', 'laboract'), ('deferenc', 'laboract')],
  ...                latents=[],
  ...                err_corr=[('yrsmill', 'age')],
  ...                err_var={})
  
  Defining a model (Education [2]) with all the parameters set. For not setting any
  parameter `np.NaN` can be explicitly passed.
  >>> sem_edu = SEMGraph(ebunch=[('intelligence', 'academic', 0.8), ('intelligence', 'scale_1', 0.7),
  ...                            ('intelligence', 'scale_2', 0.64), ('intelligence', 'scale_3', 0.73),
  ...                            ('intelligence', 'scale_4', 0.82), ('academic', 'SAT_score', 0.98),
  ...                            ('academic', 'High_school_gpa', 0.75), ('academic', 'ACT_score', 0.87)],
  ...                    latents=['intelligence', 'academic'],
  ...                    err_corr=[],
  ...                    err_var={'intelligence': 1})
  
  References
  ----------
  [1] McDonald, A, J., & Clelland, D. A. (1984). Textile Workers and Union Sentiment.
      Social Forces, 63(2), 502–521
  [2] https://en.wikipedia.org/wiki/Structural_equation_modeling#/
      media/File:Example_Structural_equation_model.svg
  
  Attributes
  ----------
  latents: list
      List of all the latent variables in the model except the error terms.
  
  observed: list
      List of all the observed variables in the model.
  
  graph: nx.DirectedGraph
      The graphical structure of the latent and observed variables except the error terms.
      The parameters are stored in the `weight` attribute of each edge.
  
  err_graph: nx.Graph
      An undirected graph representing the relations between the error terms of the model.
      The node of the graph has the same name as the variable but represents the error terms.
      The variance is stored in the `weight` attribute of the node and the covariance are stored
      in the `weight` attribute of the edge.
  
  full_graph_struct: nx.DiGraph
      Represents the full graph structure. The names of error terms start with `.` and
      new nodes are added for each correlation which starts with `..`.
class_docstr_tok: ["Base","class","for","graphical","representation","of","Structural","Equation","Models","(","SEMs",")",".","All","variables","are","by","default","assumed","to","have","an","associated","error","latent","variable",",","therefore","does","n't","need","to","be","specified",".","Parameters","--","--","--","--","--","ebunch",":","list\/array-like","List","of","edges","in","form","of","tuples",".","Each","tuple","can","be","of","two","possible","shape",":","1",".","(","u",",","v",")",":","This","would","add","an","edge","from","u","to","v","without","setting","any","parameter","for","the","edge",".","2",".","(","u",",","v",",","parameter",")",":","This","would","add","an","edge","from","u","to","v","and","set","the","edge's","parameter","to","`","parameter","`",".","latents",":","list\/array-like","List","of","nodes","which","are","latent",".","All","other","variables","are","considered","observed",".","err_corr",":","list\/array-like","List","of","tuples","representing","edges","between","error","terms",".","It","can","be","of","the","following","forms",":","1",".","(","u",",","v",")",":","Add","correlation","between","error","terms","of","`","u","`","and","`","v","`",".","Does","n't","set","any","variance","or","covariance","values",".","2",".","(","u",",","v",",","covar",")",":","Adds","correlation","between","the","error","terms","of","`","u","`","and","`","v","`","and","sets","the","parameter","to","`","covar","`",".","err_var",":","dict","(","variable",":","variance",")","Sets","variance","for","the","error","terms","in","the","model",".","Examples","--","--","--","--","Defining","a","model","(","Union","sentiment","model","[","1","]",")","without","setting","any","paramaters",".",">",">",">","from","pgmpy.models","import","SEMGraph",">",">",">","sem","=","SEMGraph","(","ebunch=","[","(","'deferenc","'",",","'unionsen","'",")",",","(","'laboract","'",",","'unionsen","'",")",",","...","(","'yrsmill","'",",","'unionsen","'",")",",","(","'age","'",",","'deferenc","'",")",",","...","(","'age","'",",","'laboract","'",")",",","(","'deferenc","'",",","'laboract","'",")","]",",","...","latents=","[","]",",","...","err_corr=","[","(","'yrsmill","'",",","'age","'",")","]",",","...","err_var=","{","}",")","Defining","a","model","(","Education","[","2","]",")","with","all","the","parameters","set",".","For","not","setting","any","parameter","`","np.NaN","`","can","be","explicitly","passed",".",">",">",">","sem_edu","=","SEMGraph","(","ebunch=","[","(","'intelligence","'",",","'academic","'",",","0.8",")",",","(","'intelligence","'",",","'scale_1","'",",","0.7",")",",","...","(","'intelligence","'",",","'scale_2","'",",","0.64",")",",","(","'intelligence","'",",","'scale_3","'",",","0.73",")",",","...","(","'intelligence","'",",","'scale_4","'",",","0.82",")",",","(","'academic","'",",","'SAT_score","'",",","0.98",")",",","...","(","'academic","'",",","'High_school_gpa","'",",","0.75",")",",","(","'academic","'",",","'ACT_score","'",",","0.87",")","]",",","...","latents=","[","'intelligence","'",",","'academic","'","]",",","...","err_corr=","[","]",",","...","err_var=","{","'intelligence","'",":","1","}",")","References","--","--","--","--","--","[","1","]","McDonald",",","A",",","J.",",","&","Clelland",",","D.","A",".","(","1984",")",".","Textile","Workers","and","Union","Sentiment",".","Social","Forces",",","63","(","2",")",",","502\u2013521","[","2","]","https",":","\/\/en.wikipedia.org\/wiki\/Structural_equation_modeling","#","\/","media\/File",":","Example_Structural_equation_model.svg","Attributes","--","--","--","--","--","latents",":","list","List","of","all","the","latent","variables","in","the","model","except","the","error","terms",".","observed",":","list","List","of","all","the","observed","variables","in","the","model",".","graph",":","nx.DirectedGraph","The","graphical","structure","of","the","latent","and","observed","variables","except","the","error","terms",".","The","parameters","are","stored","in","the","`","weight","`","attribute","of","each","edge",".","err_graph",":","nx.Graph","An","undirected","graph","representing","the","relations","between","the","error","terms","of","the","model",".","The","node","of","the","graph","has","the","same","name","as","the","variable","but","represents","the","error","terms",".","The","variance","is","stored","in","the","`","weight","`","attribute","of","the","node","and","the","covariance","are","stored","in","the","`","weight","`","attribute","of","the","edge",".","full_graph_struct",":","nx.DiGraph","Represents","the","full","graph","structure",".","The","names","of","error","terms","start","with","`",".","`","and","new","nodes","are","added","for","each","correlation","which","starts","with","`","..","`","."]
docstr: Finds all the observed variables which are d-connected to `variables` in the `graph_struct`
  when `observed` variables are observed.
  
  Parameters
  ----------
  variables: str or array like
      Observed variables whose d-connected variables are to be found.
  
  observed : list/array-like
      If given the active trails would be computed assuming these nodes to be observed.
  
  avoid_nodes: list/array-like
      If specificed, the algorithm doesn't account for paths that have influence flowing
      through the avoid node.
  
  struct: str or nx.DiGraph instance
      If "full", considers correlation between error terms for computing d-connection.
      If "non_error", doesn't condised error correlations for computing d-connection.
      If instance of nx.DiGraph, finds d-connected variables on the given graph.
  
  Examples
  --------
  >>> from pgmpy.models import SEM
  >>> model = SEMGraph(ebunch=[('yrsmill', 'unionsen'), ('age', 'laboract'),
  ...                          ('age', 'deferenc'), ('deferenc', 'laboract'),
  ...                          ('deferenc', 'unionsen'), ('laboract', 'unionsen')],
  ...                  latents=[],
  ...                  err_corr=[('yrsmill', 'age')])
  >>> model.active_trail_nodes('age')
  
  Returns
  -------
  dict: {str: list}
      Returns a dict with `variables` as the key and a list of d-connected variables as the
      value.
  
  References
  ----------
  Details of the algorithm can be found in 'Probabilistic Graphical Model
  Principles and Techniques' - Koller and Friedman
  Page 75 Algorithm 3.1
docstr_tok: ["Finds","all","the","observed","variables","which","are","d-connected","to","`","variables","`","in","the","`","graph_struct","`","when","`","observed","`","variables","are","observed",".","Parameters","--","--","--","--","--","variables",":","str","or","array","like","Observed","variables","whose","d-connected","variables","are","to","be","found",".","observed",":","list\/array-like","If","given","the","active","trails","would","be","computed","assuming","these","nodes","to","be","observed",".","avoid_nodes",":","list\/array-like","If","specificed",",","the","algorithm","does","n't","account","for","paths","that","have","influence","flowing","through","the","avoid","node",".","struct",":","str","or","nx.DiGraph","instance","If","``","full","''",",","considers","correlation","between","error","terms","for","computing","d-connection",".","If","``","non_error","''",",","does","n't","condised","error","correlations","for","computing","d-connection",".","If","instance","of","nx.DiGraph",",","finds","d-connected","variables","on","the","given","graph",".","Examples","--","--","--","--",">",">",">","from","pgmpy.models","import","SEM",">",">",">","model","=","SEMGraph","(","ebunch=","[","(","'yrsmill","'",",","'unionsen","'",")",",","(","'age","'",",","'laboract","'",")",",","...","(","'age","'",",","'deferenc","'",")",",","(","'deferenc","'",",","'laboract","'",")",",","...","(","'deferenc","'",",","'unionsen","'",")",",","(","'laboract","'",",","'unionsen","'",")","]",",","...","latents=","[","]",",","...","err_corr=","[","(","'yrsmill","'",",","'age","'",")","]",")",">",">",">","model.active_trail_nodes","(","'age","'",")","Returns","--","--","--","-","dict",":","{","str",":","list","}","Returns","a","dict","with","`","variables","`","as","the","key","and","a","list","of","d-connected","variables","as","the","value",".","References","--","--","--","--","--","Details","of","the","algorithm","can","be","found","in","'Probabilistic","Graphical","Model","Principles","and","Techniques","'","-","Koller","and","Friedman","Page","75","Algorithm","3.1"]
code: def active_trail_nodes(
      self, variables, observed=[], avoid_nodes=[], struct="full"
  ):
      """
      Finds all the observed variables which are d-connected to `variables` in the `graph_struct`
      when `observed` variables are observed.
  
      Parameters
      ----------
      variables: str or array like
          Observed variables whose d-connected variables are to be found.
  
      observed : list/array-like
          If given the active trails would be computed assuming these nodes to be observed.
  
      avoid_nodes: list/array-like
          If specificed, the algorithm doesn't account for paths that have influence flowing
          through the avoid node.
  
      struct: str or nx.DiGraph instance
          If "full", considers correlation between error terms for computing d-connection.
          If "non_error", doesn't condised error correlations for computing d-connection.
          If instance of nx.DiGraph, finds d-connected variables on the given graph.
  
      Examples
      --------
      >>> from pgmpy.models import SEM
      >>> model = SEMGraph(ebunch=[('yrsmill', 'unionsen'), ('age', 'laboract'),
      ...                          ('age', 'deferenc'), ('deferenc', 'laboract'),
      ...                          ('deferenc', 'unionsen'), ('laboract', 'unionsen')],
      ...                  latents=[],
      ...                  err_corr=[('yrsmill', 'age')])
      >>> model.active_trail_nodes('age')
  
      Returns
      -------
      dict: {str: list}
          Returns a dict with `variables` as the key and a list of d-connected variables as the
          value.
  
      References
      ----------
      Details of the algorithm can be found in 'Probabilistic Graphical Model
      Principles and Techniques' - Koller and Friedman
      Page 75 Algorithm 3.1
      """
      if struct == "full":
          graph_struct = self.full_graph_struct
      elif struct == "non_error":
          graph_struct = self.graph
      elif isinstance(struct, nx.DiGraph):
          graph_struct = struct
      else:
          raise ValueError(
              f"Expected struct to be str or nx.DiGraph. Got {type(struct)}"
          )
  
      ancestors_list = set()
      for node in observed:
          ancestors_list = ancestors_list.union(
              nx.algorithms.dag.ancestors(graph_struct, node)
          )
  
      # Direction of flow of information
      # up ->  from parent to child
      # down -> from child to parent
  
      active_trails = {}
      for start in (
          variables
          if isinstance(variables, (list, tuple))
          else [variables]
      ):
          visit_list = set()
          visit_list.add((start, "up"))
          traversed_list = set()
          active_nodes = set()
          while visit_list:
              node, direction = visit_list.pop()
              if node in avoid_nodes:
                  continue
              if (node, direction) not in traversed_list:
                  if (
                      (node not in observed)
                      and (not node.startswith("."))
                      and (node not in self.latents)
                  ):
                      active_nodes.add(node)
                  traversed_list.add((node, direction))
                  if direction == "up" and node not in observed:
                      for parent in graph_struct.predecessors(node):
                          visit_list.add((parent, "up"))
                      for child in graph_struct.successors(node):
                          visit_list.add((child, "down"))
                  elif direction == "down":
                      if node not in observed:
                          for child in graph_struct.successors(node):
                              visit_list.add((child, "down"))
                      if node in ancestors_list:
                          for parent in graph_struct.predecessors(node):
                              visit_list.add((parent, "up"))
          active_trails[start] = active_nodes
      return active_trails
  
imports: import itertools
  import networkx
  import numpy
  import pandas
  from networkx.algorithms.dag import descendants
  from pyparsing import OneOrMore, Optional, Suppress, Word, alphanums, nums
  from pgmpy.base import DAG
  from pgmpy.global_vars import logger
label_desc: Use image node_id 4 for calling the SEMGraph obj's underlying member method code with example usage: obj.active_trail_nodes(variables, observed, avoid_nodes, struct) and returns: active_trails