0% found this document useful (0 votes)
14 views

Tute7 Soln

Uploaded by

audrey
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)
14 views

Tute7 Soln

Uploaded by

audrey
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/ 18

Monash University

Faculty of Information Technology


2nd Semester 2022

FIT2014
Tutorial 7
Decidability, Undecidability and Complexity

SOLUTIONS
Although you may not need to do all the exercises in this Tutorial Sheet, it is still
important that you attempt the first ten exercises and a selection of the supplementary
exercises, and that the exercises you attempt cover a variety of problem types.
Even for problems that you do not choose to attempt seriously, you should still
give some thought to how to do them before reading the solutions.

1.
(a) Given M, x as input to NFA ACCEPTANCE, convert M to an equivalent FA;
let’s call it M ′ . (See Kleene’s Theorem.) Then M accepts x if and only if M ′ ac-
cepts x. In other words, (M, x) is a Yes-input to NFA ACCEPTANCE if and only
if (M ′ , x) is a Yes-input to FINITE AUTOMATON ACCEPTANCE. Furthermore,
the construction (M, x) 7→ (M ′ , x) is computable. So, it’s a mapping reduction from
NFA ACCEPTANCE to FINITE AUTOMATON ACCEPTANCE.

(b) Given M, x as input to FINITE AUTOMATON ACCEPTANCE, convert M to


an equivalent TM (see Lecture 18, slide 14); let’s call it M ′ . Then M accepts x if and
only if M ′ accepts x. In other words, (M, x) is a Yes-input to FINITE AUTOMA-
TON ACCEPTANCE if and only if (M ′ , x) is a Yes-input to TM ACCEPTANCE.
Furthermore, the construction (M, x) 7→ (M ′ , x) is computable. So, it’s a mapping
reduction from FINITE AUTOMATON ACCEPTANCE to TM ACCEPTANCE.

(c) TM ACCEPTANCE is undecidable, so there can be no mapping reduction from


it to any decidable problem. The problem FINITE AUTOMATON ACCEPTANCE
is clearly decidable: you can just simulate the FA on the string, to determine if it
accepts or not. So there can be no mapping reduction from TM ACCEPTANCE to
FINITE AUTOMATON ACCEPTANCE.

(d) The problem PDA ACCEPTANCE is decidable. Any decidable problem has
a mapping reduction to (almost1 ) anything else.2 So, in particular, PDA ACCEP-
TANCE has a mapping reduction to FINITE AUTOMATON ACCEPTANCE. We’ll
explain how that happens in this particular case.
1
What are the exceptions?
2
This suggests another approach to (b).

1
Let D be any decider for PDA ACCEPTANCE. (For example, D could just sim-
ulate the execution of the PDA M on input x, and see if it accepts or not.) Pick any
FA A and any string y such that A accepts y. Also pick any FA B and any string z
such that B rejects z. (Note that A, y, B, z are all fixed in advance, before we even
look at any input to PDA ACCEPTANCE.)
The mapping reduction from PDA ACCEPTANCE to FINITE AUTOMATON
ACCEPTANCE works as follows.
1. Input: a PDA M , and a string x.

2. Run D on the pair (M, x) to determine if M accepts x.

(a) If D reports that M accepts x: OUTPUT (A, y).


(b) If D reports that M rejects x: OUTPUT (B, z).

If (M, x) is a Yes-input to PDA ACCEPTANCE, then D reports that M accepts


x, and therefore the algorithm outputs the fixed pair (A, y), which is a Yes-input to
FINITE AUTOMATON ACCEPTANCE.
On the other hand, If (M, x) is a No-input to PDA ACCEPTANCE, then D
reports that M rejects x, and therefore the algorithm outputs the fixed pair (B, z),
which is a No-input to FINITE AUTOMATON ACCEPTANCE.
Finally, the algorithm is clearly computable.

2.
(a)
(i) Vertex v gets at least one colour: w v ∨ bv
(ii) Vertex v does not get more than one colour: ¬wv ∨ ¬bv
(iii) Vertices u and v do not get the same colour: (¬wu ∨ ¬wv ) ∧ (¬bu ∨ ¬bv )
(b)
Given G, create φ as follows. Firstly, take the conjunction (over all v) of all
clauses of type (i); secondly, take the conjunction of all clauses of type (ii); thirdly,
take the conjunction, over all edges uv of G, of all expressions of type (iii). Then
take the conjunction of (i), (ii), (iii) together. Then you have a single expression φ,
in CNF, with exactly two literals in each clause, and it is satisfiable if and only if G
is 2-colourable.
(c)
Assume that the time taken to create a single two-literal clause is ≤ c, where c is
a constant.3 If G has n vertices and m edges, then the time taken is:

