Repository: microsoft/RD-Agent
File: rdagent/scenarios/data_science/proposal/exp_gen/base.py (Python)

Code before:
    ) -> list[tuple[DSExperiment, ExperimentFeedback]]:
        """
        Retrieve the search list based on the selection and search_type.

        Parameters
        ----------
        search_type : str
            One of "all", "ancestors".
            - "all": search the whole hist.
            - "ancestors": search the trace from root to the selection.

        Returns
        -------
        list[tuple[DSExperiment, ExperimentFeedback]]
            The search list.
        """
        if search_type == "all":
            return self.hist

        elif search_type == "ancestors":
            return self.get_parent_exps(selection)

        else:
            raise ValueError(f"Invalid search type: {search_type}")

    def collect_all_ancestors(
        self,
        selection: tuple[int, ...] | None = None,
    ) -> list[tuple[DSExperiment, ExperimentFeedback]]:
        """
        Collect all ancestors of the given selection.
        The return list follows the order of [root->...->parent->current_node].
        """
        if selection is None:
            selection = self.get_current_selection()

        if len(self.dag_parent) == 0:
            return []

        elif len(selection) == 0:
            return []

        else:
            all_ancestors = []

            # start from the latest selection
            current_node_idx = selection[0]

            # add the current node to the list
            all_ancestors.insert(0, self.hist[current_node_idx])


Review comment (suggestion):
You can create a function like this
https://github.com/microsoft/RD-Agent/blob/main/rdagent/core/proposal.py#L145 

For example,  `get_parent_exp_fbs`

Code after:
    ) -> list[tuple[DSExperiment, ExperimentFeedback]]:
        """
        Retrieve the search list based on the selection and search_type.

        Parameters
        ----------
        search_type : str
            One of "all", "ancestors".
            - "all": search the whole hist.
            - "ancestors": search the trace from root to the selection.

        Returns
        -------
        list[tuple[DSExperiment, ExperimentFeedback]]
            The search list.
        """
        if search_type == "all":
            return self.hist

        elif search_type == "ancestors":
            return self.get_parent_exps(selection)

        else:
            raise ValueError(f"Invalid search type: {search_type}")

    def next_incomplete_component(
        self,
        search_type: Literal["all", "ancestors"] = "ancestors",
    ) -> COMPONENT | None:
        """
        NOTE:
        - A component will be complete until get True decision feedback !!!

        """
        search_list = self.retrieve_search_list(search_type)

        for c in self.COMPLETE_ORDER:
            """Check if the component is in the ancestors of the selection."""
            if not self.has_component(c, search_list):
                return c

        return None

    def has_component(
        self, component: COMPONENT, search_list: list[tuple[DSExperiment, ExperimentFeedback]] = []
    ) -> bool:
        for exp, fb in search_list:
            assert isinstance(exp.hypothesis, DSHypothesis), "Hypothesis should be DSHypothesis (and not None)"
            if exp.hypothesis.component == component and fb:
                return True
        return False