class_docstr: Implements methods for finding optimal (efficient) backdoor sets.
class_docstr_tok: ["Implements","methods","for","finding","optimal","(","efficient",")","backdoor","sets","."]
docstr: Returns the optimal adjustment set with respect to treatment,
  outcome, conditional and observable variables.
  
  If the sufficient conditions for the existence of the optimal adjustment
  set outlined in Smucler, Sapienza and Rotnitzky (2021), Biometrika, do
  not hold, an error is raised.
  
  :returns: optimal: set
      The optimal adjustment set.
docstr_tok: ["Returns","the","optimal","adjustment","set","with","respect","to","treatment",",","outcome",",","conditional","and","observable","variables",".","If","the","sufficient","conditions","for","the","existence","of","the","optimal","adjustment","set","outlined","in","Smucler",",","Sapienza","and","Rotnitzky","(","2021",")",",","Biometrika",",","do","not","hold",",","an","error","is","raised",".",":","returns",":","optimal",":","set","The","optimal","adjustment","set","."]
code: def optimal_adj_set(self):
      """Returns the optimal adjustment set with respect to treatment,
      outcome, conditional and observable variables.
  
      If the sufficient conditions for the existence of the optimal adjustment
      set outlined in Smucler, Sapienza and Rotnitzky (2021), Biometrika, do
      not hold, an error is raised.
  
      :returns: optimal: set
          The optimal adjustment set.
      """
      H1 = self.build_H1()
      if self.treatment_name in H1.neighbors(self.outcome_name):
          raise ValueError(EXCEPTION_NO_ADJ)
      elif self.observed_nodes == set(
          self.graph.nodes()
      ) or self.observed_nodes.issubset(
          self.ancestors_all(
              self.conditional_node_names
              + [self.treatment_name, self.outcome_name]
          )
      ):
          optimal = nx.node_boundary(H1, {self.outcome_name})
          return optimal
      else:
          raise ValueError(EXCEPTION_COND_NO_OPT)
  
file_path: dowhy/dowhy/causal_identifier/efficient_backdoor.py
imports: from typing import List
  import networkx
  import numpy
label_desc: Use image node_id 13 for calling the EfficientBackdoor obj's underlying member method code with example usage: obj.optimal_adj_set() and returns: optimal