code: def identify_effect_id(
      graph: nx.DiGraph,
      action_nodes: Union[str, List[str]],
      outcome_nodes: Union[str, List[str]],
  ) -> IDExpression:
      """
      Implementation of the ID algorithm.
      Link - https://ftp.cs.ucla.edu/pub/stat_ser/shpitser-thesis.pdf
      The pseudo code has been provided on Pg 40.
  
      :param treatment_names: OrderedSet comprising names of treatment variables.
      :param outcome_names:OrderedSet comprising names of outcome variables.
  
      :returns: target estimand, an instance of the IDExpression class.
      """
      node_names = OrderedSet(graph.nodes)
  
      adjacency_matrix = np.asmatrix(get_adjacency_matrix(graph))
  
      try:
          tsort_node_names = OrderedSet(
              list(nx.topological_sort(graph))
          )  # topological sorting of graph nodes
      except:
          raise Exception(
              "The graph must be a directed acyclic graph (DAG)."
          )
  
      return __adjacency_matrix_identify_effect(
          adjacency_matrix,
          OrderedSet(parse_state(action_nodes)),
          OrderedSet(parse_state(outcome_nodes)),
          tsort_node_names,
          node_names,
      )
  
file_path: dowhy/dowhy/causal_identifier/id_identifier.py
imports: from typing import Dict, List, Optional, Set, Union
  import networkx
  import numpy
  from dowhy.graph import get_adjacency_matrix
  from dowhy.utils.api import parse_state
  from dowhy.utils.graph_operations import find_ancestor, find_c_components, induced_graph
  from dowhy.utils.ordered_set import OrderedSet
label_desc: Use image node_id 1 for calling a global function with example usage: identify_effect_id(graph, action_nodes, outcome_nodes) and returns: __adjacency_matrix_identify_effect