Can someone help me convert grammar to regular expression and explain how to do it on some complex grammars?
S -> aA | bB
A -> aC | bC | a | b
B -> aC | bC | a | b
C -> aA
This grammar of yours:
S -> aA | bB
A -> aC | bC | a | b
B -> aC | bC | a | b
C -> aA
Happens to be a right-regular grammar. As such, it describes a regular language and can easily be converted to a deterministic finite automaton:
q s q'
S a A
S b B
A a (C)
A b (C)
B a (C)
B b (C)
(C) a A
(C) b [D]
[D] a [D]
[D] b [D]
Here, S is the initial state, C is accepting and D is dead. To get a regular expression, treat this automaton as a NFA and start replacing symbol labels with regular expressions eliminating states:
S = aA + bB
A = aC + bC + a + b
B = aC + bC + a + b
C = aA + bD
D = aD + bD
Notice that D = aD + bD = (a + b)D is only true if D = {}. Rewriting:
S = aA + bB
A = aC + bC + a + b
B = aC + bC + a + b
C = aA
Now we can safely eliminate C by substitution:
S = aA + bB
A = aaA + baA + a + b = (aa + ba)A + (a + b)
B = aaA + baA + a + b = (aa + ba)A + (a + b)
Now we can use the rule Z = xZ + y => Z = x*y:
S = aA + bB
A = (aa + ba)*(a + b)
B = aaA + baA + a + b = (aa + ba)A + (a + b)
Now substitute:
S = aA + bB
A = (aa + ba)*(a + b)
B = (aa + ba)(aa + ba)*(a + b) + (a + b)
Now again:
S = a(aa + ba)*(a + b) + b((aa + ba)(aa + ba)*(a + b) + (a + b))
Now we can group like terms:
S = (a(aa + bb)* + b(aa + ba)(aa + ba)* + b)(a + b)
Notice that b(aa + ba)(aa + ba)* + b can be factored b((aa + ba)(aa + ba)* + e) and that (aa + ba)(aa + ba)* + e = (aa + ba)*:
S = (a(aa + bb)* + b(aa + ba)*)(a + b)
We can factor again:
S = (a + b)(aa + ba)*(a + b)
This last expression is a good, concise, correct regular expression for your language. It basically encodes the idea "see one symbol, then see another symbol, but if you see a third symbol it had better not be a b".
Related
I have a function T which I'm wanting to maximise:
T = (B((A + 1.646) + 0.583 w) + 311)((1 + ((R + 0.553) + 0.0389 x)((D) + 0.0389 y)
with the constraints
w + x + y + z = 25
w >= 0
x >= 0
y >= 0
z >= 0
B, A, R, D are all constants.
How would I go about doing this?
I have tried the following code:
a = tf.where(tf.greater_equal(x,1.0),x*tf.math.log(b + 1e-19), (1-x)*tf.math.log(1 - b + 1e-19))
does not produce the same results as:
a = x*tf.math.log(b + 1e-19) + (1-x)*tf.math.log(1 - b + 1e-19)
Here x is a binary variable either 0 or 1. b is real valued between 0 and 1.
Is there something I am missing?
The way I compared the 2 answers was tf.reduce_sum(a)
Solution found: The 2 are indeed equivalent for x = 0 or x = 1. The data I used was a 2D tensor, which had some bits not 0 or 1.
This was discovered via
tf.unique(tf.reshape(x, (-1,))
Code sample:
# When x = 0.0
x = 0.0
b = 0.5
a = tf.where(tf.greater_equal(x,1.0),x*tf.math.log(b + 1e-19), (1-x)*tf.math.log(1 - b + 1e-19)) # -0.6931472 from (1-x)*tf.math.log(1 - b + 1e-19)
c = x*tf.math.log(b + 1e-19) + (1-x)*tf.math.log(1 - b + 1e-19) # 0 + (1-x)*tf.math.log(1 - b + 1e-19) = -0.6931472
# When x = 1.0
x = 1.0
b = 0.5
a = tf.where(tf.greater_equal(x,1.0),x*tf.math.log(b + 1e-19), (1-x)*tf.math.log(1 - b + 1e-19)) # -0.6931472 from x*tf.math.log(b + 1e-19)
c = x*tf.math.log(b + 1e-19) + (1-x)*tf.math.log(1 - b + 1e-19) # x*tf.math.log(b + 1e-19) + 0 = -0.6931472
# When x = 0.4
x = 0.4
b = 0.5
a = tf.where(tf.greater_equal(x,1.0),x*tf.math.log(b + 1e-19), (1-x)*tf.math.log(1 - b + 1e-19)) # -0.41588834 from (1-x)*tf.math.log(1 - b + 1e-19)
c = x*tf.math.log(b + 1e-19) + (1-x)*tf.math.log(1 - b + 1e-19) # x*tf.math.log(b + 1e-19) + (1-x)*tf.math.log(1 - b + 1e-19) = -0.27725 + -0.41588 = -0.6931471824645996.
The only case where both codes mentioned in your question will produce the same results is when x = 1 or 0.
tf.reduce_sum(a)
Here, a is a scalar so this won't change the value of a.
I saw some textbook about the worst-case space complexity of Fibonacci Sequence. However, I have the following question:
You can start with a concrete example and generalize. Start with n = 5.
S(5) = S(4) + c
= (S(3) + c) + c
= ((S(2) + c) + c) + c
= (((S(1) + c) + c) + c) + c
= S(1) + 4c
There are 4 c's when n = 5. In general, there are n-1 c's.
I may need your help with this quite simple thing:
This -> abc' + ab'c + a'bc + abc
can (I guess) be simplified to this -> ab+ac+bc.
But how in the world is this done with Boolean algebra?
I already reduced it to -> abc'+ab'c+bc by using the absorption rule on the last two terms [a'bc + abc]. But how can I reduce the rest of it to get the end result?
Before simplifying the expression I'll show you one nice trick that will be used later. For any two logical variables A and B the following holds:
A + AB = A(B + 1) = A
With this in mind let's simplify your expression:
abc' + ab'c + a'bc + abc = ac(b + b') + abc' + a'bc = ac + abc' + a'bc
We can expand ac in the following way using that 'trick' I mentioned before:
ac = ac + abc = ac(b + 1) = ac
Using this we get:
ac + abc' + a'bc =
ac + abc + abc' + a'bc =
ac + ab(c + c') + a'bc =
ac + ab + a'bc =
ac + ab + abc + a'bc =
ab + bc(a + a') + ac =
ab + ac + bc
Leading to the final expression you wanted to get in the first place.
I'm looking at an algorithm I'm trying to optimize, and it's basically a lot of bit twiddling, followed by some additions in a tight feedback. If I could use carry-save addition for the adders, it would really help me speed things up, but I'm not sure if I can distribute the operations over the addition.
Specifically if I represent:
a = sa+ca (state + carry)
b = sb+cb
can I represent (a >>> r) in terms of s and c?
How about a | b and a & b?
Think about it...
sa = 1 ca = 1
sb = 1 cb = 1
a = sa + ca = 2
b = sb + cb = 2
(a | b) = 2
(a & b) = 2
(sa | sb) + (ca | cb) = (1 | 1) + (1 | 1) = 1 + 1 = 2 # Coincidence?
(sa & sb) + (ca & cb) = (1 & 1) + (1 & 1) = 1 + 1 = 2 # Coincidence?
Let's try some other values:
sa = 1001 ca = 1 # Binary
sb = 0100 cb = 1
a = sa + ca = 1010
b = sb + cb = 0101
(a | b) = 1111
(a & b) = 0000
(sa | sb) + (ca | cb) = (1001 | 0101) + (1 | 1) = 1101 + 1 = 1110 # Oh dear!
(sa & sb) + (ca & cb) = (1001 & 0101) + (1 & 1) = 0001 + 1 = 2 # Oh dear!
So, proof by 4-bit counter example that you cannot distribute AND or OR over addition.
What about '>>>' (unsigned or logical right shift). Using the last example values, and r = 1:
sa = 1001
ca = 0001
sa >>> 1 = 0101
ca >>> 1 = 0000
(sa >>> 1) + (ca >>> 1) = 0101 + 0000 = 0101
(sa + ca) >>> 1 = (1001 + 0001) >>> 1 = 1010 >>> 1 = 0101 # Coincidence?
Let's see whether that is coincidence too:
sa = 1011
ca = 0001
sa >>> 1 = 0101
ca >>> 1 = 0000
(sa >>> 1) + (ca >>> 1) = 0101 + 0000 = 0101
(sa + ca) >>> 1 = (1011 + 0001) >>> 1 = 1100 >>> 1 = 0110 # Oh dear!
Proof by counter-example again.
So logical right shift is not distributive over addition either.
No, you cannot distribute AND or OR over binary operators.
Explanation
Let P be a proposition where P: (A+B)&C = A&C + B&C
let us take A=2,B=3 =>A+B=5.
We are to prove A&C + B&C != (A+B)&C
A=2= 010
B=3= 011
let 010&C = x,
where x is some integer whose value is the resultant of bitwise AND of 010 and C
similarly 011&C = y, where y is some integer whose value is the resultant of bitwise AND of 011 and C
since we cannot say P holds for all C in the set of Natural numbers ( {0,1,...} ), consequently P is false.
In this case, take C=2=010
x=010 & 010 = 010 = 2
y=011 & 010 = 010 = 2
5&2=101 & 010 = 000 = 0
clearly, x+y!=0 , which means (A+B)&C != A&C + B&C.
Hence proved!