def is_stable_or_dead(protocol, valuation, disabled):
    # Dead?
    dead = True

    for t in protocol.transitions:
        p, q = tuple(t.pre)

        if (not t.silent() and (t.pre not in disabled)
                and (valuation[Var(p)] is not False)
                and (valuation[Var(q)] is not False)):
            dead = False
            break

    if dead:
        return True

    # Stable?
    V = protocol.states - valuation.absent_states()
    out = {protocol.output(q) for q in V}

    if len(out) > 1:
        return False
    else:
        x = out.pop()
        R = set()

        for t in protocol.transitions:
            for q in t.post:
                if protocol.output(q) != x:
                    R.add(t.pre)

        formula = Formula(valuation, disabled)

        return formula.implies_all_absent_tautology_check(R)
def is_very_fast(protocol, valuation, disabled):
    graph, vertices, edges = transformation_graph(protocol, valuation,
                                                  disabled)
    components, _, is_bottom = label_components(graph, attractors=True)

    U = {q for q in vertices if not is_bottom[components[vertices[q]]]}
    formula = Formula(valuation, disabled)

    for t in protocol.transitions:
        p, q = tuple(t.pre)
        p_, q_ = tuple(t.post)

        if (p in vertices and q in vertices and p_ in vertices
                and q_ in vertices and len({p, q, p_, q_} & U) > 0):
            if ((components[vertices[p]] != components[vertices[p_]])
                    and (components[vertices[p]] != components[vertices[q_]])
                    and (components[vertices[q]] != components[vertices[p_]])
                    and (components[vertices[q]] != components[vertices[q_]])):
                continue
            elif formula.implies_all_absent_tautology_check({t.pre}):
                continue
            else:
                return False

    return True