for (i), we have n vertices each requiring time ≤ c to create one clause, giving
time ≤ cn.
3
If you prefer, use a looser upper bound here, such as cn.

2
for (ii), similarly, we have time ≤ cn.

for (iii), we have m edges, and need to create two clauses for each, giving time
≤ 2cm.

So the total time is ≤ cn + cn + 2cm = 2c(n + m) = O(n + m). So this mapping


reduction is in fact a polynomial time mapping reduction.4

3.
We give a mapping reduction from the Diagonal Halting Problem (DHP) to HALT
ON EVEN STRINGS.
Let M be a Turing machine provided as input to DHP.
Construct a new TM M ′ that takes, as input, a string x, and then ignores it and
simulates the running of M on input M .
The function that maps M to M ′ is clearly computable.
If M is in DHP, then it halts on input M . Therefore M ′ will eventually halt,
whatever the input string x was (including for all strings of even length).
If M is not in DHP, then it loops forever on input M . Therefore M ′ also loops
forever, whatever the input string x was (including for all strings of even length).
So the function that maps M to M ′ is a mapping reduction from DHP to HALT
ON EVEN STRINGS.
Together with the fact that DHP is undecidable, this implies that HALT ON
EVEN STRINGS is undecidable.

4
Had we assumed time ≤ cn for clause creation, the total time would have been O(n2 +m), which
is still polynomial time.

3
4.
Decision Problem your answer
(tick one box in each row)

Input: a Java program P (as source code).



Question: Does P contain an infinite loop?
Decidable Undecidable
Input: a Java program P (as source code).
Question: Does P contain the infinite loop ✓
for(int i=0; i>=0; i++);? Decidable Undecidable

Input: a Java program P (as source code).



Question: Does P contain recursion?
Decidable Undecidable
Input: a Java program P (as source code).
Question: If P is run, will some method of P keep calling ✓
itself forever? Decidable Undecidable

Input: a Turing machine M .


Question: is there some input string, of length at most ✓
12, for which M halts in at most 144 steps? Decidable Undecidable

Input: a Turing machine M .


Question: is there some input string, of length at least ✓
12, for which M halts in at most 144 steps? Decidable Undecidable

Input: a Turing machine M .



Question: Is the time taken for M to halt even?
Decidable Undecidable
Input: a Turing machine M .
Question: Is there a palindrome which, if given as input, ✓
causes M to eventually halt? Decidable Undecidable

Input: a Turing machine M .



Question: Is M a palindrome?
Decidable Undecidable

4
5.
(a)

27 → 82 → 41 → 124 → 62 → 31 → 94 → 47 → 142 → 71 → 214 → 107 → 322 →


161 → 484 → 242 → 121 → 364 → 182 → 91 → 274 → 137 → 412 → 206 → 103 →
310 → 155 → 466 → 233 → 700 → 350 → 175 → 526 → 263 → 790 → 395 → 1186 →
593 → 1780 → 890 → 445 → 1336 → 668 → 334 → 167 → 502 → 251 → 754 → 377 →
1132 → 566 → 283 → 850 → 425 → 1276 → 638 → 319 → 958 → 479 → 1438 → 719 →
2158 → 1079 → 3238 → 1619 → 4858 → 2429 → 7288 → 3644 → 1822 → 911 → 2734 →
1367 → 4102 → 2051 → 6154 → 3077 → 9232 → 4616 → 2308 → 1154 → 577 → 1732 →
866 → 433 → 1300 → 650 → 325 → 976 → 488 → 244 → 122 → 61 → 184 → 92 → 46 →
23 → 70 → 35 → 106 → 53 → 160 → 80 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

This calculation was done in a Google Sheet, but it could equally well be done in
another spreadsheet, or in a Python program, or by a Turing machine, etc.

(b) Consider the algorithm that takes a positive integer x as input and keeps applying
f repeatedly, only stopping and accepting if it reaches 1.
This algorithm accepts x if and only if x ∈ COLLATZ. So, if the algorithm
is implemented as a Turing machine M , then Accept(M ) = COLLATZ. Therefore
COLLATZ is recursively enumerable.

