- Consider
$f_1: {0, 1}^* \rightarrow {0, 1}$ and$f_2: {0, 1}^* \rightarrow {0, 1}$ - Let us define
$f_1 CAT f_2: {0, 1}^* \rightarrow {0, 1}$ -
$f_1CATf_2(x)$ is 1 if$f_1(x_1) =1$ and$f_2(x_2) = 1$ , where$x = x_1x_2$ - This is splitting the input and putting each split as an input - the entire concatenation function is satisfied if each split is satisfied
-

- Example:
-
$f_1 CAT f_2$ , in general, can be calculated using DFAs- If
$f_1: {0 ,1}^* \rightarrow {0, 1}$ ,$f_2: {0 ,1}^* \rightarrow {0, 1}$ are computable by a DFA, then$f_1 CAT f_2: {0, 1}^* \rightarrow {0, 1}$ is also computable by a DFA - Pseudocode Intuition:
-
def CONCAT(f1, f2, x): ans = 0 for i in range(len(x)): x1 = x[0:i] x2 = x[i:len(x)] if f_1(x) AND f_2(x) == 1: return 1 return 0- This is not a single pass algorithm
-
- Let
$f_{reverse}: {0, 1}^* \rightarrow {0, 1}$ be another operation that evaluates the function but on a reversed$x$ - that is,$f_{reverse}(x) = f(reverse(x))$ - If
$f$ is computable by a DFA, then so is$f_{reverse}$ - This cannot necessarily be done, though, by just reversing all state directions and changing the starting state to be the ending state
- If
- If
- A non-deterministic finite automata can have multiple outgoing edges with the same label out of a state, some edges are labeled by
$\epsilon$ , and some edges can go missing (i.e. they go to a dead state - this is just to make syntax easier) - Example:
- Example:
- Formal Definition:
-
$N = (T, S)$ $S \subseteq [C]$ -
$T: [C] \times {0, 1, \epsilon } \rightarrow Power([C])$ - Recall the power set:
$[C] = {0, 1, 2, ..., C - 1}$ ,$Power([C]) = {I: I \subseteq [C]}$ i.e. all possible subsets of C, including the empty set$\emptyset$ which represents a dead state
- Recall the power set:
- On an input
$x$ ,$N(x)$ is$1$ if on any branch the final state is in$S$ and$0$ otherwise
-
- Formal Example:
- A function
$f: {0, 1}^* \rightarrow {0, 1}$ is computable by an NFA$N$ if$\forall x$ ,$f(x) = N(x)$ - If
$f_1: {0, 1}^* \rightarrow {0, 1}$ is computable by a DFA$D_1$ and$f_2: {0, 1}^* \rightarrow {0, 1}$ is computable by a DFA$D_2$ , then$f_1 CAT f_2: {0, 1}^* \rightarrow {0, 1}$ is computable by a NFA - If
$f: {0, 1}^* \rightarrow {0, 1}$ is computable by a DFA$D$ , then$f_{reverse}$ is computable by an NFA- This leverages the idea of reversing the arrows, with the new accepting state being the start state
- The new start state will be a single dummy state that has epsilon transitions to each original end state
- This leverages the idea of reversing the arrows, with the new accepting state being the start state











