0% found this document useful (0 votes)
13 views9 pages

Hwsoln 11

This document contains solutions to homework problems related to computer science foundations. It includes proofs that the complexity class P is closed under various operations and an algorithm to check if a graph contains a triangle. The last problem provides a partial solution to the CYK algorithm on a context-free grammar.

Uploaded by

Sujan Mali
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views9 pages

Hwsoln 11

This document contains solutions to homework problems related to computer science foundations. It includes proofs that the complexity class P is closed under various operations and an algorithm to check if a graph contains a triangle. The last problem provides a partial solution to the CYK algorithm on a context-free grammar.

Uploaded by

Sujan Mali
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

CS 341: Foundations of Computer Science II

Prof. Marvin Nakayama

Homework 11 Solutions

1. Answer each part TRUE or FALSE.

(a) 2n = O(n). TRUE. We can see this by letting c = 2, and noting that 2n ≤
cn = 2n for all n ≥ 1. Thus, the definition of big-O holds for c = 2 and
n0 = 1.
(b) n2 = O(n). FALSE. For it to be true, we would need that there exist positive
constants c and n0 such that n2 ≤ cn for all n ≥ n0 . By dividing both sides
by n, we see that “n2 ≤ cn for all n ≥ n0 ” is true if and only if “n ≤ c for all
n ≥ n0 ” is true, but clearly there cannot exist constants c and n0 for which the
last statement is true.
(c) n2 = O(n log2 n). FALSE. To see why, note that n2 = O(n log2 n) if and
only if there exist positive constants c and n0 such that n2 ≤ cn log2 n for all
n ≥ n0 , which holds if and only if

n2
≤ c for all n ≥ n0 . (1)
n log2 n
By cancelling out an n from the numerator and denominator, we can rewrite
equation (1) as n/(log2 n) ≤ c for all n ≥ n0 . Writing n = n1/2 n1/2 , we see
that the last statement is true if and only if [n1/2 /(log n)]2 ≤ c for all n ≥ n0 .
But because we know that log n = o(n1/2 ), we have that n1/2 /(log n) → ∞ as
n → ∞, so [n1/2 /(log n)]2 ≤ c cannot be true for all n ≥ n0 for any constant
c.
(d) n log n = O(n2 ). TRUE. Because log n = O(n), there exist positive constants
c and n0 such that log n ≤ cn for all n ≥ n0 . Multiplying both sides by n gives
n log n ≤ cn2 for all n ≥ n0 for the same positive constants c and n0 , so
n log n = O(n2 ).
(e) 3n = O(2n ). FALSE. Suppose that it were true. Then there exists constants c
and n0 such that 3n ≤ c2n for all n ≥ n0 . The last requirement is equivalent to
(3/2)n ≤ c for all n ≥ n0 . However, (3/2)n → ∞ as n → ∞, so (3/2)n ≤ c
cannot be true for all n ≥ n0 for any constant c.
(f) 3n = 2O(n) . TRUE because 3n = 2n log2 3 = 2O(n) .
n n
(g) 22 = O(22 ). TRUE. Any function f (n) is O(f (n)).