(c) We do not yet know whether or not this algorithm (for (b)) gives a decider, since
we do not yet know if it halts for all inputs, and we do not yet know if there is any
positive integer that does not belong to COLLATZ.
If the Collatz conjecture is true, then the algorithm is indeed a decider for COL-
LATZ, since the truth of the conjecture would imply that the algorithm always halts
and accepts. But, in that case, a much simpler decider would work! What is it?
If the Collatz conjecture is false, then it is still possible, in principle, as far as we
know at present, that COLLATZ might still be decidable. Why?

(d) This problem has resisted the efforts of some of the best computer scientists and
mathematicians in the world. But that should not discourage a student from having
a go at it! It needs a fresh idea, a new direction. If you do think you have made
significant progress, be sure to also read the two articles cited in the footnote for this
question in the tutorial sheet.

6.
(⇒)
Let L be a r.e. language. Then there is a TM M such that Accept(M ) = L.
Let the predicate P take two arguments, a string x (to be considered as input to
M ) and a positive integer t. It is defined to be True if, when M is run on input x,
it accepts in ≤ t steps, and False otherwise. This predicate is computable, since to
determine whether or not P (x, t) is True, we just run M on input x for t steps, and

5
if it accepts within that time, we know P (x, t) is True, and if it does not (so either it
is still going, or has rejected), we know it is False.
Having defined this predicate, we see that x ∈ L if and only if M accepts x, which
holds if and only if there is some time t such that M accepts x in ≤ t steps. (Just
take t to be any number at least as large as the number of steps that M takes on
input x until it halts. We know it must halt for input x, since it accepts.) But this
in turn is true if and only if P (x, t) is True.
(⇐)
Now suppose that there is a decidable two-argument predicate P such that x ∈ L
if and only if there exists y such that P (x, y). Let D be the Turing machine which
correctly computes P (x, y) for any x, y. What we’d like to do is simulate D on
input (x, y), for every string y in parallel, and accept x if any one of the y leads to
acceptance. But this sounds like doing infinitely many things in parallel. So, instead,
we adopt a similar strategy to that used when we showed that every r.e. language has
an enumerator.
Denote all strings by y1 , y2 , . . . , yi , . . ..
Create a new TM M which works as follows:

1. Input: x

2. For each k = 1, 2 . . .
For each i = 1, . . . , k:
{
Simulate the next step of the execution of D on (x, yi ).
If D(x, yi ) stops (in the simulation of it) and returns True,
then Accept and Stop the whole computation;
else if D(x, yi ) stops (in the simulation of it) and returns False,
then skip i in all further iterations.
}

Here, M accepts x if and only if there is some yi such that D stops and returns True,
for input (x, yi ). But this in turn holds if and only if there exists yi such that P (x, yi ).
By assumption, this holds if and only if x ∈ L.
So Accept(M ) = L. Therefore L is r.e.

7.
Let τt (n) be the times taken by your program to solve this problem, t years from
now, on an input of size n.
At present, we have τ0 (n) = an5 .
According to Moore’s Law, processor speed doubles every two years. So, assuming
all programs are run on computers whose processor speed over time follows Moore’s
Law exactly (which is a big simplification, especially for small t),

τt (n) = τ0 (n)/2t/2 . (1)

6
Also, observe that, if the input is increased by a factor of k, then (for fixed t) the
time goes up by a factor of k 5 :

τt (kn) = k 5 τt (n). (2)

(a)
The condition given in this question can be written in an equation:

τt (4n) = τ0 (n).

We want to solve this for t.


Using (1), the equation becomes

45 τt (n) = τ0 (n).

Then, using (2) gives


45 τ0 (n)
= τ0 (n),
2t/2
so that
2t/2 = 45 .
Solving this gives t = 20. So you have to wait for 20 years.
(b)
Now, τ0 (n) = 2n .
Equation (1) still holds.
Equation (2) no longer holds. Instead we have

τ0 (kn) τ0 (n)k
τt (kn) = = .
2t/2 2t/2
The condition for (b) is once again

τt (4n) = τ0 (n).

Doing the appropriate substitutions gives


τ0 (n)4
= τ0 (n).
2t/2
This simplifies to
τ0 (n)3
= 1,
2t/2
which in turn gives
τ0 (n)3 = 2t/2 .
Substituting τ0 (n) = 2n gives 23n = 2t/2 , so t = 6n. Using our lower bound, n ≥ 40,
we find t ≥ 240. So your friend has to wait for at least 240 years.

