theory of computation (fall 2014): closure properties of regular languages; programmatic aspects of...
TRANSCRIPT
Theory of Computation
Closure Properties of Regular
Languages, Programmatic Aspects of
Implementing DFAs & NFAs
Vladimir Kulyukin
http://www.vkedco.blogspot.com/
Outline
• Closure Properties of Regular Languages
• Programmatic Aspects of Implementing
DFAs and NFAs
Closure Properties of Regular
Languages
Definition: Language Complement
.|
is of complement the,over language a is If
* LxxL
LL
Closure under Complement
regular. also is then language,regular a is If :Theorem LL
.
ifonly and if ,any for Then,
.,,,,
DFA new a definecan We
.such that ,,,,
DFA a is thereregular, a is If :Proof
*
0
0
MLx
MLxx
FQqQM
MLLFqQM
L
Example
q0
q1
q2
0
0,1
0,1
L is the language over {0, 1}
consisting of strings that start with 0.
1
q0
q1
q2
0,1
0,1
1
0
The complement of L is the language
of strings over {0, 1} that
start with 1 and the empty string.
Definition: Language Intersection
. & |
then languages, are and If
21
*
21
21
LxLxxLL
LL
Closure under Intersection
regular. also is
then languages,regular are and If :Theorem 2121 LLLL
.,,
,,,
, and ,
,any For .,,
where,,,,,,
where,,,,,,
DFA new aconstruct We.
such that ,,,, and
such that ,,,, DFAs two
are thereregular, are and If :Proof
212100
*
3
210
*
20
*
1
20
*
210
*
1
21
*
213
210033
22
202211
1011
21
LLxFFxrq
FFxrxq
FxrFxq
LLxxaRrQq
araqarq
FFrqRQM
MLL
FrRMMLL
FqQM
LL
Definition: Language Union
.or |
then languages, are and If
21
*
21
21
LxLxxLL
LL
Closure under Union
regular. also is
then languages,regular are and If :Theorem 2121 LLLL
regular. is
on,intersecti and complementunder closed are
languagesregular Since .
then regular, are and If :1 Proof
21
2121
21
LL
LLLL
LL
Closure under Union
regular. also is
then languages,regular are and If :Theorem 2121 LLLL
. are states final
theunion, for the DFA theof states final for the
except on,intersectiunder closure of proof in the
ason constructi same theusecan We:2 Proof
21 FQRF
Programmatic Aspects
of Implementing DFAs & NFAs
Problem
Show that the language of binary
representations of numbers divisible by 3 is
regular.
Solution 01
q0 q1 q2
0
1
0
This DFA does the job but does not handle symbols outside of {0, 1}. To
make our solution robust, we need to add an error state where the DFA
goes and stays as soon as it sees a symbol other than 0 or 1.
1
0
1
Solution 02
q0 q1 q2
0
1
0
q3 is the sink state where the automaton stays as soon as a
symbol different from 0 or 1 is seen.
1
0
1
q3
0, 1
not 0 or 1
not 0 or 1
not 0 or 1
Two Implementation Approaches
• There are two general approaches used in
implementing DFAs and NFAs: implement delta
as a function and implement delta as a table
• Implementing delta as a function is more
understandable and sometimes more efficient if
the FA happens to be a weakly connected graph
• Implementing delta as a table is more common
because tables can be constructed offline and
read in at run time
Defining States
public class Mod3DFA {
static final int Q0 = 0;
static final int Q1 = 1;
static final int Q2 = 2;
static final int Q3 = 3;
private static int mCurrState;
…
}
Defining Delta Function private static int delta(int state, char c) {
switch ( state ) {
case Q0: switch ( c ) {
case '0': return Q0;
case '1': return Q1;
default: return Q3;
}
case Q1: switch ( c ) {
case '0': return Q2;
case '1': return Q0;
default: return Q3;
}
case Q2: switch ( c ) {
case '0': return Q1;
case '1': return Q2;
default: return Q3;
}
default: return Q3;
}
}
Resetting, Processing, Accepting
static void reset() { mCurrState = Q0; }
static void process(String input) {
for(int i = 0; i < input.length(); i++) {
mCurrState = delta(mCurrState, input.charAt(i));
}
}
static boolean isAccepted() { return mCurrState == Q0; }
Testing static void mod3StringFilter() {
try {
BufferedReader input
= new BufferedReader(new InputStreamReader(System.in));
String inputStr = input.readLine();
while ( inputStr != null ) {
Mod3DFA.reset();
Mod3DFA.process(inputStr);
if ( Mod3DFA.isAccepted() )
System.out.println("YES");
else
System.out.println("NO");
inputStr = input.readLine();
}
}
catch ( IOException ex ) {
System.err.println(ex.toString());
}
}
Testing
public static void main(String[] argv) {
Mod3DFA.mod3StringFilter();
}
Defining States
public class Mod3DFA {
static final int Q0 = 0;
static final int Q1 = 1;
static final int Q2 = 2;
static final int Q3 = 3;
private static int mCurrState;
…
}
Defining Delta
static int[][] deltaTable =
{
{Q0, Q1}, // state Q0: delta('0', Q0) = Q0; delta('1', Q1)
{Q2, Q0}, // state Q1: delta('0', Q1) = Q2; detal('1', Q0)
{Q1, Q2}, // state Q2: delta('0', Q2) = Q1; delta('1', Q2)
{Q3, Q3} // state Q3: delta('0', Q3) = Q3; delta('1', Q3)
};
Resetting, Processing, Accepting
static void reset() { mCurrState = Q0; }
static void process(String input) {
for(int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
try { // Table lookup is based on the following Java trick:
// int i = ‘1’ – ‘0’; // i == 1
// int j = ‘0’ – ‘0’; // j == 0
// this works only because c is either ‘1’ or ‘0’
mCurrState = deltaTable[mCurrState][c-'0'];
}
catch ( ArrayIndexOutOfBoundsException ex ) {
mCurrState = Q3;
} } }
static boolean isAccepted() { return mCurrState == Q0; }
Sketchy NFA Implementation
Sample NFA
q0 q1 q2
0, 1
1
This NFA accepts all strings such that the last but one
symbol is 1.
0, 1
NFAs as BackTracking Search
static short[ ][ ][ ] mDeltaTable = {
{{0}, {0, 1}}, // mDeltaTable[0, 0], mDeltaTable[0, 1]
{{2}, {2}}, // mDeltaTable[1, 0], mDeltaTable[1, 1]
{{}, {}} // mDeltaTable[2, 0], mDeltaTable[2, 1]
};
source code is here
Backtracking Search static boolean process_backtrack(short st, String input, int char_pos) {
if ( char_pos == input.length() ) return st == 2;
char c = input.charAt(char_pos);
short[] next_states;
try {
next_states = mDeltaTable[st][c-'0'];
}
catch ( ArrayIndexOutOfBoundsException ex ) {
return false;
}
// call process_backtrack recursively and use recursion to backtrack to
// this point if it returns false.
for(int i=0; i < next_states.length; i++) {
if ( process_backtrack(next_states[i], input, char_pos+1) )
return true;
}
return false;
}
Backtracking Search
public static boolean process(String input) {
return process_backtrack((short)0, input, 0);
}
Bit Fiddling Examples
1 << 0 == 1 // ‘001’
1 << 1 == 2 // ‘010’
1 << 2 == 4 // ‘100’
1 << 1 | 1 << 2 == 6 // ‘010’ | ‘100’ == ‘110’ == 6
1 << 2 | 1 << 0 == 5 // ‘100’ | ‘001’ == ‘101’ == 5
1 << 1 & 1 << 2 == 0 // ‘010’ & ‘100’ == ‘000’ == 0
(1 << 2 | 1 << 0) & (1 << 2) == 4 // ‘101’ & ‘100’ ==
// ‘100’ == 4
Bit Fiddling Examples
static void bitFiddlingExamples() {
System.out.println("1 << 0 == " + Integer.toString(1 << 0));
System.out.println("1 << 1 == " + Integer.toString(1 << 1));
System.out.println("1 << 2 == " + Integer.toString(1 << 2));
System.out.println("1 << 1 | 1 << 2 == " + Integer.toString(1 << 1 | 1 << 2));
System.out.println("1 << 2 | 1 << 0 == " + Integer.toString(1 << 2 | 1 << 0));
System.out.println("1 << 1 & 1 << 2 == " + Integer.toString(1 << 1 & 1 << 2));
System.out.println("(1 << 2 | 1 << 0) & (1 << 2) == " +
Integer.toString((1 << 2 | 1 << 0) & (1 << 2)));
}
Sets of States as Bit Strings
// A set of possible states can be represented as a bit string.
// For example, suppose an NFA has 3 states: q0, q1, and
// q2.
// Then the rightmost bit denotes q0; the middle bit denotes
// q1, and the leftmost bit is q2. Thus, ‘101’ means that the
// NFA is either in q2 or q0.
static int mStateSet;
// set the state set to '001‘, i.e. the NFA is in q0.
static void reset() { mStateSet = 1<<0; }
source code is here
Delta Table as Bit Strings
// mDeltaTable[state][symbol] = bit string representing possible states
static int[ ][ ] mDeltaTable =
{
{1 << 0, 1 << 0 | 1 << 1}, // transitions from q0: d(0,0)={0}; d(0,1)={0,1}
{1 << 2, 1 << 2}, // transitions from q1: d(1,0)={2}; d(1,1)={2}
{0, 0} // transitions from q2: d(2,0)={}; d(2,1)={}
};
Sample NFA
q0 q1 q2
0, 1
1
• ‘001’ – initially the NFA is in state q0
• Suppose the input is “01”
• After reading the 1st 0, the NFA is in ‘001’
• After reading the 2nd 1, the NFA is in ‘011’
0, 1
Keeping Track of Possible States static void processInput(String input) {
for (int i = 0; i < input.length(); i++) {
final char c = input.charAt(i);
int nextStateSet = 0;
for (int s = 0; s <= 2; s++) {
if ((mStateSet & (1 << s)) != 0) {
try {
// do the oring to set the appropriate bits
// on the next character c
nextStateSet |= mDeltaTable[s][c - '0'];
} catch (ArrayIndexOutOfBoundsException ex) { }
}
}
mStateSet = nextStateSet;
}
}
References
• A. Brooks Weber. Formal Language: A
Practical Introduction. Franklin, Beedle &
Associates.
• M. Davis, R. Sigal, E. Weyuker.
Computability, Complexity, & Languages:
Fundamentals of Theorectical Computer
Science. Academic Press.