def initialize(
        self,
        space_config: dict[str, list[dict[str, "SearchParameter"]]],
        init_model_id: str,
        objectives: dict[str, dict[str, dict[str, Any]]],
    ):
        """Initialize the search strategy.

        space_config: Ordered dictionary of format {pass_name, [{param_name: SearchParameter}]}
        init_model_id: Input model id to use to start searching.
        objectives: dictionary of format
                    {pass_name: {objective_name: {"higher_is_better": bool, "goal": float, "priority": int}}}

        Depending on the execution order, we could generate either a single search space (for joint mode)
        or multiple search spaces (for pass-by-pass mode). However, the logic in how we process these
        search spaces does not differ.
        """
        # for the fist search group, init_model_id must be provided
        if not init_model_id:
            raise ValueError("init_model_id must be provided for search")

        if self.config.execution_order == SearchStrategyExecutionOrder.JOINT:
            self._search_spaces = [
                SearchSpace(
                    [
                        (pass_name, Categorical([SearchSpace(list(params.items())) for params in passes]))
                        for pass_name, passes in space_config.items()
                    ]
                )
            ]
        elif self.config.execution_order == SearchStrategyExecutionOrder.PASS_BY_PASS:
            self._search_spaces = [
                SearchSpace([(pass_name, Categorical([SearchSpace(list(params.items())) for params in passes]))])
                for pass_name, passes in space_config.items()
            ]
        else:
            raise ValueError(f"Unsupported execution order: {self.config.execution_order}")

        objectives = objectives or {}
        self._objectives = {pass_name: objectives.get(pass_name) or {} for pass_name in space_config}
        self._init_model_id = init_model_id

        # Note that the state variables will be initialized at start of iteration.
        self._initialized = True
Initialize the search strategy.

        space_config: Ordered dictionary of format {pass_name, [{param_name: SearchParameter}]}
        init_model_id: Input model id to use to start searching.
        objectives: dictionary of format
                    {pass_name: {objective_name: {"higher_is_better": bool, "goal": float, "priority": int}}}

        Depending on the execution order, we could generate either a single search space (for joint mode)
        or multiple search spaces (for pass-by-pass mode). However, the logic in how we process these
        search spaces does not differ.
        
olive/search/search_strategy.py