7
This illustrates how even a large polynomial time complexity (and, in most prac-
tical contexts, running time n5 would be considered slow) gives much more compu-
tational power, and handles increases of input size much better, than an exponential
time complexity.
Thanks to Han Phan (FIT2014 tutor, 2013) for spotting a bug in an earlier version
of this solution, and fixing it.

Supplementary exercises
8.
(a) Yes, because given any CFG we can construct a grammar in CNF that generates
the same language, except that the empty string needs to be treated as a special case
(since a CNF grammar cannot generate the empty string).
Before we give the construction, we need to fix a couple of specific grammars in
advance.
Pick any (A, y) where A is a Chomsky Normal Form CFG that does not generate
the empty language, and y is a string generated by A. Also pick any (B, z) where
B is a Chomsky Normal Form CFG that does not generate the universal language,
and z is a string that is NOT generated by A. (Note that A, y, B, z are all fixed in
advance, before we even look at any input to CFG GENERATION.)
Now we can describe the mapping reduction.

1. Input: a CFG G, and a string x.

2. If x is nonempty:

(a) convert G to a CNF CFG H.


(b) OUTPUT (H, x)

else: // x=ε

(a) Apply the CYK algorithm to determine if G generates ε.


i. If it does: OUTPUT (A, y).
ii. If not: OUTPUT (B, z).

(b) Yes, because we can just use the mapping reduction that does nothing: for every
input (G, x), the output is also (G, x). This works because a CNF CFG is still a
CFG.

9.
(a) Let f be the function that maps any string x to the string xx obtained by
concatenating x with a copy of itself. In other words, f just doubles x. String

8
copying and concatenation are computable operations, so f is computable.
Let x be any string (which may or may not be in L).
If x ∈ L, then xx ∈ Leven , since L is closed under doubling and xx has even length.
Therefore f (x) ∈ Leven , since f (x) = xx.
If f (x) ∈ Leven , then xx ∈ Leven (by definition of f (x)), and hence xx ∈ L (since
Leven ⊆ L). But xx has even length, and so can be halved, giving x, which must then
be in L as L is closed under halving.
So f is a mapping reduction from L to Leven .

(b) Let y be some specific string not in L. Such a y exists, since L is not universal.
We use the function g defined by

x, if |x| is even;
g(x) :=
y, if |x| is odd.

Note that y does not depend on x. So, all odd-length strings are mapped to the same
string y. But each even-length string is mapped to itself.
This is computable, since determining if a string x has even length is computable,
and outputing the constant string y (when needed) is also computable.
If x ∈ Leven , then |x| is even, so g(x) = x (by definition of g), so g(x) ∈ Leven
(since x is), so g(x) ∈ L (since Leven ⊆ L).
If x ̸∈ Leven we have two cases.
If |x| is even, then g(x) = x (by definition of g), so g(x) ̸∈ Leven (since x isn’t), so
g(x) ̸∈ L (since Leven contains all even-length strings in L).
If |x| is odd, then g(x) = y (by definition of g), so g(x) ̸∈ L (since y ̸∈ L).
So, regardless of the parity of |x|, we have g(x) ̸∈ L.
We have shown that g is a mapping reduction from Leven to L.

(c) If Leven is decidable, then a decider for it, together with the mapping reduction
from L to Leven , gives a decider for L. So L is decidable.
If L is decidable, then a decider for it, together with the mapping reduction from
Leven to L, gives a decider for Leven . So Leven is decidable.
Therefore L is decidable if and only if Leven is decidable.
Therefore L is undecidable if and only if Leven is undecidable.

(d) Concatenating a string with itself can be done by a Turing machine in quadratic
time. (The machine has to repeatedly copy a bit of x to a location n tape cells to its
right, then go back to get the next bit. This must be done for each of the n bits of
x.) So the time complexity of f is O(n2 ).
The function g just has to check the parity of |x| (which can be done by one
pass all along the input string) and maybe output the fixed string y, which does not
depend on x (and takes constant time). So the time complexity of g is O(n).

(e) Recall that, if A and B are languages such that A ≤P B and B ∈ P then A ∈ P.

9
Since our two reductions are polynomial-time computable (by part (d)), we have
L ≤P Leven and Leven ≤P L. It follows that L ∈ P if and only if Leven ∈ P.

10.
Let L1 and L2 be the languages described by R1 and R2 respectively. Observe
that

L1 ∩ L2 are disjoint ⇐⇒ L1 ∩ L2 = ∅ ⇐⇒ L1 ∩ L2 = Σ∗ ⇐⇒ L1 ∪ L2 = Σ∗ .

We can find a regular expression for the language L1 ∪ L2 as follows.

