automata-rich/03_language_hierarchy.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
--- geometry: - lmargin=0.9in - rmargin=0.15in - tmargin=0.2in - bmargin=0.5in - twoside papersize: a4 classoption: - twocolumn ... # Language Recognition - The unifying framework into which any computational problem can be cast is language recognition. - Given: - The definition of language *L* - A string *w*. we ask the question: "Is *w* in *L*?". This question is a part of a more general class of prblem called the decision problem which requires a yes or a no answer. # Notes ## The Framework - The Languages and strings concept give us a mathematical model to work with that can be used to solve computation problems of all sorts. - The language recognition task is similar to the way of defining a set using a *characteristic funtion* that decides whether an element is a part of the set or not. - "Is *w* in *L*?" is the decision that we have to take. That becomes our main task. The Language will obviously have to be defined and all the strings have to examined to make sure it's in *L*. ## Encoding - Now we have the fundamental question to ask, "Is *w* in *L*?" which might seem limiting. So we need to figure out a way to "recast" a computational problem, more complex into the form "Is *w* in *L*?" - We use *encoding* for that. We express the objects as strings using an encoding and resulting strings are a part of the language *L*. We can then ask the question "Is *w* in *L*?" - **Everything is a string**. Using strings as an abstraction is useful for the mathematical model we are building. Dealing with strings is what is crucial in theory of computation. And in fact the most basic and fundamental units of computers are 0s and 1s which are essential the two characters in the alphabet and every combination of them is a string. And all of computing is formed by these strings of 0s and 1s. - The encoding will obviously have to be specified for each problem. For example A graph can be encoded as follows - Start with the binary representation of the number of vertices $|V|$ - List the edges in the graph as pairs of vertices represented by a pair of binary numbers - separate the binary numbers using '/' \begin{figure}[h] \includegraphics[width=0.8in]{img/graph} \centering \end{figure} The above graph can then be represented as:\ `101/1/10/10/11/1/100/10/101` Thus we have encoded a graph as a string. If $G$ was the graph then $<G>$ represents the string encoding of the graph. - Encoding simply lets us express problems' entities as strings and we can then define a language and ask the fundamental question "Is *w* in *L*?" - For problems that are not decision problems we can reformulate them using encoding to turn them into decision problems. The idea is to have the inputs and the outputs of a problem *P* into a single string. This way we can have a language constructed that has the correct outputs corresponding to the correct inputs for that problem. - When we have the decision question we can reduce it to the original problem. This simply means that if we have a program that solves *P* we can use it to construct a program that decides the language *L* for it. And if we have the language *L* we can construct the program to solve *P* by checking if the encoded problem string (inputs and outputs in a single string) for the particular instance of the problem, is in *L* or not. ## Machine-based hierarchy of language classes - Regular languages (FSM) - Context-Free languages (PDA) - Decidable and Semidecidable languages (Turing Machine) \begin{figure}[h] \includegraphics[width=2in]{img/languages-hier} \centering \end{figure} - **Regular Languages** - languages that can be accepted by some FSM are called regular languages. We can have an FSM for $$L=\{w \in \{\texttt{a,b}\}^\ast: \text{all a's come before b's in } w\}$$ - **Context-Free Languages** - languages that can be accepted by a PDA. A PDA is a pushdown automata and is similar to an FSM but it also has a stack. the notation *x/y/z* is used as a label for an arc to show that if *a* is read then pop *y* from the stack if possible and push *z* to the stack if possible and move to the pointed state. $x/\epsilon /z$ would mean "don't check the stack but push *z* if *x* read". $x/y/\epsilon$ would mean pop *y* and don't push anything if *x* read. We can build a PDA for: $$ L = \{a^nb^n : n\geq 0\}$$ - **Decidable Languages** - languages for which a Turing machine halts on all inputs. It's guaranteed to give a 'yes' or a 'no'. One such example is: $$ L = \{a^nb^nc^n : n\geq 0\}$$ - **Semidecidable Languages** - languages for which a Turing machine is not guaranteed to halt. It may accept a string in *L* but may not be able to reject a string not in *L* i.e., it might not know when to stop looking for an answer.