def trace_distance_bound(val: Any) -> float:
    """Returns a maximum on the trace distance between this effect's input
    and output.

    This method attempts a number of strategies to calculate this value.

    Strategy 1:
        Use the effect's `_trace_distance_bound_` method.

    Strategy 2:
        If the effect is unitary, calculate the trace distance bound from the
        eigenvalues of the unitary matrix.

    Args:
        val: The effect of which the bound should be calculated

    Returns:
        If any of the strategies return a result that is not Notimplemented and
        not None, that result is returned. Otherwise, 1.0 is returned.
        Result is capped at a maximum of 1.0, even if the underlying function
        produces a result greater than 1.0

    """
    strats = [_strat_from_trace_distance_bound_method, _strat_distance_from_unitary]

    for strat in strats:
        result = strat(val)
        if result is None:
            break
        if result is not NotImplemented:
            return result

    return 1.0
Returns a maximum on the trace distance between this effect's input
    and output.

    This method attempts a number of strategies to calculate this value.

    Strategy 1:
        Use the effect's `_trace_distance_bound_` method.

    Strategy 2:
        If the effect is unitary, calculate the trace distance bound from the
        eigenvalues of the unitary matrix.

    Args:
        val: The effect of which the bound should be calculated

    Returns:
        If any of the strategies return a result that is not Notimplemented and
        not None, that result is returned. Otherwise, 1.0 is returned.
        Result is capped at a maximum of 1.0, even if the underlying function
        produces a result greater than 1.0

    
cirq-core/cirq/protocols/trace_distance_bound.py