1. Find a FA, A1 , for R1 , using the usual method to convert a regexp to a FA that
recognises the same language.

2. Create a new FA, A′1 , from A1 by changing Final states to non-Final and vice
versa, and leaving everything else unchanged. This new FA A′1 recognises the
complement, L1 , of the language L1 recognised by A1 .

3. By the same process as used in the first two steps, create a new FA, A′2 , which
recognises L2 .

4. Now we create a NFA to recognise L1 ∪ L2 . To do this, we take our two FAs, A′1
and A′2 , and identify (i.e., merge into one) their Start states. The rest of the two
FAs — their states and transitions — are kept separate. So the new automaton
has a single Start state, and at that state there is some nondeterminism as
each alphabet letter now has two transitions going out of that state. This NFA
recognises L1 ∪ L2 .

5. Convert this NFA to a FA using the usual method for converting an NFA to
FA.

6. We now have a FA (call it A) to recognise L1 ∪ L2 . We need to see if the


language A recognises is just Σ∗ . In other words, we need to see if it accepts
every possible string over our alphabet. In other words, we need to see if it
recognises the same language as the trivial FA with a single state, serving both
as a Start and a Final state, and with a loop at that state for each letter in the
alphabet Σ (since this trivial FA accepts every string).
To do this, we use the algorithm for minimising states in an FA (Lecture 10,
slides 5–10). This algorithm is guaranteed to find an FA which recognises the
same language and does so with the minimum possible number of states. So, if
the language recognised by A is indeed Σ∗ , then the FA minimisation algorithm
applied to A will produce the trivial FA that accepts Σ∗ . But if the language
recognised by A is something else, then the FA minimisation algorithm gives
some other FA instead of our trivial one.

10
7. If we end up with the trivial FA by this process, we answer Yes, otherwise we
answer No.
What we have given is the outline of an algorithm, and it solves our decision prob-
lem (stopping and giving the correct answer in all cases). So that problem is decidable.

It may appear that this fact follows from the closure of regular languages under complement and
union. Certainly, these closure properties (along with Kleene’s Theorem) tell us that the language
L1 ∪ L2 does indeed have a FA that recognises it, and if we had such an FA, we could simplify it
to see if it is trivial and therefore accepts every string. But our task in this question was to give
a method to determine, from R1 and R2 , whether their languages are disjoint. So we needed to
actually construct the FA for L1 ∪ L2 , not to just rely on its existence.
Having said that, the proofs of the closure properties should give us the methods we need. It’s
just that the closure properties themselves just assert existence. (E.g., closure under union asserts
that, if L is regular then so is L, which tells us that there exists a regular expression and a FA for
L.)
So it’s the algorithms that come with the closure properties that we need, rather than just the
raw closure properties themselves. (Of course, we use Kleene’s Theorem too.)

11.
Suppose we have a decider that can tell us whether or not a Turing machine is
self-reproducing.
Let P be any program. Write P (x) for the program P with hard-coded input x.
(So, for example, a statement that reads input and puts the result into a variable v, is
replaced by a statement that simply assigns the hard-coded string x to the variable v.)
We are going to construct, from P , another program which will be self-reproducing
if and only if P halts when given itself as input.
To do this, we will make use of the specific self-reproducing program S described
in the question. The exact details of how S works need not concern us, but such
programs are known to exist. (Look up ‘quines’. Challenge: write a self-reproducing
Turing machine!)
The program we construct from P is just SP (P ) , the self-reproducing program S
with the code for P (P ) (i.e., P with hard-coded input being P itself) inserted at its
special point.5 Provided P halts on input P , the program P (P ) will halt, so that
SP (P ) will simply reproduce itself. But if P does not halt on input P , then P (P ) never
halts, so SP (P ) never halts. So SP (P ) is self reproducing if and only if P eventually
halts for input P . So, if we have a decider for self-reproducibility, we can use it
to make a decider for the Diagonal Halting Problem. This is a contradiction, since
the Diagonal Halting Problem is known to be undecidable. So there cannot exist a
decider for self-reproducibility. So self-reproducibility is undecidable.

12.
For any Turing machine P , construct a Turing machine UP which works as follows.
1. Input: Turing machine M , input string x for M .
5
If P shares any variables etc. with S, just rename them to avoid this.

