Context Free pumping lemma - theory

Is the following language context free?
L = {a^i b^k c^r d^s | i+s = k+r, i,k,r,s >= 0}
I've tried to come up with a context free grammar to generate this but I can not, so I'm assuming its not context free. As for my proof through contradiction:
Assume that L is context free,
Let p be the constant given by the pumping lemma,
Choose string S = a^p b^p c^p d^p where S = uvwxy
As |vwx| <= p, then at most vwx can contain two distinct symbols:
case a) vwx contains only a single type of symbol, therefore uv^2wx^2y will result in i+s != k+r
case b) vwx contains two types of symbols:
i) vwx is composed of b's and c's, therefore uv^2wx^2y will result in i+s != k+r
Now my problem is that if vwx is composed of either a's and b's, or c's and d's, then pumping them won't necessary break the language as i and k or s and r could increase in unison resulting in i+s == k+r.
Am I doing something wrong or is this a context free language?

I can't come up with a CFG to generate that particular language at the top of my head either, but we know that a language is context free iff some pushdown automata recognizes it.
Designing such a PDA won't be too difficult. Some ideas to get you started:
we know i+s=k+r. Equivalently, i-k-r+s = 0 (I wrote it in that order since that is the order in they appear). The crux of the problem is deciding what to do with the stack if (k+r)>i.
If you aren't familiar with PDA's or cannot use them to answer the problem, at least you know now that it is Context Free.
Good luck!

Here is a grammar that accepts this language:
A -> aAd
A -> B
A -> C
B -> aBc
B -> D
C -> bCd
C -> D
D -> bDc
D -> ε

Related

Loops in Lean programming language

I'm starting to learn about Lean programming language https://leanprover.github.io
I've found out that there are functions, structures, if/else, and other common programming commands.
However, I haven't found anything to deal with loops. Is there a way of iterating or repeating a block of code in Lean? Something similar to for or while in other languages. If so, please add the syntaxis or an example.
Thank you in advance.
Like other functional programming languages, loops in Lean are primarily done via recursion. For example:
-- lean 3
def numbers : ℕ → list ℕ
| 0 := []
| (n+1) := n :: numbers n
This is a bit of a change of mindset if you aren't used to it. See: Haskell from C: Where are the for Loops?
To complicate matters, Lean makes a distinction between general recursion and structural recursion. The above example is using structural recursion on ℕ, so we know that it always halts. Non-halting programs can lead to inconsistency in a DTT-based theorem prover like lean, so it has to be strictly controlled. You can opt in to general recursion using the meta keyword:
-- lean 3
meta def foo : ℕ → ℕ
| n := if n = 100 then 0 else foo (n + 1) + 1
In lean 4, the do block syntax includes a for command, which can be used to write for loops in a more imperative style. Note that they are still represented as tail-recursive functions under the hood, and there are some typeclasses powering the desugaring. (Also you need the partial keyword instead of meta to do general recursion in lean 4.)
-- lean 4
partial def foo (n : Nat) : Nat :=
if n = 100 then 0 else foo (n + 1) + 1
def mySum (n : Nat) : Nat := Id.run do
let mut acc := 0
for i in [0:n] do
acc := acc + i
pure acc

Why is this DFA not accepted?

So I am supposed to construct a DFA that accepts sets of all strings over {0,1} of length 2:
So sigma = {0,1}
L = {00, 01, 10, 11}
What I initially tried was :
Why is it wrong?
Assuming B is final state, it can even accept string of length 1. Thats why. Add one more state to mark length 2 and it should be good.
A 0,1 B 0,1 (C) 0,1 D
( ) - accepted state
Also make sure anything more than length 3 results in non terminal state by adding a D.
This is the DFA you want:
This way, if another input symbol is present after the second one - you go from C to D and can never go back to an accepting state.
By the way, and perhaps more importantly - I didn't draw this image myself. I used graphviz, which is a neet tool you might use to visualize your DFAs. The code is:
digraph G {
node [shape="circle"];
Start [shape="none" label=""];
C [shape="doublecircle"];
Start -> A;
A -> B [label="0,1"];
B -> C [label="0,1"];
C -> D [label="0,1"];
D -> D [label="0,1"];
}
and there are online renderers even, like this one.
The "Start" node is a hack to get an arrow to point at the initial state of the DFA (this is why the image is centered on B despite there being 4 states).

Regular Languages and Concatenation

