Prove that the following language is regular: - regular-language

Let L1, L2 be regular languages. And let A1=〈Σ,Q,q0,𝛿1,F1), A2=〈Σ,P,p0,𝛿2,F2) be their DFA.
Prove that the following language is regular, by making an appropriate NFA for it:
𝐿3={𝜎1𝜎1β€²πœŽ2𝜎2β€²β€¦πœŽπ‘›πœŽπ‘›β€² |𝜎1𝜎2β€¦πœŽπ‘›βˆˆπΏ1,𝜎1β€²πœŽ2β€²β€¦πœŽπ‘›β€² ∈𝐿2} (Meaning, the language of all words in which the letters on the even positions (starting from 0) are from L1 and the letters on the odd positions are from L2.
Would appreciate help with that.
Thank you.

Consider the following automaton:
alphabet Ξ£
set of states (Q x P) union (P x Q)
initial state (q0, p0)
final states (f1, f2) where f1 and f2 are in F1 and F2, respectively
transition function that takes (q, p) to (p, q') on symbol s if 𝛿1 takes q to q' on s, and which takes (p, q) to (q, p') on symbol s if A2 takes p to p' on symbol s.
Suppose that you have a word w in L3. Does our machine accept it? The sequence 𝜎1, 𝜎2, …, 𝜎n will cause the first component of the state in which the automaton arrives to be the same as the state A1 would have arrived in had A1 processed just this sequence. Since L3 says this sequence in w is a word in L1, the state should have been accepting in A1 and so the first component is in F1. Similarly, the sequence 𝜎1', 𝜎2', …, 𝜎n' is a string in L2 and so the state it arrives at is accepting. Thus, the state reached by this NFA is of the form (f1, f2) and thus the string is accepted, as it must be. We have just argued that the NFA accepts at least the strings in this language. What remains is to argue that it does not accept anything else.
Fortunately, the remainder of the argument is straightforward, and we probably could have done it at the same time as we did the above one. It follows the same format. Suppose our NFA arrives at one of the accepting states. Then it's of the form (f1, f2). That means we saw an even-length string where the odd-index symbols considered together led to f1 in A1 and the even-index symbols led to f2 in A2. But that means the sequences were accepting in their respective automata and so the string that led us to the accepting state in our machine must be a word in L3. We have just argued that the NFA accepts at most the strings in this language.
Since our machine accepts at least the strings we need, and at most the strings we need, it follows that it accepts exactly the strings we need.

Related

Complement of a given Language for a DFA

For DFA, the alphabet Ξ£ = {a,b} the language this DFA will recognise is {w|w must contain a}. For this language that the DFA recognises, what would be the compliment of this language or how would it be written please?
I can't work out if b should also be in the compliment of the language or not. a I know should be excluded from the compliment as it is in the original L or language.
I would have posted an image of the alphabet but I don't have enough points or reputation to.
I am unable to determine the complement of the language that the DFA recognises
The complement of the language {w in {a, b}* | w must contain a} is the language {w in {a, b}* | w contains no a}. Strings in this language can be empty or consist of any number of b; the regular expression for this is b* and there is a 2-state minimal DFA that loops on the accepting initial state in case of b, and goes to a non-accepting dead state in case of a, where both transitions from the dead state are loops back to the dead state itself.

Regular language demonstration

Consider this function:
Faro(x,z) that assume value: z if x = Ξ΅ and a.faro(z,y) if x = ay
So is a recursive function, and for instance we have as result of faro(00110, 0101) = 000110110
I have to demonstrate that if L and M are regular language on the same alphabet we have that faro(L,M) = {faro(x,z) | x is on L and z is on M} is regular.
I'm not sure which is the best method to demonstrate the result. I'm now studying this type of problem for the first time.
Is more convenient to create a DFA or use the pumping lemma?
It looks like what's going on here is that the faro function takes two strings and interleaves them: faro(a1a2a3...an, b1b2b3...bm) = a1b1a2b2a3b3...anbn...bm (assuming w.l.o.g. m >= n).
If you can demonstrate that semantic fact about the faro function to your and others' satisfaction, then producing a NFA that does the same thing seems to be within reach:
create four states in the NFA for each triple (q, q', s) where q is a state in L's DFA, q' is a state in M's DFA, and s is either L, M, L' or M';
make the start state (q0, q0', L) to signify that we will start reading according to L's DFA with the possibility of alternating still available
probably, the accepting states are just those where q is accepting in L's DFA and q' is accepting in M's DFA... but I will let you work through the details here
the transitions will work as follows:
When you see symbol a in state (q, q', L), then go to states (w, q', M) and (w, q', L'), where L's DFA transitions from q to w on a. This means we can either accept the next interleaved symbol of the string from M, or we can just read the rest of the string from L without a possibility of taking any more of the string from M
When you see symbol a in state (q, q', M), go to states (q, w', L) and (q, w', M'), similar to above
When you see symbol a in state (q, q', L'), go to state (w, q', L'); remember, L' means we gave up on reading interleaved symbols from the string in M
When you see symbol a in state (q, q', M'), go to the state (q, w', M'), similar to the above
This is an NFA so if at least one path through accepts, the string is accepted. This is as it should be since if a string can be interpreted as some result of faro(x, y) for x in L and y in M, our NFA should accept it. Our NFA works by keeping track of:
how much of x has been read so far, by the component q in (q, q', s)
how much of y has been read so far, by the component q' in (q, q', s)
whether we need to read a symbol from x or y next, by the component s in (q, q', s)
whether we will subsequently be able to read from x or y, by the component s in (q, q', s)
I think the next steps are probably doing a couple of simple examples to see whether this construction works and, if so, then proceeding to prove that this NFA's language is the one desired (a proof by induction would be a good idea here). Once you prove there's an NFA for your language, you're done.

If Either can be either Left or Right but not both, then why does it correspond to OR instead of XOR in Curry-Howard correspondence?

When I asked this question, one of the answers, now deleted, was suggesting that the type Either corresponds to XOR, rather than OR, in the Curry-Howard correspondence, because it cannot be Left and Right at the same time.
Where is the truth?
If you have a value of type P and a value of type Q (that is, you have both a proof of P and a proof of Q), then you are still able to provide a value of type Either P Q.
Consider
x :: P
y :: Q
...
z :: Either P Q
z = Left x -- Another possible proof would be `Right y`
While Either does not have a specific case that explicitly represents this situation (unlike These), it does not do anything to exclude it (as in exclusive OR).
This third case where both have proofs is a bit different than the other two cases where only one has a proof, which reflects the fact that "not excluding" something is a bit different than "including" something in intuitionistic logic, since Either does not provide a particular witness for this fact. However Either is not an XOR in the way that XOR would typically work since, as I said, it does not exclude the case where both parts have proofs. What Daniel Wagner proposes in this answer, on the other hand, is much closer to an XOR.
Either is kind of like an exclusive OR in terms of what its possible witnesses are. On the other hand, it is like an inclusive OR when you consider whether or not you can actually create a witness in four possible scenarios: having a proof of P and a refutation of Q, having a proof of Q and a refutation of P, having a proof of both or having a refutation of both.[1] While you can construct a value of type Either P Q when you have a proof of both P and Q (similar to an inclusive OR), you cannot distinguish this situation from the situation where only P has a proof or only Q has a proof using only a value of type Either P Q (kind of similar to an exclusive OR). Daniel Wagner's solution, on the other hand, is similar to exclusive OR on both construction and deconstruction.
It is also worth mentioning that These more explicitly represents the possibility of both having proofs. These is similar to inclusive OR on both construction and deconstruction. However, it's also worth noting that there is nothing preventing you from using an "incorrect" constructor when you have a proof of both P and Q. You could extend These to be even more representative of an inclusive OR in this regard with a bit of additional complexity:
data IOR a b
= OnlyFirst a (Not b)
| OnlySecond (Not a) b
| Both a b
type Not a = a -> Void
The potential "wrong constructor" issue of These (and the lack of a "both" witness in Either) doesn't really matter if you are only interested in a proof irrelevant logical system (meaning that there is no way to distinguish between any two proofs of the same proposition), but it might matter in cases where you want more computational relevance in the logic.[2]
In the practical situation of writing computer programs that are actually meant to be executed, computational relevance is often extremely important. Even though 0 and 23 are both proofs that the Int type is inhabited, we certainly like to distinguish between the two values in programs, in general!
Regarding "construction" and "destruction"
Essentially, I just mean "creating values of a type" by construction and "pattern matching" by destruction (sometimes people use the words "introduction" and "elimination" here, particularly in the context of logic).
In the case of Daniel Wagner's solutions:
Construction: When you construct a value of type Xor A B, you must provide a proof of exactly one of A or B and a refutation of the other one. This is similar to exclusive or. It is not possible to construct a value of this unless you have a refutation of either A or B and a proof of the other one. A particularly significant fact is that you cannot construct a value of this type if you have a proof of both A and B and you don't have a refutation of either of them (unlike inclusive OR).
Destruction: When you pattern match on a value of type Xor A B, you always have a proof of one of the types and a refutation of the other. It will never give you a proof of both of them. This follows from its definition.
In the case of IOR:
Construction: When you create a value of type IOR A B, you must do exactly one of the following: (1) provide only a proof of A and a refutation of B, (2) provide a proof of B and a refutation of B, (3) provide a proof of both A and B. This is like inclusive OR. These three possibilities correspond exactly to each of the three constructors of IOR, with no overlap. Note that, unlike the situation with These, you cannot use the "incorrect constructor" in the case where you have a proof of both A and B: the only way to make a value of type IOR A B in this case is to use Both (since you would otherwise need to provide a refutation of either A or B).
Destruction: Since the three possible situations where you have a proof of at least one of A and B are exactly represented by IOR, with a separate constructor for each (and no overlap between the constructors), you will always know exactly which of A and B are true and which is false (if applicable) by pattern matching on it.
Pattern matching on IOR
Pattern matching on IOR works exactly like pattern matching on any other algebraic datatype. Here is an example:
x :: IOR Char Int
x = Both 'c' 3
y :: IOR Char Void
y = OnlyFirst 'a' (\v -> v)
f :: Not p -> IOR p Int
f np = OnlySecond np 7
z :: IOR Void Int
z = f notVoid
g :: IOR p Int -> Int
g w =
case w of
OnlyFirst p q -> -1
OnlySecond p q -> q
Both p q -> q
-- We can show that the proposition represented by "Void" is indeed false:
notVoid :: Not Void
notVoid = \v -> v
Then a sample GHCi session, with the above code loaded:
ghci> g x
3
ghci> g z
7
[1]This gets a bit more complex when you consider that some statements are undecidable and therefore you cannot construct a proof or a refutation for them.
[2]Homotopy type theory would be one example of a proof relevant system, but this is reaching the limit of my knowledge as of now.
The confusion stems from the Boolean truth-table exposition of logic. In particular, when both arguments are True, OR is True, whereas XOR is False. Logically it means that to prove OR it's enough to provide the proof of one of the arguments; but it's okay if the other one is True as well--we just don't care.
In Curry-Howard interpretation, if somebody gives you an element of Either a b, and you were able to extract the value of a from it, you still know nothing about b. It could be inhabited or not.
On the other hand, to prove XOR, you not only need the proof of one argument, you must also provide the proof of the falsehood of the other argument.
So, with Curry-Howard interpretation, if somebody gives you an element of Xor a b and you were able to extract the value of a from it, you would conclude that b is uninhabited (that is, isomorphic to Void). Conversely, if you were able to extract the value of b, then you'd know that a was uninhabited.
The proof of falsehood of a is a function a->Void. Such a function would be able to produce a value of Void, given a value of a, which is clearly impossible. So there can be no values of a. (There is only one function that returns Void, and that's the identity on Void.)
Perhaps try replacing β€œproof” in the Curry-Howard isomorphism with β€œevidence”.
Below I will use italics for propositions and proofs (which I will also call evidence), the mathematical side of the isomorphism, and I will use code for types and values.
The question is: suppose I know the type for [values corresponding to] evidence that P is true (I will call this type P), and I know the type for evidence that Q is true (I call this type Q), then what is the type for evidence of the proposition R = P OR Q?
Well there are two ways to prove R: we can prove P, or we can prove Q. We could prove both but that would be more work than necessary.
Now ask what the type should be? It is the type for things which are either evidence of P or evidence of Q. I.e. values which are either things of type P or things of type Q. The type Either P Q contains precisely those values.
What if you have evidence of P AND Q? Well this is just a value of type (P, Q), and we can write a simple function:
f :: (p,q) -> Either p q
f (a,b) = Left a
And this gives us a way to prove P OR Q if we can prove P AND Q. Therefore Either cannot correspond to xor.
What is the type for P XOR Q?
At this point I will say that negations are a bit annoying in this sort of constructive logic.
Let’s convert the question to things we understand, and a simpler thing we don’t:
P XOR Q = (P AND (NOT Q)) OR (Q AND (NOT P))
Ask now: what is the type for evidence of NOT P?
I don’t have an intuitive explanation for why this is the simplest type but if NOT P were true then evidence of P being true would be a contradiction, which we say as proving FALSE, the unprovable thing (aka BOTTOM or BOT). That is, NOT P may be written in simpler terms as: P IMPLIES FALSE. The type for FALSE is called Void (in haskell). It is a type which no values inhabit because there are no proofs of it. Therefore if you could construct a value of that type you would have problems. IMPLIES corresponds to functions and so the type corresponding to NOT P is P -> Void.
We put this with what we know and get the following equivalence in the language of propositions:
P XOR Q = (P AND (NOT Q)) OR (Q AND (NOT P)) = (P AND (Q IMPLIES FALSE)) OR ((P IMPLIES FALSE) AND Q)
The type is then:
type Xor p q = Either (p, q -> Void) (p -> Void, q)

Finding error in proof stating the language L = {0^(n)1^(n) | n>0} is a regular expression

Proof: Let M be the following NFA:
Automata for L
Now, if x is in L, then x = 0^(n)1^(n). Thus while processing x, M will start in state q0, loop in state q0 n times, then transition to state q1 on the rst 1, and follow the loop in state q1 a total of n τ€€€ 1 times. Since it ends in state q1, x will be accepted. Thus M recognizes every string in L, so L is NFA-recognizable (and by Kleene's theorem, is thus regular).
You've shown that M accepts every string of L. But that doesn't mean that M recognizes L: for that to be true, you have to also show that M accepts exactly the strings of L and no others (or equivalently: it doesn't accept any string not in L). Unfortunately in your case, M does accept some non-L strings: for example, "011".
Your proof is indeed wrong. To prove that the language L is regular you need to prove that there exists a finite state automaton M that recognizes the language L. Hence, there are three things that you need to prove about the automaton M:
The automaton M exists.
The automaton M recognizes the language L (nothing more, nothing less).
The automaton M has a finite number of states.
The problem with your proof is that the automaton you posted does not recognize the language L:
This automaton recognizes the language 0*1+ which is not the same as the language L (0^n1^n). Yes, every string in L is recognized by this automaton. However, this automaton also recognizes strings like 1 which is clearly not in L. Hence, using this automaton in your proof is wrong.
So, how do you prove that the automaton M exists? Well, the only way to prove that the automaton M exists is by showing that M exists. The only problem is that L is not a regular language. Hence, there is no finite state automaton M that recognizes L.
The opposite way is to prove that L is not a regular language. To prove that L is not a regular language you need to prove that there is no finite state automaton M that recognizes L. This is an easier proof because you don't have to find the automaton M. You can just assume that it exists.
Here's what you need to do to prove that L is not a regular language:
Assume that an automaton M exists that recognizes the language L.
Show that M must necessarily have an infinite number of states.
The standard way of proving that an automaton M cannot have a finite number of states is by using the Pumping Lemma. I'll leave it as an exercise for you to figure that out because it's not in the scope of your question.

Haskell starter questions... please explain it to me

I am supposed to write some haskell program but I don't really know where to start. I will be really really grateful if you can point me to some resources to read or explain me the question. I am sure this is something totally amateurish, but I really need a starting point.
data DFA q o = DFA (q -> o -> q) q [q]
data NFA q o = NFA (q -> o -> [q]) [q] [q]
-- I really realy don't understand the declarations here
-- I can guess that q is somewhat related to Q and o to E, but don't get what it really means
data Q = Q0 | Q1 | Q2
deriving (Eq, Enum, Bounded)
data E = A | B
-- what does n1 do ??
n1 :: NFA Q E
n1 = NFA d [Q0] [Q2] -- i see [Q0] refers to set of initial states and [Q2] refers to final states :)
where
d Q0 A = [Q0]
d Q0 B = [Q0, Q1]
d Q1 _ = [Q2]
d Q2 _ = []
-- the following functions are for me to write
starDFA :: Eq q => DFA q o -> [o] -> Bool
--for the above function, what are the arguments the function takes in ?
--how can we relate q with Q and [o] with [E] ??
Any explanations or references to proper starting points will be really helpful to me.
Sorry to ask such a dumb question, but I really don't know where to start :)
Thanks
Learn You a Haskell for Great Good! is probably the best Haskell tutorial at the moment. I recommend reading through the whole thing, but if you are in a hurry, I'll point out some of the more relevant sections for this assignment.
The main part in the code you are given are the data declarations, so once you're familiar with the basics (chapter 2 and the first section of chapter 3), a good place to dive in is the Algebraic data types intro, Type variables and Type parameters.
The above should be enough for deciphering the data declarations and understanding the relationship between q vs Q and o vs E.
Now to implement the actual function, you need to be familiar with how deterministic finite automata work and then know enough Haskell to write the actual implementation. Chapter 4 and chapter 5 are the most relevant chapters for this in the tutorial and you might also find the section on standard library list functions useful.
Once you get to this point, if you are stuck with the implementation, you can post another question with the code you have written so far.
In haskell we have three way to define new type, using three distinct keywords, type, newtype, and data.
In your example it's data keyword which is in use, let's focus a bit more on it.
It's better to start with the easiest one coming from your code
data E = A | B
Here, We have define a new type E which can take only two mode or state or value.
A type like this is what we call a sum type.
How can we use a it ?
Mostly with pattern matching.
useE :: E -> String
useE A = "This is A"
useE B = "This is B"
Now, a more complex data declaration from your code.
data Q = Q0 | Q1 | Q2 deriving (Eq, Enum, Bounded)
Again, as said previously we have a sum type which define a new type Q, taken three value, Q0, Q1 or Q2. But we have a deriving clause, which tell to the compiler that this new type implement the method (or function) deriving (or inherited) from Eq, Enum, Bounded class.
What's that mean ?
Let's take a look to a function.
Imagine you want to associate a number for each of the value of Q, how can we perform that ?
enumQ :: Q -> Int
enumQ x = fromEnum x
If you want more insight about this particular functionality provide by deriving clause, read the resources which have been indicated and try :info Enum under ghci. Note that the previous type could also derive from the same class. As these types are fully describe as the sum of an enumerable set of value (discriminated by |) we better understand why we call them sum type.
Finally the most difficult data declaration.
data DFA q o = DFA (q -> o -> q) q [q]
data NFA q o = NFA (q -> o -> [q]) [q] [q]
If fact they are almost the same data definition then I will go trough the first one and let you the analyses of the second one as an exercise.
data DFA q o = DFA (q -> o -> q) q [q]
This time we must talk about data constructor and type constructor.
On the left hand side of the equality, there is data constructor,
to built data and give it a name. On this side we have the required
parameter used to built this new data.
On the right hand side of the equality, there is type constructor, to
built this new type. On this side we have the explicit
plumbering which show to the reader how this new type (data) is built
using the existing type.
Now keeping in mind, that the following are type,
[x] ::: Type representing the polymorphic list, Example, [Int] =>
List of Int
x ::: A basic type, one of the existing one (Int, Char, String ...)
x -> y ::: Type which define a function taken a type x to produce a
type y.
x -> y -> z ::: Type which define a function taken a type x and a
type y to produce a type z. Which can be view as a function taking another function of type (x->y) and producing a type z. This is what we call an High-Order Function.
Then our data declaration, put in this context, is a data constructor, feed by two type parameter, q and o and as a result, it return a new type as the product of a high-order function a basic type and a list type. Which explain why we call this a product type.
It should be enough, now, infering by yourself, to answer your question what does n1 ?
Good luck.
From the little I understand about Haskell type declarations, the initial statements about DFA and NFA are saying something like (looking at NFA, for example):
(Left hand side:) NFA is a type that utilizes two types (q and o) in its construction.
(Right hand side:) an instance of NFA will be called NFA, and be composed of three parameters:
(1) "(q -> o -> [q])" , meaning a function that takes two parameters, one of type q and one of type o, and returns a list of q's, ([q])
(2) "[q]" , meaning one list of values of type q
(3) "[q]" , another list of values of type q
n1 seems like an instance construction of NFA, and we see
n1 = NFA d [Q0] [Q2]
So we can infer that:
(1) d is a function that takes two parameters, a 'q' and an 'o' and returns a list of q's
(2) [Q0] is a list of q's, and
(3) [Q2] is a list of q's.
And, indeed, the definition of d follows:d takes two parameters, a 'Q' and an 'E' and returns a list of Q's (which we know can be either Q0, Q1, or Q2) or an empty list.
I hope that helps a little and/or perhaps someone could clarify and correct my vague understanding as well.

Resources