11
2. Simulate P on input P . After P stops (in the simulation), continue.
(This can easily be done in such a way as to still leave (M, x) sitting on the
tape afterwards.)
3. Run U on input (M, x). (It simulates the execution of M with input x.)
If P halts for input P , then UP is the same as U except for a delay at the start
while P is run on input P . So UP is universal.
If P does not halt on input P , then UP never halts, no matter what input it is
given. So it cannot be universal any more.
So: P halts on input P if and only if UP is universal.
So, if we had a decider for universality, then we could use it to make a decider for
the Diagonal Halting Problem.
Hence there is no decider for universality. So, determining whether or not a Turing
machine is outwardly universal is undecidable.

13.
(a) HALT, i.e., {M : M loops forever, for input M }

(b) Given a CFG, does it generate every string (over its alphabet)?

(c) Given a (multivariate) polynomial, does it have no integer roots?

In each case, we have taken a decision problem/language known to be r.e. but


undecidable, and taken its complement. Such a language is co-r.e. by definition, and
its also undecidable (since the complement of a decidable language is decidable).

14.
(a)
If m is the length of the input string in bases, then we are given that the running
time is 5m3 . Each base needs two bits to specify it, so n = 2m and m = n/2.
Therefore the running time is 5m3 = 5(n/2)3 = 58 n3 .
(b)
No change is needed. Big-O running time absorbs constant factors.

15.
An adjacency matrix is an n × n matrix of bits, so its length, as an input, is n2
bits.
If algorithm A solves problem Π in polynomial time, then there exists k such that
its time complexity is

= O( (length of string representing adjacency matrix )k )


= O((n2 )k )
= O(n2k ).

12
We will now derive an inequality that relates the lengths of adjacency matrices
and edge lists.
We use a lower bound for the length of the edge list.
Suppose the graph has m edges. Then the edge list consists of m pairs (i, j). For
each edge, the pair (i, j) specifies its two endpoints i and j.
The total length of the edge list is clearly Ω(m). Since m = Ω(n) (since the graph
is connected), we find that the length of the edge list is Ω(n), which means that

n = O( (length of string representing edge list) ). (3)

So the time complexity is:

= O(n2k )
= O( (length of edge list)2k )
(using (3)).

Since the exponent 2k is fixed (i.e., does not depend on n), this shows that the
algorithm still runs in polynomial time when the input is represented as an edge list.
A good exercise is to do the reverse problem: show that, if a problem on graphs
can be solved in polynomial time when the input is given as an edge list, then it can
also be solved in polynomial time when the input is instead given as an adjacency
matrix.
The way input is represented does affect how quickly algorithms run in practice,
so it is important. But most “reasonable” representation schemes should not affect
the classification of problems as polynomial-time solvable or not.

16.
(a)
Input: x
z := 1 √ // z is smallest factor of x found so far.
For y := 2 to ⌊ x⌋ // y is the number to be tested
√ to see if it is a factor.
// Smallest factor must be ≤ x.
{
If y is a factor of x, then put z := y
}
If z > 1 then output z, else report that x is prime.

(b) √
In the worst case, the number of loop iterations is x. Each such iteration requires
one divisibility test, a comparison, an increment, and possibly an assignment. We’ll
call this a constant number of steps, which is sweeping a lot under the carpet but it
will do for the purposes of this exercise. √
So we’ll take the complexity to be O( x). If we √ write n for the input size then,
1/2
since x is in unary, n = x. So the complexity is O( n) = O(n ).

13
(c)
This complexity is polynomial, since it is O(nk ) for some constant k (in this case,
k = 21 ).
(d)
If x is in binary, then its length as a string of bits is ⌊log2 x⌋ + 1. This is close to
log2 x, and we’ll use this approximation for now.
Writing n for the input size again, we now have n = log2 x, so x = 2n . Substituting
this into our complexity gives O(x1/2 ) = O((2n )1/2 ) = O(2n/2 ).
(e)
The complexity is now exponential in the input size. The algorithm does not run
in polynomial time.
(f)
If we use base b > 2, then input size is n ≈ logb x and x = bn . The complexity is
O(bn/2 ). This also is exponential time, not polynomial time.
(g)
(i)
It would be very difficult. Even something as simple as an increment would take
a long time.
(ii)
In this encoding, a number is prime if and only if its encoding consists of a single
1, preceded by a (possibly empty) sequence of 0s. Its representation has the form
(0, 0, . . . , 0, 1). We just have to check, for every position in the input sequence except
the last, whether or not it is 0, and then we check that the last is 1. This takes
constant time per position, and the number of positions is O(n), where n is the input
length. So the time complexity is O(n), which is linear time, and certainly polynomial
time.
Incidentally, the input length n is the number of prime numbers ≤ x. This number
is approximately x/ log x, according to the Prime Number Theorem. But we don’t
need to know this for this question, since we are expressing complexity in terms of
the input length n, and not in terms of the number x itself.