1
2. Let b > 1 be a constant. Show that O(t(n)) × O(bt(n) ) = 2O(t(n)) .
Answer: Let f1 (n) = O(t(n)) and f2 (n) = O(bt(n) ), so we want to show that
f1 (n)f2 (n) = 2O(t(n)) . Because f1 (n) = O(t(n)), there exist constants c1 and n1
such that f1 (n) ≤ c1 t(n) for all n ≥ n1 . Because f2 (n) = O(bt(n) ), there exist
constants c2 and n2 such that f2 (n) ≤ c2 bt(n) for all n ≥ n2 . Consequently, letting
c0 = c1 c2 , we get
f1 (n) f2 (n) ≤ c0 t(n) bt(n)
for all n ≥ n0 ≡ max(n1 , n2 ). Now recall that x = 2log2 (x) for any x, so
t(n)
c0 t(n) bt(n) = 2log2 (c0 t(n) b )
= 2log2 (c0 )+log2 (t(n))+t(n) log2 (b)
= 2O(t(n))
because log2 (t(n)) = O(t(n)).
3. (a) Show that P is closed under union.
Answer: Suppose that language L1 ∈ P and language L2 ∈ P. Thus, there are
polynomial-time TMs M1 and M2 that decide L1 and L2 , respectively. Specifi-
cally, suppose that M1 has running time O(nk1 ), and that M2 has running time
O(nk2 ), where n is the length of the input w, and k1 and k2 are constants. A
Turing machine M3 that decides L1 ∪ L2 is the following:
M3 = “On input w:
1. Run M1 with input w. If M1 accepts, accept.
2. Run M2 with input w. If M2 accepts, accept.
Otherwise, reject.”
Thus, M3 accepts w if and only if either M1 or M2 (or both) accepts w. The
running time of M3 is O(nk1 ) + O(nk2 ) = O(nmax(k1 ,k2 ) ), which is still polyno-
mial in n; i.e., the sum of two polynomials is also polynomial. Thus, the overall
running time of M3 is also polynomial.
(b) Show that P is closed under concatenation.
Answer: Suppose that language L1 ∈ P and language L2 ∈ P. Thus, there are
polynomial-time TMs M1 and M2 that decide L1 and L2 , respectively. Specifi-
cally, suppose that M1 has running time O(nk1 ), and that M2 has running time
O(nk2 ), where n is the length of the input, and k1 and k2 are constants. A
Turing machine M3 that decides the concatenation L1 ◦ L2 is the following:
M3 = “On input w = a1 a2 · · · an , with each ai ∈ Σ a symbol:
1. For i = 0, 1, 2, . . . , n, do
2. Run M1 with input w1 = a1 a2 · · · ai , and
run M2 with input w2 = ai+1 ai+1 · · · an .
If both M1 and M2 accept, accept.
3. If none of the iterations in Stage 2 accept, reject.”

2
The TM M3 checks every possible way of splitting the input w into two parts w1
and w2 , and checks if the first part w1 is accepted by M1 (i.e., w1 ∈ L1 ) and
the second part w2 is accepted by M2 (i.e., w2 ∈ L2 ), so that w1 w2 ∈ L1 ◦ L2 .
Suppose that the input w to M3 has length |w| = n. Stage 2 is executed at most
n + 1 times. Each time Stage 2 is executed, M1 and M2 are run on strings w1
and w2 with |w1 | ≤ |w| = n and |w2 | ≤ |w| = n. Thus, running M1 on w1
takes O(nk1 ) time, and running M2 on w2 takes O(nk2 ) time, so Stage 2 runs
in time O(nk1 ) + O(nk2 ) = O(nmax(k1 ,k2 ) ), which is polynomial in n. Because
Stage 2 is executed at most n + 1 times, we get that the time complexity of M3 is
O(n + 1)O(nmax(k1 ,k2 ) ) = O(n1+max(k1 ,k2 ) ), which is polynomial in n. Hence,
the overall running time of M3 is polynomial in n.
(c) Show that P is closed under complementation.
Answer: Suppose that language L1 ∈ P, so there is a polynomial-time TM M1
that decides L1 . A Turing machine M2 that decides L1 is the following:

M2 = “On input w:
1. Run M1 with input w.
If M1 accepts, reject; otherwise, accept.”

The TM M2 just outputs the opposite of what M1 does, so M2 decides L1 .


Because M1 is a polynomial-time TM, so is M2 .

4. A triangle in an undirected graph is a 3-clique. Show that TRIANGLE ∈ P, where


TRIANGLE = { hGi | G contains a triangle }.

