From c249ecdcbd1d662c2e4509e69b149dc3b16dc55d Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Tue, 18 Oct 2022 17:04:03 +0200 Subject: [PATCH 01/13] Updated IntersectionLanguage --- gap/aut-func.gi | 156 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 105 insertions(+), 51 deletions(-) diff --git a/gap/aut-func.gi b/gap/aut-func.gi index 6ca4edd..c1fd5f2 100644 --- a/gap/aut-func.gi +++ b/gap/aut-func.gi @@ -887,79 +887,133 @@ end); ## expressions as arguments ## InstallGlobalFunction(IntersectionLanguage, function(a1,a2) - local HashPair, ht, init, states, m, i, t1, t2, t, st, a, - nst, he, finals, p, q; + local HashPair, ht, init, states, m, s1, s2, t1, t2, t, i, st, a, x, y, nst, he, finals, p, q, numofinitst,m1,m2; - if IsAutomaton(a1) then - elif IsRationalExpression(a1) then - a1 := RatExpToAut(a1); + if IsAutomaton( a1 ) then + ; + elif IsRationalExpression( a1 ) then + a1 := RatExpToAut( a1 ); else - Error("The first argument must be an automaton or a rational expression"); + Error( "The first argument must be an automaton or a rational expression" ); fi; - if IsAutomaton(a2) then - elif IsRationalExpression(a2) then - a2 := RatExpToAut(a2); + if IsAutomaton( a2 ) then + ; + elif IsRationalExpression( a2 ) then + a2 := RatExpToAut( a2 ); else - Error("The second argument must be an automaton or a rational expression"); + Error( "The second argument must be an automaton or a rational expression" ); fi; - if not AlphabetOfAutomatonAsList(a1) = AlphabetOfAutomatonAsList(a2) then - Error("A1 and A2 must have the same alphabet"); + if a1!.type = "epsilon" then + m1 := AlphabetOfAutomaton(a1)-1; + else + m1 := AlphabetOfAutomaton(a1); fi; - - if a1!.type = "nondet" then - a1 := NFAtoDFA(a1); + if a2!.type = "epsilon" then + m2 := AlphabetOfAutomaton(a2)-1; + else + m2 := AlphabetOfAutomaton(a2); fi; - if a2!.type = "nondet" then - a2 := NFAtoDFA(a2); + if m1 <> m2 then + Error( "The arguments must be two automata over the same alphabet" ); fi; - if a1!.type = "epsilon" then - a1 := NFAtoDFA(EpsilonToNFA(a1)); + + if a1!.type <> "epsilon" then + a1 := Automaton("epsilon", a1!.states, a1!.alphabet+1, Concatenation(a1!.transitions, [ListWithIdenticalEntries(a1!.states,[])]), a1!.initial, a1!.accepting); fi; - if a2!.type = "epsilon" then - a2 := NFAtoDFA(EpsilonToNFA(a2)); + if a2!.type <> "epsilon" then + a2 := Automaton("epsilon", a2!.states, a2!.alphabet+1, Concatenation(a2!.transitions, [ListWithIdenticalEntries(a2!.states,[])]), a2!.initial, a2!.accepting); fi; - a1 := NullCompletionAut(a1); - a2 := NullCompletionAut(a2); - HashPair := s->HashKeyBag(s,57,0,12); + HashPair := function ( s ) + return HashKeyBag( s, 57, 0, 3*GAPInfo.BytesPerVariable ); + end; + ht := SparseHashTable( HashPair ); + init := [ ]; + for s1 in a1!.initial do + for s2 in a2!.initial do + Add(init, [ s1, s2 ]); + AddHashEntry( ht, [ s1, s2 ], Length( init ) ); + od; + od; + + numofinitst:=Length(init); - ht := SparseHashTable(HashPair); - init := [a1!.initial[1],a2!.initial[1]]; - AddHashEntry(ht,init,1); - states := [init]; + states := init; m := a1!.alphabet; i := 1; t1 := a1!.transitions; t2 := a2!.transitions; - t := List([1..m],x->[]); - while i <= Length(states) do - st := states[i]; - for a in [1..m] do - nst := [t1[a][st[1]],t2[a][st[2]]]; - MakeImmutable(nst); - he := GetHashEntry(ht,nst); - if he = fail then - Add(states,nst); - he := Length(states); - AddHashEntry(ht,nst,he); - fi; - t[a][i] := he; - od; - i := i+1; + t := List( [ 1 .. m ], function ( x ) return [ ]; end ); + + while i <= Length( states ) do + st := states[i]; + for a in [ 1 .. m ] do + t[a][i] := [ ]; + if a = m then + for x in t1[a][st[1]] do + nst := [ x, st[2] ]; + MakeImmutable( nst ); + he := GetHashEntry( ht, nst ); + if he = fail then + Add( states, nst ); + he := Length( states ); + AddHashEntry( ht, nst, he ); + fi; + Add(t[a][i], he); + od; + for x in t2[a][st[2]] do + nst := [ st[1], x ]; + MakeImmutable( nst ); + he := GetHashEntry( ht, nst ); + if he = fail then + Add( states, nst ); + he := Length( states ); + AddHashEntry( ht, nst, he ); + fi; + Add(t[a][i], he); + od; + else + for x in t1[a][st[1]] do + for y in t2[a][st[2]] do + nst := [ x, y ]; + MakeImmutable( nst ); + he := GetHashEntry( ht, nst ); + if he = fail then + Add( states, nst ); + he := Length( states ); + AddHashEntry( ht, nst, he ); + fi; + Add(t[a][i], he); + od; + od; + fi; + od; + i := i + 1; od; - finals := []; - for p in a1!.accepting do - for q in a2!.accepting do - he := GetHashEntry(ht,[p,q]); + finals := [ ]; + for p in a1!.accepting do + for q in a2!.accepting do + he := GetHashEntry( ht, [ p, q ] ); if he <> fail then - AddSet(finals,he); + AddSet( finals, he ); fi; - od; + od; od; - return Automaton("det",Length(states),AlphabetOfAutomatonAsList(a1),t,[1],finals); -end); + init := [ ]; + for s1 in a1!.initial do + for s2 in a2!.initial do + he := GetHashEntry( ht, [ s1, s2 ] ); + if he <> fail then + Add( init, he ); + fi; + od; + od; + + return Automaton( "epsilon", Length( states ), AlphabetOfAutomatonAsList( a1 ), t, [ 1 .. numofinitst ], finals ); + +end ); From 2be6307565046fd3f10803a3e06c792426d1db86 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Tue, 18 Oct 2022 17:05:31 +0200 Subject: [PATCH 02/13] Updated UnionAutomata --- gap/aut-basics.gi | 76 +++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/gap/aut-basics.gi b/gap/aut-basics.gi index dd7c72b..e08451c 100644 --- a/gap/aut-basics.gi +++ b/gap/aut-basics.gi @@ -605,46 +605,58 @@ end); ## Produces the disjoint union of the automata A and B ## InstallGlobalFunction(UnionAutomata, function(A, B) - local QA, T, a, i, I, F; - - if not (IsAutomatonObj(A) and IsAutomatonObj(B)) then - Error("The arguments must be two automata"); - fi; - if A!.type = "nondet" then - A := NFAtoDFA(A); + local QA, T, a, i, I, F, mA,mB; + + if not (IsAutomatonObj( A ) and IsAutomatonObj( B )) then + Error( "The arguments must be two automata" ); fi; + if A!.type = "epsilon" then - A := NFAtoDFA(EpsilonToNFA(A)); - fi; - if B!.type = "nondet" then - B := NFAtoDFA(B); + mA := AlphabetOfAutomaton(A)-1; + else + mA := AlphabetOfAutomaton(A); fi; if B!.type = "epsilon" then - B := NFAtoDFA(EpsilonToNFA(B)); + mB := AlphabetOfAutomaton(B)-1; + else + mB := AlphabetOfAutomaton(B); fi; - if not AlphabetOfAutomatonAsList(A) = AlphabetOfAutomatonAsList(B) then - Error("The arguments must be two automata over the same alphabet"); + if mA <> mB then + Error( "The arguments must be two automata over the same alphabet" ); fi; - + QA := A!.states; - T := StructuralCopy(A!.transitions); - for a in [1 .. B!.alphabet] do - for i in [1 .. B!.states] do - if B!.transitions[a][i] = 0 then - T[a][QA + i] := 0; - else - T[a][QA + i] := QA + B!.transitions[a][i]; - fi; - od; - od; - I := ShallowCopy(A!.initial); - Add(I, QA + B!.initial[1]); - F := ShallowCopy(A!.accepting); - for i in B!.accepting do - Add(F, QA + i); + T := List( A!.transitions, ShallowCopy ); + if A!.type <> "epsilon" and B!.type = "epsilon" then + Add(T,[]); + fi; + + for a in [ 1 .. B!.alphabet ] do + for i in [ 1 .. B!.states ] do + if B!.transitions[a][i] = 0 then + T[a][QA + i] := 0; + else + T[a][QA + i] := QA + B!.transitions[a][i]; + fi; + od; od; - return(Automaton("nondet", QA + B!.states, AlphabetOfAutomatonAsList(A), T, I, F)); -end); + if A!.type = "epsilon" and B!.type <> "epsilon" then + for i in [1..B!.states] do + Add(T[mA+1],0); + od; + fi; + I := ShallowCopy( A!.initial ); + Append( I, QA + B!.initial ); + + F := ShallowCopy( A!.accepting ); + Append( F, QA + B!.accepting ); + + if A!.type = "epsilon" or B!.type = "epsilon" then + return Automaton( "epsilon", QA + B!.states, mA+1, T, I, F ); + else + return Automaton( "nondet", QA + B!.states, AlphabetOfAutomatonAsList( A ), T, I, F ); + fi; +end ); ############################################################################# ## From 5952228baa34a8f38806a67238cf9cc4b33c55f3 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 10:55:47 +0200 Subject: [PATCH 03/13] added an initial batch of tests --- tst/testall.tst | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tst/testall.tst b/tst/testall.tst index 577c2d1..aa9c2ff 100644 --- a/tst/testall.tst +++ b/tst/testall.tst @@ -889,6 +889,47 @@ gap> NW := InverseAutomatonToGenerators(A); [ 2, "baBA", "bbA" ] +gap> A := Automaton("nondet",5,"abc",[ [ [ 2, 3 ], [ 5 ], [ 1, 4, 5 ], [ 1, 5 ], [ 3, 4 ] ], [ [ 1, 4, 5 ], [ ], [ 1 ], [ 1, 3, 5 ], [ 1, 2, 5 ] ], [ [ ], [ 2, 4, 5 ], [ 1, 3, 5 ], [ ], [ 2, 3, 4 ] ] ],[ ],[ 2, 3, 4 ]);; +gap> B := Automaton("nondet",5,"abc",[ [ [ 2, 3 ], [ 5 ], [ 1, 4, 5 ], [ 1, 5 ], [ 3, 4 ] ], [ [ 1, 4, 5 ], [ ], [ 1 ], [ 1, 3, 5 ], [ 1, 2, 5 ] ], [ [ 1, 4, 5 ], [ 2, 4, 5 ], [ 1, 3, 5 ], [ 2, 3, 4, 5 ], [ 2, 3, 4 ] ] ],[ 3, 4, 5 ],[ 2, 3, 4 ]);; +gap> C:=IntersectionAutomaton(A,B);; +gap> Display(C); + | 1 2 3 4 5 +-------------------- + a | 2 4 4 4 4 + b | 3 4 5 4 4 + c | 4 4 4 4 4 +Initial state: [ 1 ] +Accepting state: [ ] + +gap> a1:=RationalExpression("(bUcUd)*ab*"); +(bUcUd)*ab* +gap> a2:=RationalExpression("(acUd)*(aU@)"); +(acUd)*(aU@) +gap> IntersectionAutomaton(a1,a2); +Error, The arguments must be two automata over the same alphabet + +gap> a2:=RationalExpression("(acUd)*(aUb)"); +(acUd)*(aUb) +gap> IntersectionAutomaton(a1,a2); +< epsilon automaton on 5 letters with 9 states > + +gap> UnionAutomata(a1,a2); +Error, The arguments must be two automata +gap> a1:=RatExpToAut(RationalExpression("(bUcU@)*ab*")); +< deterministic automaton on 3 letters with 3 states > +gap> a2:=RatExpToAut(RationalExpression("(acUd)*(@Ub)")); +< deterministic automaton on 4 letters with 4 states > +gap> UnionAutomata(a1,a2); +Error, The arguments must be two automata over the same alphabet + +gap> a1:=RatExpToAut(RationalExpression("(bUcU@)*ab*")); +< deterministic automaton on 3 letters with 3 states > +gap> a2:=RatExpToAut(RationalExpression("(acUd)*(@Ub)")); +< deterministic automaton on 4 letters with 4 states > +gap> UnionAutomata(a1,a2); +Error, The arguments must be two automata over the same alphabet + + gap> STOP_TEST( "testall.tst", 10000 ); ## The first argument of STOP_TEST should be the name of the test file. ## The number is a proportionality factor that is used to output a From a472d1e2e93438d1bd62cbd8191003324f17dc42 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Tue, 18 Oct 2022 17:04:03 +0200 Subject: [PATCH 04/13] Updated IntersectionLanguage --- gap/aut-func.gi | 156 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 105 insertions(+), 51 deletions(-) diff --git a/gap/aut-func.gi b/gap/aut-func.gi index 6ca4edd..c1fd5f2 100644 --- a/gap/aut-func.gi +++ b/gap/aut-func.gi @@ -887,79 +887,133 @@ end); ## expressions as arguments ## InstallGlobalFunction(IntersectionLanguage, function(a1,a2) - local HashPair, ht, init, states, m, i, t1, t2, t, st, a, - nst, he, finals, p, q; + local HashPair, ht, init, states, m, s1, s2, t1, t2, t, i, st, a, x, y, nst, he, finals, p, q, numofinitst,m1,m2; - if IsAutomaton(a1) then - elif IsRationalExpression(a1) then - a1 := RatExpToAut(a1); + if IsAutomaton( a1 ) then + ; + elif IsRationalExpression( a1 ) then + a1 := RatExpToAut( a1 ); else - Error("The first argument must be an automaton or a rational expression"); + Error( "The first argument must be an automaton or a rational expression" ); fi; - if IsAutomaton(a2) then - elif IsRationalExpression(a2) then - a2 := RatExpToAut(a2); + if IsAutomaton( a2 ) then + ; + elif IsRationalExpression( a2 ) then + a2 := RatExpToAut( a2 ); else - Error("The second argument must be an automaton or a rational expression"); + Error( "The second argument must be an automaton or a rational expression" ); fi; - if not AlphabetOfAutomatonAsList(a1) = AlphabetOfAutomatonAsList(a2) then - Error("A1 and A2 must have the same alphabet"); + if a1!.type = "epsilon" then + m1 := AlphabetOfAutomaton(a1)-1; + else + m1 := AlphabetOfAutomaton(a1); fi; - - if a1!.type = "nondet" then - a1 := NFAtoDFA(a1); + if a2!.type = "epsilon" then + m2 := AlphabetOfAutomaton(a2)-1; + else + m2 := AlphabetOfAutomaton(a2); fi; - if a2!.type = "nondet" then - a2 := NFAtoDFA(a2); + if m1 <> m2 then + Error( "The arguments must be two automata over the same alphabet" ); fi; - if a1!.type = "epsilon" then - a1 := NFAtoDFA(EpsilonToNFA(a1)); + + if a1!.type <> "epsilon" then + a1 := Automaton("epsilon", a1!.states, a1!.alphabet+1, Concatenation(a1!.transitions, [ListWithIdenticalEntries(a1!.states,[])]), a1!.initial, a1!.accepting); fi; - if a2!.type = "epsilon" then - a2 := NFAtoDFA(EpsilonToNFA(a2)); + if a2!.type <> "epsilon" then + a2 := Automaton("epsilon", a2!.states, a2!.alphabet+1, Concatenation(a2!.transitions, [ListWithIdenticalEntries(a2!.states,[])]), a2!.initial, a2!.accepting); fi; - a1 := NullCompletionAut(a1); - a2 := NullCompletionAut(a2); - HashPair := s->HashKeyBag(s,57,0,12); + HashPair := function ( s ) + return HashKeyBag( s, 57, 0, 3*GAPInfo.BytesPerVariable ); + end; + ht := SparseHashTable( HashPair ); + init := [ ]; + for s1 in a1!.initial do + for s2 in a2!.initial do + Add(init, [ s1, s2 ]); + AddHashEntry( ht, [ s1, s2 ], Length( init ) ); + od; + od; + + numofinitst:=Length(init); - ht := SparseHashTable(HashPair); - init := [a1!.initial[1],a2!.initial[1]]; - AddHashEntry(ht,init,1); - states := [init]; + states := init; m := a1!.alphabet; i := 1; t1 := a1!.transitions; t2 := a2!.transitions; - t := List([1..m],x->[]); - while i <= Length(states) do - st := states[i]; - for a in [1..m] do - nst := [t1[a][st[1]],t2[a][st[2]]]; - MakeImmutable(nst); - he := GetHashEntry(ht,nst); - if he = fail then - Add(states,nst); - he := Length(states); - AddHashEntry(ht,nst,he); - fi; - t[a][i] := he; - od; - i := i+1; + t := List( [ 1 .. m ], function ( x ) return [ ]; end ); + + while i <= Length( states ) do + st := states[i]; + for a in [ 1 .. m ] do + t[a][i] := [ ]; + if a = m then + for x in t1[a][st[1]] do + nst := [ x, st[2] ]; + MakeImmutable( nst ); + he := GetHashEntry( ht, nst ); + if he = fail then + Add( states, nst ); + he := Length( states ); + AddHashEntry( ht, nst, he ); + fi; + Add(t[a][i], he); + od; + for x in t2[a][st[2]] do + nst := [ st[1], x ]; + MakeImmutable( nst ); + he := GetHashEntry( ht, nst ); + if he = fail then + Add( states, nst ); + he := Length( states ); + AddHashEntry( ht, nst, he ); + fi; + Add(t[a][i], he); + od; + else + for x in t1[a][st[1]] do + for y in t2[a][st[2]] do + nst := [ x, y ]; + MakeImmutable( nst ); + he := GetHashEntry( ht, nst ); + if he = fail then + Add( states, nst ); + he := Length( states ); + AddHashEntry( ht, nst, he ); + fi; + Add(t[a][i], he); + od; + od; + fi; + od; + i := i + 1; od; - finals := []; - for p in a1!.accepting do - for q in a2!.accepting do - he := GetHashEntry(ht,[p,q]); + finals := [ ]; + for p in a1!.accepting do + for q in a2!.accepting do + he := GetHashEntry( ht, [ p, q ] ); if he <> fail then - AddSet(finals,he); + AddSet( finals, he ); fi; - od; + od; od; - return Automaton("det",Length(states),AlphabetOfAutomatonAsList(a1),t,[1],finals); -end); + init := [ ]; + for s1 in a1!.initial do + for s2 in a2!.initial do + he := GetHashEntry( ht, [ s1, s2 ] ); + if he <> fail then + Add( init, he ); + fi; + od; + od; + + return Automaton( "epsilon", Length( states ), AlphabetOfAutomatonAsList( a1 ), t, [ 1 .. numofinitst ], finals ); + +end ); From 9bb348f92807c738b45166abc3ce4568e0588d68 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Tue, 18 Oct 2022 17:05:31 +0200 Subject: [PATCH 05/13] Updated UnionAutomata --- gap/aut-basics.gi | 76 +++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/gap/aut-basics.gi b/gap/aut-basics.gi index dd7c72b..e08451c 100644 --- a/gap/aut-basics.gi +++ b/gap/aut-basics.gi @@ -605,46 +605,58 @@ end); ## Produces the disjoint union of the automata A and B ## InstallGlobalFunction(UnionAutomata, function(A, B) - local QA, T, a, i, I, F; - - if not (IsAutomatonObj(A) and IsAutomatonObj(B)) then - Error("The arguments must be two automata"); - fi; - if A!.type = "nondet" then - A := NFAtoDFA(A); + local QA, T, a, i, I, F, mA,mB; + + if not (IsAutomatonObj( A ) and IsAutomatonObj( B )) then + Error( "The arguments must be two automata" ); fi; + if A!.type = "epsilon" then - A := NFAtoDFA(EpsilonToNFA(A)); - fi; - if B!.type = "nondet" then - B := NFAtoDFA(B); + mA := AlphabetOfAutomaton(A)-1; + else + mA := AlphabetOfAutomaton(A); fi; if B!.type = "epsilon" then - B := NFAtoDFA(EpsilonToNFA(B)); + mB := AlphabetOfAutomaton(B)-1; + else + mB := AlphabetOfAutomaton(B); fi; - if not AlphabetOfAutomatonAsList(A) = AlphabetOfAutomatonAsList(B) then - Error("The arguments must be two automata over the same alphabet"); + if mA <> mB then + Error( "The arguments must be two automata over the same alphabet" ); fi; - + QA := A!.states; - T := StructuralCopy(A!.transitions); - for a in [1 .. B!.alphabet] do - for i in [1 .. B!.states] do - if B!.transitions[a][i] = 0 then - T[a][QA + i] := 0; - else - T[a][QA + i] := QA + B!.transitions[a][i]; - fi; - od; - od; - I := ShallowCopy(A!.initial); - Add(I, QA + B!.initial[1]); - F := ShallowCopy(A!.accepting); - for i in B!.accepting do - Add(F, QA + i); + T := List( A!.transitions, ShallowCopy ); + if A!.type <> "epsilon" and B!.type = "epsilon" then + Add(T,[]); + fi; + + for a in [ 1 .. B!.alphabet ] do + for i in [ 1 .. B!.states ] do + if B!.transitions[a][i] = 0 then + T[a][QA + i] := 0; + else + T[a][QA + i] := QA + B!.transitions[a][i]; + fi; + od; od; - return(Automaton("nondet", QA + B!.states, AlphabetOfAutomatonAsList(A), T, I, F)); -end); + if A!.type = "epsilon" and B!.type <> "epsilon" then + for i in [1..B!.states] do + Add(T[mA+1],0); + od; + fi; + I := ShallowCopy( A!.initial ); + Append( I, QA + B!.initial ); + + F := ShallowCopy( A!.accepting ); + Append( F, QA + B!.accepting ); + + if A!.type = "epsilon" or B!.type = "epsilon" then + return Automaton( "epsilon", QA + B!.states, mA+1, T, I, F ); + else + return Automaton( "nondet", QA + B!.states, AlphabetOfAutomatonAsList( A ), T, I, F ); + fi; +end ); ############################################################################# ## From afff8485c7522f9b0cb555fe76c51906c69e5dea Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 10:55:47 +0200 Subject: [PATCH 06/13] added an initial batch of tests --- tst/testall.tst | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tst/testall.tst b/tst/testall.tst index 577c2d1..aa9c2ff 100644 --- a/tst/testall.tst +++ b/tst/testall.tst @@ -889,6 +889,47 @@ gap> NW := InverseAutomatonToGenerators(A); [ 2, "baBA", "bbA" ] +gap> A := Automaton("nondet",5,"abc",[ [ [ 2, 3 ], [ 5 ], [ 1, 4, 5 ], [ 1, 5 ], [ 3, 4 ] ], [ [ 1, 4, 5 ], [ ], [ 1 ], [ 1, 3, 5 ], [ 1, 2, 5 ] ], [ [ ], [ 2, 4, 5 ], [ 1, 3, 5 ], [ ], [ 2, 3, 4 ] ] ],[ ],[ 2, 3, 4 ]);; +gap> B := Automaton("nondet",5,"abc",[ [ [ 2, 3 ], [ 5 ], [ 1, 4, 5 ], [ 1, 5 ], [ 3, 4 ] ], [ [ 1, 4, 5 ], [ ], [ 1 ], [ 1, 3, 5 ], [ 1, 2, 5 ] ], [ [ 1, 4, 5 ], [ 2, 4, 5 ], [ 1, 3, 5 ], [ 2, 3, 4, 5 ], [ 2, 3, 4 ] ] ],[ 3, 4, 5 ],[ 2, 3, 4 ]);; +gap> C:=IntersectionAutomaton(A,B);; +gap> Display(C); + | 1 2 3 4 5 +-------------------- + a | 2 4 4 4 4 + b | 3 4 5 4 4 + c | 4 4 4 4 4 +Initial state: [ 1 ] +Accepting state: [ ] + +gap> a1:=RationalExpression("(bUcUd)*ab*"); +(bUcUd)*ab* +gap> a2:=RationalExpression("(acUd)*(aU@)"); +(acUd)*(aU@) +gap> IntersectionAutomaton(a1,a2); +Error, The arguments must be two automata over the same alphabet + +gap> a2:=RationalExpression("(acUd)*(aUb)"); +(acUd)*(aUb) +gap> IntersectionAutomaton(a1,a2); +< epsilon automaton on 5 letters with 9 states > + +gap> UnionAutomata(a1,a2); +Error, The arguments must be two automata +gap> a1:=RatExpToAut(RationalExpression("(bUcU@)*ab*")); +< deterministic automaton on 3 letters with 3 states > +gap> a2:=RatExpToAut(RationalExpression("(acUd)*(@Ub)")); +< deterministic automaton on 4 letters with 4 states > +gap> UnionAutomata(a1,a2); +Error, The arguments must be two automata over the same alphabet + +gap> a1:=RatExpToAut(RationalExpression("(bUcU@)*ab*")); +< deterministic automaton on 3 letters with 3 states > +gap> a2:=RatExpToAut(RationalExpression("(acUd)*(@Ub)")); +< deterministic automaton on 4 letters with 4 states > +gap> UnionAutomata(a1,a2); +Error, The arguments must be two automata over the same alphabet + + gap> STOP_TEST( "testall.tst", 10000 ); ## The first argument of STOP_TEST should be the name of the test file. ## The number is a proportionality factor that is used to output a From 022de40e58c58d1bed12fa21f9331417ab33e2e6 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 11:21:17 +0200 Subject: [PATCH 07/13] fixed the tests --- tst/testall.tst | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tst/testall.tst b/tst/testall.tst index aa9c2ff..b42ac3d 100644 --- a/tst/testall.tst +++ b/tst/testall.tst @@ -888,19 +888,6 @@ Accepting state: [ 1 ] gap> NW := InverseAutomatonToGenerators(A); [ 2, "baBA", "bbA" ] - -gap> A := Automaton("nondet",5,"abc",[ [ [ 2, 3 ], [ 5 ], [ 1, 4, 5 ], [ 1, 5 ], [ 3, 4 ] ], [ [ 1, 4, 5 ], [ ], [ 1 ], [ 1, 3, 5 ], [ 1, 2, 5 ] ], [ [ ], [ 2, 4, 5 ], [ 1, 3, 5 ], [ ], [ 2, 3, 4 ] ] ],[ ],[ 2, 3, 4 ]);; -gap> B := Automaton("nondet",5,"abc",[ [ [ 2, 3 ], [ 5 ], [ 1, 4, 5 ], [ 1, 5 ], [ 3, 4 ] ], [ [ 1, 4, 5 ], [ ], [ 1 ], [ 1, 3, 5 ], [ 1, 2, 5 ] ], [ [ 1, 4, 5 ], [ 2, 4, 5 ], [ 1, 3, 5 ], [ 2, 3, 4, 5 ], [ 2, 3, 4 ] ] ],[ 3, 4, 5 ],[ 2, 3, 4 ]);; -gap> C:=IntersectionAutomaton(A,B);; -gap> Display(C); - | 1 2 3 4 5 --------------------- - a | 2 4 4 4 4 - b | 3 4 5 4 4 - c | 4 4 4 4 4 -Initial state: [ 1 ] -Accepting state: [ ] - gap> a1:=RationalExpression("(bUcUd)*ab*"); (bUcUd)*ab* gap> a2:=RationalExpression("(acUd)*(aU@)"); From 4a73464349e4be73a698885efb0b3ccafa9a3607 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 11:24:42 +0200 Subject: [PATCH 08/13] fixing what the merge overwrote --- tst/testall.tst | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/tst/testall.tst b/tst/testall.tst index 67122fa..b42ac3d 100644 --- a/tst/testall.tst +++ b/tst/testall.tst @@ -917,47 +917,6 @@ gap> UnionAutomata(a1,a2); Error, The arguments must be two automata over the same alphabet -gap> A := Automaton("nondet",5,"abc",[ [ [ 2, 3 ], [ 5 ], [ 1, 4, 5 ], [ 1, 5 ], [ 3, 4 ] ], [ [ 1, 4, 5 ], [ ], [ 1 ], [ 1, 3, 5 ], [ 1, 2, 5 ] ], [ [ ], [ 2, 4, 5 ], [ 1, 3, 5 ], [ ], [ 2, 3, 4 ] ] ],[ ],[ 2, 3, 4 ]);; -gap> B := Automaton("nondet",5,"abc",[ [ [ 2, 3 ], [ 5 ], [ 1, 4, 5 ], [ 1, 5 ], [ 3, 4 ] ], [ [ 1, 4, 5 ], [ ], [ 1 ], [ 1, 3, 5 ], [ 1, 2, 5 ] ], [ [ 1, 4, 5 ], [ 2, 4, 5 ], [ 1, 3, 5 ], [ 2, 3, 4, 5 ], [ 2, 3, 4 ] ] ],[ 3, 4, 5 ],[ 2, 3, 4 ]);; -gap> C:=IntersectionAutomaton(A,B);; -gap> Display(C); - | 1 2 3 4 5 --------------------- - a | 2 4 4 4 4 - b | 3 4 5 4 4 - c | 4 4 4 4 4 -Initial state: [ 1 ] -Accepting state: [ ] - -gap> a1:=RationalExpression("(bUcUd)*ab*"); -(bUcUd)*ab* -gap> a2:=RationalExpression("(acUd)*(aU@)"); -(acUd)*(aU@) -gap> IntersectionAutomaton(a1,a2); -Error, The arguments must be two automata over the same alphabet - -gap> a2:=RationalExpression("(acUd)*(aUb)"); -(acUd)*(aUb) -gap> IntersectionAutomaton(a1,a2); -< epsilon automaton on 5 letters with 9 states > - -gap> UnionAutomata(a1,a2); -Error, The arguments must be two automata -gap> a1:=RatExpToAut(RationalExpression("(bUcU@)*ab*")); -< deterministic automaton on 3 letters with 3 states > -gap> a2:=RatExpToAut(RationalExpression("(acUd)*(@Ub)")); -< deterministic automaton on 4 letters with 4 states > -gap> UnionAutomata(a1,a2); -Error, The arguments must be two automata over the same alphabet - -gap> a1:=RatExpToAut(RationalExpression("(bUcU@)*ab*")); -< deterministic automaton on 3 letters with 3 states > -gap> a2:=RatExpToAut(RationalExpression("(acUd)*(@Ub)")); -< deterministic automaton on 4 letters with 4 states > -gap> UnionAutomata(a1,a2); -Error, The arguments must be two automata over the same alphabet - - gap> STOP_TEST( "testall.tst", 10000 ); ## The first argument of STOP_TEST should be the name of the test file. ## The number is a proportionality factor that is used to output a From 05601f3f6333f69f3b912adba057ced1bdebc50b Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 11:28:32 +0200 Subject: [PATCH 09/13] Update gap/aut-func.gi Co-authored-by: Max Horn --- gap/aut-func.gi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gap/aut-func.gi b/gap/aut-func.gi index c1fd5f2..c7e6897 100644 --- a/gap/aut-func.gi +++ b/gap/aut-func.gi @@ -944,7 +944,7 @@ InstallGlobalFunction(IntersectionLanguage, function(a1,a2) i := 1; t1 := a1!.transitions; t2 := a2!.transitions; - t := List( [ 1 .. m ], function ( x ) return [ ]; end ); + t := List( [ 1 .. m ], x -> [ ] ); while i <= Length( states ) do st := states[i]; From 2181fd8413af7ce03e171844c6300ef8219cb9b2 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 11:43:52 +0200 Subject: [PATCH 10/13] adding more tests for non-deterministic and epsilon automata --- tst/testall.tst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tst/testall.tst b/tst/testall.tst index b42ac3d..96fc30c 100644 --- a/tst/testall.tst +++ b/tst/testall.tst @@ -916,6 +916,16 @@ gap> a2:=RatExpToAut(RationalExpression("(acUd)*(@Ub)")); gap> UnionAutomata(a1,a2); Error, The arguments must be two automata over the same alphabet +gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2],[2,3]);; +gap> y:=Automaton("epsilon",3,"01@",[ [ [ 3 ], [ 1 ], [ 1, 2 ] ], [ [ ], [ ], [ 1, 3 ] ], [ [ 1, 3 ], [ 1 ], [ 3 ] ] ],[ 1, 2, 3 ],[ 1, 3 ]);; +gap> UnionAutomata(x,y); +< epsilon automaton on 3 letters with 6 states > + +gap> x:=Automaton("det",3,2,[ [ 0, 2, 0 ], [ 0, 1, 0 ] ],[ 3 ],[ 2 ]);; +gap> y:=Automaton("nondet",3,2,[[,[1,3],],[,[2,3],[1,3]]],[1,2],[1,3]);; +gap> UnionAutomata(x,y); +< non deterministic automaton on 2 letters with 6 states > + gap> STOP_TEST( "testall.tst", 10000 ); ## The first argument of STOP_TEST should be the name of the test file. From df097f443c1f4c8e3efef4b668d28e69d59fc043 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 11:50:50 +0200 Subject: [PATCH 11/13] added extra tests --- tst/testall.tst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tst/testall.tst b/tst/testall.tst index 96fc30c..e73cbe0 100644 --- a/tst/testall.tst +++ b/tst/testall.tst @@ -926,6 +926,16 @@ gap> y:=Automaton("nondet",3,2,[[,[1,3],],[,[2,3],[1,3]]],[1,2],[1,3]);; gap> UnionAutomata(x,y); < non deterministic automaton on 2 letters with 6 states > +gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2],[2,3]);; +gap> y:=Automaton("nondet",3,2,[[,[1,3],],[,[2,3],[1,3]]],[1,2],[1,3]);; +gap> UnionAutomata(x,y); +< epsilon automaton on 3 letters with 6 states > + +gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2],[2,3]);; +gap> y:=Automaton("det",3,2,[ [ 0, 2, 0 ], [ 0, 1, 0 ] ],[ 3 ],[ 2 ]);; +gap> UnionAutomata(x,y); +< epsilon automaton on 3 letters with 6 states > + gap> STOP_TEST( "testall.tst", 10000 ); ## The first argument of STOP_TEST should be the name of the test file. From fe7eb95e7abd5736eb31e6c98a587637a998a364 Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 11:54:14 +0200 Subject: [PATCH 12/13] even more tests added --- tst/testall.tst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tst/testall.tst b/tst/testall.tst index e73cbe0..aaa4d9b 100644 --- a/tst/testall.tst +++ b/tst/testall.tst @@ -920,22 +920,29 @@ gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2], gap> y:=Automaton("epsilon",3,"01@",[ [ [ 3 ], [ 1 ], [ 1, 2 ] ], [ [ ], [ ], [ 1, 3 ] ], [ [ 1, 3 ], [ 1 ], [ 3 ] ] ],[ 1, 2, 3 ],[ 1, 3 ]);; gap> UnionAutomata(x,y); < epsilon automaton on 3 letters with 6 states > +gap> UnionAutomata(y,x); +< epsilon automaton on 3 letters with 6 states > gap> x:=Automaton("det",3,2,[ [ 0, 2, 0 ], [ 0, 1, 0 ] ],[ 3 ],[ 2 ]);; gap> y:=Automaton("nondet",3,2,[[,[1,3],],[,[2,3],[1,3]]],[1,2],[1,3]);; gap> UnionAutomata(x,y); < non deterministic automaton on 2 letters with 6 states > +gap> UnionAutomata(y,x); +< non deterministic automaton on 2 letters with 6 states > gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2],[2,3]);; gap> y:=Automaton("nondet",3,2,[[,[1,3],],[,[2,3],[1,3]]],[1,2],[1,3]);; gap> UnionAutomata(x,y); < epsilon automaton on 3 letters with 6 states > +gap> UnionAutomata(y,x); +< epsilon automaton on 3 letters with 6 states > gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2],[2,3]);; gap> y:=Automaton("det",3,2,[ [ 0, 2, 0 ], [ 0, 1, 0 ] ],[ 3 ],[ 2 ]);; gap> UnionAutomata(x,y); < epsilon automaton on 3 letters with 6 states > - +gap> UnionAutomata(y,x); +< epsilon automaton on 3 letters with 6 states > gap> STOP_TEST( "testall.tst", 10000 ); ## The first argument of STOP_TEST should be the name of the test file. From eb4a4fa2ad626ef83abdc21e5a5e7100034ce82d Mon Sep 17 00:00:00 2001 From: Ruth Hoffmann Date: Wed, 19 Oct 2022 12:06:34 +0200 Subject: [PATCH 13/13] more intersection tests --- tst/testall.tst | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tst/testall.tst b/tst/testall.tst index aaa4d9b..e41f04b 100644 --- a/tst/testall.tst +++ b/tst/testall.tst @@ -920,8 +920,8 @@ gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2], gap> y:=Automaton("epsilon",3,"01@",[ [ [ 3 ], [ 1 ], [ 1, 2 ] ], [ [ ], [ ], [ 1, 3 ] ], [ [ 1, 3 ], [ 1 ], [ 3 ] ] ],[ 1, 2, 3 ],[ 1, 3 ]);; gap> UnionAutomata(x,y); < epsilon automaton on 3 letters with 6 states > -gap> UnionAutomata(y,x); -< epsilon automaton on 3 letters with 6 states > +gap> IntersectionAutomaton(x,y); +< epsilon automaton on 3 letters with 3 states > gap> x:=Automaton("det",3,2,[ [ 0, 2, 0 ], [ 0, 1, 0 ] ],[ 3 ],[ 2 ]);; gap> y:=Automaton("nondet",3,2,[[,[1,3],],[,[2,3],[1,3]]],[1,2],[1,3]);; @@ -929,6 +929,10 @@ gap> UnionAutomata(x,y); < non deterministic automaton on 2 letters with 6 states > gap> UnionAutomata(y,x); < non deterministic automaton on 2 letters with 6 states > +gap> IntersectionAutomaton(x,y); +< epsilon automaton on 3 letters with 2 states > +gap> IntersectionAutomaton(y,x); +< epsilon automaton on 3 letters with 2 states > gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2],[2,3]);; gap> y:=Automaton("nondet",3,2,[[,[1,3],],[,[2,3],[1,3]]],[1,2],[1,3]);; @@ -936,6 +940,10 @@ gap> UnionAutomata(x,y); < epsilon automaton on 3 letters with 6 states > gap> UnionAutomata(y,x); < epsilon automaton on 3 letters with 6 states > +gap> IntersectionAutomaton(x,y); +< epsilon automaton on 3 letters with 3 states > +gap> IntersectionAutomaton(y,x); +< epsilon automaton on 3 letters with 3 states > gap> x:=Automaton("epsilon",3,"01@",[[,[2],[3]],[[1,3],,[1]],[[1],[2],[2]]],[2],[2,3]);; gap> y:=Automaton("det",3,2,[ [ 0, 2, 0 ], [ 0, 1, 0 ] ],[ 3 ],[ 2 ]);; @@ -943,6 +951,11 @@ gap> UnionAutomata(x,y); < epsilon automaton on 3 letters with 6 states > gap> UnionAutomata(y,x); < epsilon automaton on 3 letters with 6 states > +gap> IntersectionAutomaton(x,y); +< epsilon automaton on 3 letters with 1 states > +gap> IntersectionAutomaton(y,x); +< epsilon automaton on 3 letters with 1 states > + gap> STOP_TEST( "testall.tst", 10000 ); ## The first argument of STOP_TEST should be the name of the test file.