Esempio n. 1
0
def intersect_dfa(D1in, D2in):
    """In : D1in (consistent DFA)
            D2in (consistent DFA)
       Out: DFA for language intersection of D1in, D2in (consistent DFA). 
    """
    assert (is_consistent_dfa(D1in)), "Inconsist. DFA1 in intersect_dfa"
    assert (is_consistent_dfa(D2in)), "Inconsist. DFA2 in intersect_dfa"
    if (D1in["Sigma"] != D2in["Sigma"]):
        print("Intersection on DFA with different alphabets.")
        print("Making alphabets the same (taking unions).")
        Sigma = D1in["Sigma"] | D2in["Sigma"]
        D1 = copy.deepcopy(D1in)
        D2 = copy.deepcopy(D2in)
        D1["Sigma"] = Sigma
        D2["Sigma"] = Sigma
        D1 = totalize_dfa(D1)
        D2 = totalize_dfa(D2)
    else:
        D1 = totalize_dfa(D1in)
        D2 = totalize_dfa(D2in)

    Q = set(product(D1["Q"], D2["Q"]))

    # This is the only difference with the union:
    # The final states are those when both DFA accept
    F = set(product(D1["F"], D2["F"]))

    q0 = (D1["q0"], D2["q0"])
    Delta = {((q1, q2), ch): (q1p, q2p)
             for q1 in D1["Q"] for q1p in D1["Q"] for q2 in D2["Q"]
             for q2p in D2["Q"] for ch in D1["Sigma"]
             if D1["Delta"][(q1, ch)] == q1p and D2["Delta"][(q2, ch)] == q2p}

    return pruneUnreach(mk_dfa(Q, D1["Sigma"], Delta, q0, F))
Esempio n. 2
0
def iso_dfa(D1, D2):
    """Given consistent and total DFAs D1 and D2,
       check whether they are isomorphic. Two DFAs
       are isomorphic if they have the same number
       of states and are language-equivalent. (One would
       then be able to match-up state for state and transition
       for transition.)
    """
    assert (is_consistent_dfa(D1)), "Inconsist. DFA1 in iso_dfa"
    assert (is_consistent_dfa(D2)), "Inconsist. DFA2 in iso_dfa"
    return (len(D1["Q"]) == len(D2["Q"]) and langeq_dfa(D1, D2))
Esempio n. 3
0
def mk_dfa(Q, Sigma, Delta, q0, F):
    """In : Traits of a DFA
       Out: A DFA
       Check for structural consistency of the given DFA traits.
       If the check passes, make and return a DFA with a total 
       Delta.
    """
    newDFA = {"Q": Q, "Sigma": Sigma, "Delta": Delta, "q0": q0, "F": F}
    assert (
        is_consistent_dfa(newDFA)
    ), "DFA given to mk_dfa is not consistent. Plz check its components."
    return (newDFA)
Esempio n. 4
0
def union_dfa(D1in, D2in):
    """In : D1in (consistent DFA)
            D2in (consistent DFA)
       Out: DFA for language union of D1in, D2in (consistent DFA). 
    """
    assert (is_consistent_dfa(D1in)), "Inconsist. DFA1 in union_dfa"
    assert (is_consistent_dfa(D2in)), "Inconsist. DFA2 in union_dfa"
    if (D1in["Sigma"] != D2in["Sigma"]):
        print("Union on DFA with different alphabets.")
        print("Making alphabets the same (taking unions).")
        Sigma = D1in["Sigma"] | D2in["Sigma"]
        D1 = copy.deepcopy(D1in)
        D2 = copy.deepcopy(D2in)
        D1["Sigma"] = Sigma
        D2["Sigma"] = Sigma
        D1 = totalize_dfa(D1)
        D2 = totalize_dfa(D2)
    else:
        D1 = totalize_dfa(D1in)
        D2 = totalize_dfa(D2in)

    # The states can be anything in the cartesian product
    Q = set(product(D1["Q"], D2["Q"]))

    # Accept if one of the DFAs accepts
    F = (set(product(D1["F"], D2["Q"])) | set(product(D1["Q"], D2["F"])))

    # Start a lock-step march from the respective q0
    q0 = (D1["q0"], D2["q0"])

    # The transition function attempts to march both
    # DFAs in lock-step per their own transition functions
    Delta = {((q1, q2), ch): (q1p, q2p)
             for q1 in D1["Q"] for q1p in D1["Q"] for q2 in D2["Q"]
             for q2p in D2["Q"] for ch in D1["Sigma"]
             if D1["Delta"][(q1, ch)] == q1p and D2["Delta"][(q2, ch)] == q2p}

    return pruneUnreach(mk_dfa(Q, D1["Sigma"], Delta, q0, F))