Answer: Let G = (V, E) be a graph with a set V of vertices and a set E of edges.
We enumerate all triples (u, v, w) with vertices u, v, w ∈ V and u < v < w, and then
check whether or not all three edges (u, v), (v, w) and (u, w) exist in E. Enumeration
of all triples requires O(|V |3 ) time. Checking whether or not all three edges belong
to E takes O(|E|) time. Thus, the overall time is O(|V |3 |E|), which is polynomial
in the length of the input hGi. Therefore, TRIANGLE ∈ P.
Remark: Note that for TRIANGLE , we are looking for a clique of fixed size 3, so
even though the 3 is in the exponent of the time bound, the exponent is a constant, so
the time bound is polynomial. We could modify the above algorithm for TRIANGLE
to work for CLIQUE = { hG, ki | G is an undirected graph with a k-clique } by enu-
merating all collections of k vertices, where k is the size of the clique desired. But the
number of such collections is
 
|V | |V |!
= = O(|V |k ),
k k!(|V | − k)!

so the time bound is O(|V |k k|E|), which is exponential in k. Because k is part of


the input hG, ki, the time bound is no longer polynomial. Hence, we cannot use this
algorithm to show that CLIQUE ∈ P. Nor does it show that CLIQUE 6∈ P since we’ve
only shown that one algorithm doesn’t have polynomial runtime, but there might be

3
another algorithm for CLIQUE that does run in polynomial time. However at this
time, it is currently unknown if CLIQUE ∈ P or CLIQUE 6∈ P. Because CLIQUE is
NP-complete, this question will be answered if anyone solves the P vs. NP problem,
which is still unresolved.
5. Using the polynomial-time algorithm for context-free language recognition (i.e., the
CYK algorithm or dynamic programming), fill out the table for string w = abba and
CFG G:
S → RT
R → TR | a
T → TR | b

Answer: We start the CYK algorithm by writing an empty n × n table, where n = 4


is the length of the string w = abba that we want to determine if the CFG G (in
Chomsky normal form) can generate.

1 2 3 4
1
2
3
4
string a b b a

Note that we numbered the rows and columns, and we wrote the string abba along
the bottom of the table. We will fill in the table a diagonal at a time, starting with
the main diagonal. Once one diagonal is filled in, we move to the diagonal directly
above it. The entry table(i, j) corresponds to the substring starting in position i and
ending in position j, and we put into table(i, j) those variables that we can start with
to generate that substring.
We start by filling in the main diagonal, which consists of the entries table(1, 1),
table(2, 2), table(3, 3), and table(4, 4). Entry table(1, 1) corresponds to the sub-
string starting in position 1 and ending in position 1, which is the substring a. Because
the given CFG is in Chomsky normal form, the only way a variable can generate this
substring is if there is a rule that has this variable go directly to a. Because there
is a rule R → a, we add the variable R into table(1, 1). There are no other rules
with a on the right side, so we don’t add any other variables to table(1, 1); hence,
table(1, 1) = {T }.

1 2 3 4
1 R
2
3
4
string a b b a

4
We now move to the main diagonal’s next entry, table(2, 2). This corresponds to the
substring starting in position 2 and ending in position 2, which is the substring b. The
only way to generate this substring is through the rule T → b, so table(2, 2) = {T }.

1 2 3 4
1 R
2 T
3
4
string a b b a

Similarly, for entries table(3, 3) and table(4, 4), which correspond to substrings b and
a, respectively, we have table(3, 3) = {T } and table(4, 4) = {R}.

1 2 3 4
1 R
2 T
3 T
4 R
string a b b a

Now that the main diagonal is complete, we next fill in the diagonal just above it.
Entry table(1, 2) corresponds to the substring starting in position 1 and ending in
position 2, which is the substring ab. We can divide this substring into two shorter
parts, a and b, and we see how we can generate these two shorter parts.
ˆ For the first part a, which starts in position 1 and ends in position 1, we look in
entry table(1, 1) to see that R can generate this part a.
ˆ For the second part b, which starts in position 2 and ends in position 2, we look
in entry table(2, 2) to see that T can generate this part b.
Now if we have a rule in which the right side pairs a variable from table(1, 1) with a
variable from table(2, 2), then the variable on the left side of the rule can generate the
current substring ab. Specifically, we are looking for rules whose right sides are from
table(1, 1) ◦ table(2, 2). Since table(1, 1) = {R} and table(2, 2) = {T }, we have
that table(1, 1) ◦ table(2, 2) = {RT }, so we look for rules with RT on the right side.
ˆ For example, there is a rule S → RT , so the variable S can generate the current
substring ab. To see why, consider the right side RT of the rule S → RT .
Entry table(1, 1) tells us that the R on the right side can generate a, and entry

