Right-Quotient Languages 

>
 

> ###########
### Procedure to find right quotient of 2 languages
###########
main := proc( dfa1, dfa2 )
 local qdfa, i, dfaI, dfaInteX;

 ######
 ## The right quotient is defined by a DFA which is exactly the
 ## same as that for the first language, except for the set of final states
 ######
 qdfa := [dfa1[1],dfa1[2],dfa1[3],dfa1[4],{}];
 
 ######
 ## For every internal state in the first DFA
 ######
 for i in dfa1[1] do
   #####
   ## Create a DFA exactly like the first DFA but with that state
   ## as the starting state
   #####
   dfaI := [dfa1[1],dfa1[2],dfa1[3],i,dfa1[5]];
   
   #####
   ### Create a DFA that is the describes the language that is the
   ### intersection of that described by the above DFA and the
   ### second language
   #####
   dfaInteX := createIntersection( dfaI, dfa2 );

   #####
   ## For debugging
   # print( dfaInteX );
   #####
   
   ####
   ## Check if the resulting DFA describes a NULL language
   ####
   if( checkIfEmpty( dfaInteX ) = 0 ) then
     ####
     ## If it doesnot, then add this state to the set of final states
     ####

     ####
     ## For debugging only
     # print( "Not Empty" );
     ####
     qdfa[5] := qdfa[5] union {i};
   else
     ####
     ## For debugging only
     # print( "Empty" );
     ####
   fi;
 od;
 print( "The right quotient is described by:", qdfa );
end:
 

>
 

> ######
## Procedure to create a DFA that describes the intersection of
## of two regular languages
######
createIntersection := proc( FirstDfa, SecondDfa )
local IntersectDfa, IntStatesInt, FinStateInt, i, j, AlphaInt, InitInt;

IntStatesInt := {};
FinStateInt := {};

####
## Set of internal states is Q1 x Q2
####
for i in FirstDfa[1] do
 for j in SecondDfa[1] do
   IntStatesInt := IntStatesInt union {[i, j]};
 od;
od;

### Set of alphabets is the same
AlphaInt := FirstDfa[2];

######
## Initial State is [q0 , q0  ]
##                     1    2
######
InitInt := [FirstDfa[4], SecondDfa[4]];

######
## Set of Final States is F1 x F2
######
for i in FirstDfa[5] do
 for j in SecondDfa[5] do
   FinStateInt := FinStateInt union {[i, j]};
 od;
od;

#####
##  Add delta function as follows:
##  delta( [qi, qj], a ) = [delta1( qi, a ), delta2( qj, a )]
#####
for i in IntStatesInt do
 for j in AlphaInt do
   delta3(i,j) := [FirstDfa[3](i[1],j), SecondDfa[3](i[2],j)];
 od;
od;

## Package it and return
IntersectDfa := [IntStatesInt, AlphaInt, delta3, InitInt, FinStateInt];
RETURN( IntersectDfa );
end:
 

>
 

> ######
## Check if the language describe by the DFA is empty
######
checkIfEmpty := proc( myDfa )
local tempList, tempCnt, i, j, ReachStates, UnReachable;

####
## The idea is to see if all final states are inaccessible
####
tempList := [myDfa[4]];         # Start with the initial state
tempCnt := 1;
i := 0;
do                              # For each state that is accessible
 i := i + 1;
 for j from 1 to nops(myDfa[2]) do          # Check transition on every symbol
   ###
   # If a new state becomes reachable.. add it to the list
   ###
   if not member( myDfa[3](tempList[i], myDfa[2][j]), tempList ) then
     tempList := [op(tempList), myDfa[3](tempList[i], myDfa[2][j])];
     tempCnt := nops(tempList);
   fi;
 od;
 if i = tempCnt then
   break;
 fi;
od;
####
## For debugging
#print( "tempList:", tempList );
####
ReachStates := {op(tempList)};              # These are all the reachable states
UnReachable := myDfa[1] minus ReachStates;  # These are all the unreachable states
if myDfa[5] union UnReachable = UnReachable then
 ## All final states are unreachable ==> NULL language
 RETURN( 1 );
fi;

## Atleast one final state reachable ==> Non-NULL language
RETURN( 0 );
####
## For debugging
#print( ReachStates );
####
end:
 

>