def _check_execution_providers(self):
        """Check the execution providers are supported by the device and remove the unsupported ones.

        If the skip_supported_eps_check is True, the check will be skipped and the accelerators will be filtered against
        the device.
        """
        # check the execution providers are supported
        # TODO(myguo): should we cleanup the EPs if ep is not used?
        ep_not_supported = []
        for accelerator in self.system_config.config.accelerators:
            device = Device(accelerator.device.lower())
            eps_per_device = AcceleratorLookup.get_managed_supported_execution_providers(device)

            if self.system_config.olive_managed_env:
                available_eps = eps_per_device
            elif (
                self.system_config.type in (SystemType.Local, SystemType.PythonEnvironment, SystemType.IsolatedORT)
                and not self.skip_supported_eps_check
            ):
                # skip_supported_eps_check is False here
                # target is used so we need to check that the system supported eps are compatible with the accelerators
                available_eps = self.system_supported_eps
            else:
                # AzureML and Docker system: These are required to be specified by the user.
                # Local, PythonEnvironment, IsolatedORT: skip_supported_eps_check is True
                # the target is not used so no need to check the compatibility between the system supported eps and
                # the accelerators (available_eps == accelerator.execution_providers, the check will always pass)
                # Example scenario: to run optimization workflow for qnn-ep on x86 machine, the pass (onnxquantization)
                # needs to know qnn-ep is the target ep, but ort-qnn is not available on x86 machine.
                # we can still run the workflow using cpu ORT package as the target is not used for evaluation or
                # pass runs (= no inference sesion is created). The ort tools don't need the ep to be available.
                eps = AcceleratorLookup.filter_execution_providers(accelerator.execution_providers, eps_per_device)
                available_eps = eps or ["CPUExecutionProvider"]

            supported_eps = AcceleratorLookup.get_execution_providers_for_device_by_available_providers(
                device, available_eps
            )
            logger.debug("Supported execution providers for device %s: %s", device, supported_eps)

            eps = []
            for ep in accelerator.execution_providers:
                if ep not in supported_eps:
                    ep_not_supported.append(ep)
                else:
                    eps.append(ep)

            # remove the unsupported execution providers
            if not self.skip_supported_eps_check and not eps:
                raise ValueError(
                    f"None of the execution providers {accelerator.execution_providers} cannot be found in the target"
                    " system but at least one is required to run the workflow."
                )
            accelerator.execution_providers = eps or ["CPUExecutionProvider"]

        if ep_not_supported:
            logger.warning(
                "The following execution providers are not supported: '%s' by the device: '%s' and will be ignored. "
                "Please consider installing an onnxruntime build that contains the relevant execution providers. ",
                ",".join(ep_not_supported),
                ",".join([accelerator.device for accelerator in self.system_config.config.accelerators]),
            )
Check the execution providers are supported by the device and remove the unsupported ones.

        If the skip_supported_eps_check is True, the check will be skipped and the accelerators will be filtered against
        the device.
        
olive/systems/accelerator_creator.py