def identify_backdoor()

in dowhy/causal_identifier.py [0:0]


    def identify_backdoor(self, treatment_name, outcome_name,
            include_unobserved=False, dseparation_algo="default"):
        backdoor_sets = []
        backdoor_paths = None
        bdoor_graph = None
        if dseparation_algo == "naive":
            backdoor_paths = self._graph.get_backdoor_paths(treatment_name, outcome_name)
        elif dseparation_algo == "default":
            bdoor_graph = self._graph.do_surgery(treatment_name,
                    remove_outgoing_edges=True)
        else:
            raise ValueError(f"d-separation algorithm {dseparation_algo} is not supported")
        method_name = self.method_name if self.method_name != CausalIdentifier.BACKDOOR_DEFAULT else CausalIdentifier.DEFAULT_BACKDOOR_METHOD

        # First, checking if empty set is a valid backdoor set
        empty_set = set()
        check = self._graph.check_valid_backdoor_set(treatment_name,
                outcome_name, empty_set,
                backdoor_paths=backdoor_paths, new_graph=bdoor_graph,
                dseparation_algo=dseparation_algo)
        if check["is_dseparated"]:
            backdoor_sets.append({'backdoor_set':empty_set})
            # If the method is `minimal-adjustment`, return the empty set right away.
            if method_name == CausalIdentifier.BACKDOOR_MIN:
                return backdoor_sets

        # Second, checking for all other sets of variables. If include_unobserved is false, then only observed variables are eligible.
        eligible_variables = self._graph.get_all_nodes(include_unobserved=include_unobserved) \
            - set(treatment_name) \
            - set(outcome_name)
        eligible_variables -= self._graph.get_descendants(treatment_name)
        # If var is d-separated from both treatment or outcome, it cannot
        # be a part of the backdoor set
        filt_eligible_variables = set()
        for var in eligible_variables:
            dsep_treat_var = self._graph.check_dseparation(
                    treatment_name, parse_state(var),
                    set())
            dsep_outcome_var = self._graph.check_dseparation(
                    outcome_name, parse_state(var), set())
            if not dsep_outcome_var or not dsep_treat_var:
                filt_eligible_variables.add(var)
        if method_name in CausalIdentifier.METHOD_NAMES:
            backdoor_sets, found_valid_adjustment_set = self.find_valid_adjustment_sets(
                    treatment_name, outcome_name,
                    backdoor_paths, bdoor_graph,
                    dseparation_algo,
                    backdoor_sets, filt_eligible_variables,
                    method_name=method_name,
                    max_iterations= CausalIdentifier.MAX_BACKDOOR_ITERATIONS)
            if method_name == CausalIdentifier.BACKDOOR_DEFAULT and found_valid_adjustment_set:
                # repeat the above search with BACKDOOR_MIN
                backdoor_sets, _ = self.find_valid_adjustment_sets(
                        treatment_name, outcome_name,
                        backdoor_paths, bdoor_graph,
                        dseparation_algo,
                        backdoor_sets, filt_eligible_variables,
                        method_name=CausalIdentifier.BACKDOOR_MIN,
                        max_iterations= CausalIdentifier.MAX_BACKDOOR_ITERATIONS)
        else:
            raise ValueError(f"Identifier method {method_name} not supported. Try one of the following: {CausalIdentifier.METHOD_NAMES}")
        return backdoor_sets