17.
(a)
Let φ be a Boolean expression in CNF with exactly two literals in each clause
such that each variable appears at most twice.
If a variable appears either only in normal form, or only in negated form, then there
is nothing to be lost by making it True or False, respectively. It can be eliminated
from any clause where it appears. (This covers the case where a variable appears just
once in φ.)
So we may assume that each variable appears exactly twice, once normal and once
negated. Furthermore, if these two literals are in the same clause, then that clause
is satisfied, and has no interaction with any other clause (since the variable appears
nowhere else), so the clause may be eliminated. So we now assume that the two

14
occurrences of each variable are in different clauses.
Draw a graph on all the literals in φ, as follows. The literals are the vertices. Put
a green edge between two members of the same clause, and a red edge between two
literals which have the same variable. By the assumptions we’ve been able to make on
the way, no two vertices are joined by both a red and a green edge, and every vertex
is incident with one red edge and one green edge. Since each clause has exactly two
literals, the graph has no loops.
This graph must be a disjoint union of circuits, with all the circuits of even length.
For each such circuit, mark every second vertex. This marks exactly one vertex on
each green edge (and exactly one on each red edge, too). These are the literals which
we will make True. We do so by taking its variable, and making the variable True if
this literal is just the variable, and False if the literal is the negation of the variable.
The result is that, for each green edge — i.e., for each clause — one of the vertices is
marked, meaning that one of the literals in the clause is True. So the whole expression
is satisfied.
So every member of 2SAT2 is satisfiable.
(b)
When a literal is True, so its vertex is marked, the neighbour along a red edge —
the other literal with the same variable — cannot be marked, since that literal must
be False. But then its neighbour along a green edge must be True, else the clause
corresponding to that green edge is not satisfied. This continues all the way round
the circuit. Similarly, if a literal is False, its green neighbour must be True (else that
clause is not satisfied), and again we can continue all around the circuit.
So there are only two possible satisfying truth assignments to the variables ap-
pearing in a single circuit.
Disjoint circuits are independent for our purposes. So the total number of satis-
fying truth assignments is 2c , where c is the number of disjoint circuits in the graph
we have constructed. (This is if we consider the simplified Boolean expression which
only contains variables appearing in both normal and negated form, where the two
occurrences of each variable are always in different clauses. Additional variables in
the original, unsimplified expression may increase this total number further.)

18.
(a)
Put x = True, since there is nothing to be lost by doing so, and remove every
clause in which it appears. The new, smaller Boolean expression is satisfiable if and
only if the original one is.
(b)
Put x = False, for similar reasons, and remove every clause in which the literal
¬x appears, since the negated literal equates to True.
(c)
If a clause contains two identical literals, just replace it by a clause containing one
copy of that literal, since x ∨ x = x and ¬x ∨ ¬x = ¬x.