table(2, 2) tells us that the T on the right side can generate b. Thus, S ⇒ RT ⇒
ab, so S can generate ab.
We have now determined that S can generate the current substring ab, which starts in
position 1 and ends in position 2, so we add S into table(1, 2); hence, table(1, 2) =
{S}.

5
1 2 3 4
1 R S
2 T
3 T
4 R
string a b b a

Now we consider the next entry in the current diagonal. This is table(2, 3), which
corresponds to the substring starting in position 2 and ending in position 3, which
is the substring bb. We divide this substring into two smaller parts, b and b, and we
determine how we can generate these two parts.

ˆ For the first part b, which starts in position 2 and ends in position 2, the entry
table(2, 2) tells us that T can generate this part b.
ˆ For the second part b, which starts in position 3 and ends in position 3, the entry
table(3, 3) tells us that T can generate this part b.

Now if we have a rule in which the right side is from table(2, 2) ◦ table(3, 3) (i.e.,
the right side pairs a variable from table(2, 2) with a variable from table(3, 3)), then
the variable on the left side of the rule can generate the current substring bb. Since
table(2, 2) = {T } and table(3, 3) = {T }, we have table(2, 2) ◦ table(3, 3) =
{T T }, so we are looking for rules that have T T on the right side. But there are no
rules with T T on the right side, so it is impossible to generate the current substring
bb using the rules of the CFG; thus, we put a dash “—” in entry (2, 3) to denote that
table(2, 3) = ∅.

1 2 3 4
1 R S
2 T —
3 T
4 R
string a b b a

Using similar reasoning for entry table(3, 4), we look for rules that have right sides
from table(3, 3) ◦ table(4, 4) = {T } ◦ {R} = {T R}. Thus, we look for rules with
T R on the right side, which leads us to put R and T in table(3, 4), so table(3, 4) =
{R, T }.

1 2 3 4
1 R S
2 T —
3 T R, T
4 R
string a b b a

6
Now that the second diagonal is complete, we next fill in the diagonal just above
it. Entry table(1, 3) corresponds to the substring starting in position 1 and ending in
position 3, which is the substring abb. We can divide this substring into two nonempty
parts in two different ways: a concatenated with bb, and ab concatenated with b.
First consider splitting abb into parts a and bb.

ˆ For the first part a, which starts in position 1 and ends in position 1, entry
table(1, 1) = {R} tells us that R can generate this part a.
ˆ For the second part bb, which starts in position 2 and ends in position 3, entry
table(2, 3) = ∅ tells us that nothing can generate this part bb.

Note that table(1, 1) ◦ table(2, 3) = {R} ◦ ∅ = ∅, so it is impossible to generate the


current substring abb by using the split a concatenated with bb.
Now consider the other way of splitting the current substring abb into two parts, by
concatenating ab with b.

ˆ For the first part ab, which starts in position 1 and ends in position 2, entry
table(1, 2) = {S} tells us that S can generate this part ab.
ˆ For the second part b, which starts in position 3 and ends in position 3, entry
table(3, 3) = {T } tells us that T can generate this part b.

Thus, if we have a rule with right side from table(1, 2) ◦ table(3, 3) = {S} ◦ {T } =
{ST }, then the variable on the left side of the rule can generate the current substring
abb. We are thus looking for rules with right side ST , and we add the variables on the
left sides of these rules to table(1, 3). In this case, there are no rules with ST on the
right side, so it is impossible to generate the current substring abb using the split that
concatenates ab with b. (Actually, we don’t have to even look at the rules to determine
that no rule has ST on the right side since the start variable S cannot appear on the
right side of any rule because the CFG is in Chomsky normal form.) Since the other
way of splitting abb as a concatenated with bb also was impossible, we then see it is
not possible to generate abb using the CFG, so table(1, 3) = ∅, which we denote with
a dash.

