<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def build_to_target_size_from_token_counts(cls, target_size, token_counts, min_val, max_val, num_iterations=4):
 """Builds a SubwordTextTokenizer that has `vocab_size` near `target_size`. Uses simple recursive binary search to find a minimum token count that most closely matches the `target_size`. Args: target_size: Desired vocab_size to approximate. token_counts: A dictionary of token counts, mapping string to int. min_val: An integer; lower bound for the minimum token count. max_val: An integer; upper bound for the minimum token count. num_iterations: An integer; how many iterations of refinement. Returns: A SubwordTextTokenizer instance. Raises: ValueError: If `min_val` is greater than `max_val`. """

        if min_val > max_val:
            raise ValueError("Lower bound for the minimum token count "
                             "is greater than the upper bound.")

        def bisect(min_val, max_val):
            """Bisection to find the right size."""
            present_count = (max_val + min_val) // 2
            logger.info("Trying min_count %d" % present_count)
            subtokenizer = cls()
            subtokenizer.build_from_token_counts(token_counts, present_count, num_iterations)
            logger.info("min_count %d attained a %d vocab_size", present_count,
                        subtokenizer.vocab_size)

            # If min_val == max_val, we can't do any better than this.
            if subtokenizer.vocab_size == target_size or min_val >= max_val:
                return subtokenizer

            if subtokenizer.vocab_size > target_size:
                other_subtokenizer = bisect(present_count + 1, max_val)
            else:
                other_subtokenizer = bisect(min_val, present_count - 1)

            if other_subtokenizer is None:
                return subtokenizer

            if (abs(other_subtokenizer.vocab_size - target_size) <
                    abs(subtokenizer.vocab_size - target_size)):
                return other_subtokenizer
            return subtokenizer

        return bisect(min_val, max_val)