15
If a clause contains two opposite literals (i.e., x ∨ ¬x, for some variable x), then
eliminate that clause, since it must be satisfied, no matter what truth value is assigned
to x.
(d)
Make that literal True. So, if it is x (for some variable x), then put x = True, and
if the literal is ¬x, then put x = False. Then, eliminate any clause containing the
literal (since it is True so every such clause is satisfied). Also, remove every occurrence
of the opposite literal (but don’t remove the clauses they are in, since they still need
to be satisfied).
(e)
Algorithm: Simplify
Input: φ
If any clause contains two identical literals, replace it with a clause containing just
one copy of that literal.
If any clause contains two opposite literals in the same variable — i.e., both x
and ¬x — then eliminate that clause, as it’s always satisfied, whatever truth value is
given to that variable.
Loop:
{
While there is some variable x that appears only positively
(i.e., only as x, never negated) or only negatively (i.e., only as ¬x) in φ:
Set x to True or False respectively,
Eliminate from φ all clauses in which it appears.
(Eliminated clauses are satisfied.)
If any clause is empty, then Reject. (An empty clause cannot be satisfied.)
If φ has a clause with just one literal:
Assign a truth value to the variable to make that literal True.
Eliminate every clause in which this literal appears.
Remove every occurrence of the opposite literal
(i.e., the one with the same variable but opposite truth value).
} until no more changes occur to φ.
Output φ, together with the truth assignments made so far.
If φ now has no clauses, then Accept it (as all its clauses have been eliminated,
and so satisfied).
Once the loop finishes, if φ is not empty (i.e., it has at least one clause), then we
know that each clause has exactly two literals (in two different variables), and each
variable appears both positively and negatively (but in different clauses).
(f)
Let c be the number of clauses of φ.
Inductive basis: if c = 1, then φ has a single clause, with just one literal. The
algorithm Simplify enters the main outer loop, then in its first iteration, enters the
inner loop (While . . . ) as its condition is satisfied, and the body of that loop makes
this literal True (by appropriate truth assignment to its variable, then eliminates this

16
single clause, making φ empty. That completes execution of the While loop. The
next statement (If . . . ) is not done, as there is no empty clause (in fact, no clause at
all). The next statement (also If . . . ) is also skipped, as there is no clause. The final
exit-loop condition (until . . . ) is not yet met, as φ changed. The main outer loop
will be done one more time, but nothing will be done in it, and at the end of that
iteration, φ will not have changed, so we exit the loop, then output the now-empty
φ together with the single truth assignment we made, then Accept it as it has no
clauses.
Inductive step:
Assume the assertion of (f) is true whenever the number of clauses is < c, and let
φ be a Boolean expression of the required type with exactly c clauses.
Consider the first iteration of the outer loop of Simplify. Rejection, at the first
If statement, can only happen if φ is unsatisfiable, in which case we are done. So
suppose we don’t reject at this stage. The While loop and the first If statement
ensure that, by the time we get to the second If statement, we have an expression
with no empty clauses, and which has every variable appearing both positively and
negatively. If there is no one-literal clause, then we are done already. So suppose
there is a one-literal clause. Then the condition of the second If statement is met.
The variable in this literal (call it x) is then given the appropriate truth value, to
satisfy this clause, and the clause is eliminated. Now, since every variable appears
both positively and negatively, there is some clause containing the opposite form of
x. This literal is False, so is removed from that clause. That leaves a new one-literal
clause in the modified φ. The literal in that clause cannot involve x, else this clause
would have had two literals with the same variable (in the previous φ, just before
these latest modifications). So it involves another variable, to which we have not yet
assigned a truth value.
Since φ has just changed, the condition on the outer loop (until . . . ) is not
satisfied. So we go back to the start of the outer loop again. We are, in fact, in the
same situation as applying Simplify to this modified φ. But the modified φ has
fewer clauses than the φ we started with. So we can apply the inductive hypothesis,
which tells us that the algorithm will complete with either a rejection or by finding
a satisfying truth assignment for φ and outputing it. This, together with the truth
assignments for the variables that were eliminated in the process of modifying φ, gives
a satisfying truth assignment for the original φ.
This completes the proof of the inductive step. So, by the Principle of Mathemat-
ical Induction, the assertion of (f) holds.
(g)
Algorithm for 2SAT:
Input: φ
Apply Simplify to φ.
If we have not yet stopped, then (by (f)) we know that φ has exactly two literals,
with different variables, in each clause.
Pick any variable x. It must appear both positively and negatively.

17
Put x = True:
φ′ := φ
Eliminate from φ′ each clause in which the literal x appears. (This must happen
at least once.)
Remove from φ′ every literal ¬x. This must happen at least once, and will lead
to at least one clause with just one literal, so (f) is applicable.
Run Simplify on φ′ .
If it accepts, then we have a satisfying truth assignment for φ, by (f): we just take
the satisfying truth assignment for φ′ , and augment it with x = True. So we Accept.
If it rejects, then we know x = True cannot lead to a satisfying truth assignment
for φ. So, we try the other possibility.
Put x = False:
φ′ := φ
Eliminate from φ′ each clause in which the literal ¬x appears. (This must happen
at least once.)
Remove from φ′ every literal x. This must happen at least once, and will lead to
at least one clause with just one literal, so (f) is applicable.
Run Simplify on φ′ .
If it accepts, then we have a satisfying truth assignment for φ, by (f): we just take
the satisfying truth assignment for φ′ , and augment it with x = False. So we Accept.
If it rejects, then we know that neither x = True nor x = False can lead to a
satisfying truth assignment for φ. So we Reject.
(h)
This approach will not work for 3SAT because, when a literal is removed from a
clause of size 3, we have two remaining literals and we don’t know which one has to be
True in order for the whole expression to be satisfied. We can extend the algorithm
by branching here, treating each of the two remaining literals in turn. This leads to
an exponential-time algorithm.

18

You might also like