Regular languages are closed under concatenation - this is demonstrable by having the accepting state(s) of one language with an epsilon transition to the start state of the next language.
If we consider the language L = {a^n | n >=0}, this language is regular (it is simply a*). If we concatenate it with another language L = {b^n | n >=0}, which is also regular, we end up with a^nb^n, but we obviously know this isn't regular.
Where am I going wrong with my logic here?
The definition of the concatenation of two languages L1 and L2 is the set of all strings wx where w &in; L1 and x &in; L2. This means that L1L2 consists of all possible strings formed by pairing one string from L1 and one string from L2, which isn't necessarily the same as pairing up matching strings from each language.
As a result, as #Oli Charlesworth pointed out, the language you get back here isn't actually { anbn | n in N }. Instead, it's the language { anbm | n in N and m in N }, which is the language a*b*. This language is regular, since it's given by the regular languages.
Hope this helps!

Is Wikipedia's Astar reference implementation incomplete? It seems to omit properly updating cheaper paths

I want to implement A* and I looked to Wikipedia for a reference.
It looks like it can fail in the following case. Consider three nodes, A, B, and C.
START -> A -> C -> GOAL
| ^
\-> B
The path costs are:
START -> A : 10
START -> B : 1
B -> A : 1
A -> C : 100
C -> GOAL : 100
Clearly the solution is START -> B -> A -> C -> GOAL but what happens if the heuristic lets us expand A before expanding B?
Our heuristic costs are as follows (note these are all underestimates)
A -> GOAL : 10
B -> GOAL : 50
When A is expanded, the true cost to C will turn out out to be higher than B's heuristic cost, and so B will be expanded before C.
Fine, right?
The problem I see is that when we expand B and replace the datum "A comes from START with cost 10" to "A comes from B with cost 2" we aren't also updating "C comes from A with cost 110" to "C comes from A with cost 102". There is nothing in Wikipedia's pseudocode that looks like it will forward-propagate the cheaper path. Now imagine another node D which can reach C with cost 105, it will erroneously override "C comes from A with cost 110".
Am I reading this wrong or does Wikipedia need to be fixed?
If you are using graph search, i.e. you remember which nodes you visit and you don't allow revisiting the nodes, then your heuristic is not consistent. It says in the article, that for a heuristic to be consistent, following needs to hold:
h(x) <= d(x, y) + h(y) for all adjacent nodes x, y
In your case the assumption h(B) = 50 is inconsistent as d(B -> A) + h(A) = 1 + 10 = 11. Hence your heuristic is inconsistent and A* wouldn't work in this case, as you rightly noticed and as is also mentioned in the wikipedia article: http://en.wikipedia.org/wiki/A%2a_search_algorithm#Properties.
If you are using tree search, i.e. you allow the algorithm to revisit the nodes, the following will happen:
Add A and B to the queue, score(A) = 10 + 10 = 20, score(B) = 1 + 50 = 51.
Pick A from queue as it has smallest score. Add C to the queue with score(C) = 10 + 100 + h(C).
Pick B from the queue as it is now the smallest. Add A to the queue with score(A) = 2 + 10 = 12.
Pick A from the queue as it is now again smallest. Notice that we are using tree search algorithm, so we can revisit nodes. Add C to the queue with score(C) = 1 + 1 + 100 + h(C).
Now we have 2 elements in the queue, C via A with score 110 + h(C) and C via B and A with score 102 + h(C), so we pick the correct path to C via B and A.
The wikipedia pseudocode is the first case, i.e. graph search. And they indeed state right under the pseudocode that:
Remark: the above pseudocode assumes that the heuristic function is monotonic (or consistent, see below), which is a frequent case in many practical problems, such as the Shortest Distance Path in road networks. However, if the assumption is not true, nodes in the closed set may be rediscovered and their cost improved. In other words, the closed set can be omitted (yielding a tree search algorithm) if a solution is guaranteed to exist, or if the algorithm is adapted so that new nodes are added to the open set only if they have a lower f value than at any previous iteration.

Decomposing into BCNF

Suppose R = {A,B,C,D}
And FD = C→D,C→A,B→C
I am supposed to find:
1. the key(s)
2. the NF it is in
3. the BCNF (if possible and if not in already)
So here's what I've got so far:
the key is B since it transitively determines C which determines D and A.
it is in 2NF since dependancies are on the whole key
R1 = {B,C} R2 = {C, A, D}
So here's where I have an issue. The mark scheme says to decompose R into AC, BC, and CD. But why wouldn't my answer be right? Am I saying the FD is C -> {A,D} and if so is this difference to C -> A and C -> D?
When you're asked to compute the minimum cover of R, you're usually expected to answer like this.
C -> D
C -> A
B -> C
When you're asked to elevate R to BCNF, you're usually expected to answer like this.
B C
C AD
If you're not using a standard textbook, I can't give you any suggestions. Questions and answers written by TAs (teaching assistants) are particularly hard to understand. Sometimes they're just wrong.

Resources