1 2 3 4
1 R S —
2 T —
3 T R, T
4 R
string a b b a

Let us now review how we filled in entry table(1, 3). We looked for rules that had on
the right side either

ˆ a variable from table(1, 1) paired with a variable from table(2, 3), i.e., a right
side from table(1, 1) ◦ table(2, 3), or

7
ˆ a variable from table(1, 2) paired with a variable from table(3, 3), i.e., a right
side from table(1, 2) ◦ table(3, 3).

Thus, to fill in entry table(1, 3), we pair entries by going across row 1 and down column
3. In general, to fill in entry table(i, j), we pair entries by going across row i and down
column j, i.e., we look for rules with right sides from table(i, i) ◦ table(i + 1, j), or
table(i, i + 1) ◦ table(i + 2, j), or . . . , or table(i, j − 1) ◦ table(n, j).
Next we fill in entry table(2, 4), which corresponds to the substring starting in position
2 and ending in position 4, which is the substring bba. Using the observation from the
previous paragraph, we thus want to pair entries going across row 2 and down column
4. In particular, we look for rules with right sides from

ˆ table(2, 2) ◦ table(3, 4), i.e., we pair a variable from table(2, 2) with a variable
from table(3, 4), or
ˆ table(2, 3) ◦ table(4, 4), i.e., we pair a variable from table(2, 3) with a variable
from table(4, 4).

In the first case, since table(2, 2) = {T } and table(3, 4) = {R, T }, we have


table(2, 2) ◦ table(3, 4) = {T } ◦ {R, T } = {T R, T T }, so we look for rules with
T R or T T on the right side. We find the rules R → T R and T → T R, so we add the
variables R and T to entry table(2, 4). There are no rules with T T on the right side,
so we don’t any more variables to table(2, 4) at this point.
In the second case, table(2, 3) ◦ table(4, 4) = ∅ ◦ {R} = ∅, so there is no way to
generate the substring bba by the split that concatenates bb with a. Thus, we add no
other variables to entry table(2, 4), so table(2, 4) = {R, T } from the R and T in the
first case.

1 2 3 4
1 R S —
2 T — R, T
3 T R, T
4 R
string a b b a

This completes the third diagonal, so now we move to the next diagonal. The entry
table(1, 4) corresponds to the substring starting in position 1 and ending in position
4, which is the substring abba. To determine how we can generate this substring, we
pair entries in the table by going across row 1 and down column 4. In particular, we
pair

ˆ a variable from table(1, 1) with a variable from table(2, 4), or


ˆ a variable from table(1, 2) with a variable from table(3, 4), or
ˆ a variable from table(1, 3) with a variable from table(4, 4).

Thus, we look for rules with right sides from

8
ˆ table(1, 1) ◦ table(2, 4) = {R} ◦ {R, T } = {RR, RT }, or
ˆ table(1, 2) ◦ table(3, 4) = {S} ◦ {R, T } = {SR, ST }, or
ˆ table(1, 3) ◦ table(4, 4) = ∅ ◦ {R} = ∅.

For any rule that has any of these right sides, we add the variable on the left of the
rule to entry table(1, 4). The only rule with these possible right sides are S → RT ,
so we add S to entry table(1, 4).

1 2 3 4
1 R S — S
2 T — R, T
3 T R, T
4 R
string a b b a

The table is now complete since we have filled in the upper triangle. To determine if
the CFG can generate original string abba, which is the substring starting in position
1 and ending in position 4, we check if the starting variable S ∈ table(1, 4). Since it
is, CFG G generates the string abba. If S were not in the upper right corner, then the
CFG would not generate the string.

You might also like