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

4-computation (1)

The document discusses the theory of computation, focusing on the capabilities and limitations of Turing Machines (TMs) in solving problems algorithmically. It highlights the Church Thesis, stating that no computational device can surpass the power of TMs, and explores the concept of computable functions, concluding that many problems cannot be solved algorithmically. The document also addresses the undecidability of the halting problem, illustrating that it is impossible to determine whether a given program will terminate on a specific input.

Uploaded by

aleksa.pulai
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

4-computation (1)

The document discusses the theory of computation, focusing on the capabilities and limitations of Turing Machines (TMs) in solving problems algorithmically. It highlights the Church Thesis, stating that no computational device can surpass the power of TMs, and explores the concept of computable functions, concluding that many problems cannot be solved algorithmically. The document also addresses the undecidability of the halting problem, illustrating that it is impossible to determine whether a given program will terminate on a specific input.

Uploaded by

aleksa.pulai
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

1

Theory of computation
• Which problems can we solve
– With some (any given) type of machine
– In the broadest possible meaning
• At first sight the question seems too general:
– What do we mean by “problem”?
A mathematical computation; taking a decision in a meeting
of people; cash withdrawal from an ATM …?
– Which abstract machines should we consider?
– What does it mean to be able to solve a problem:
If I am not able to solve the problem by some means I might
be able to solve it by some other one.
2

In fact we can formalize the problem in its broader generality


• The notion of language allows us to formalize any “computer
science problem” :
x  L? (Language recognition problem)
y = t(x)? (Function computation problem)
The two above formulations can be reduced to each other:
– If I can find a machine to solve the problem of computing any function
y = t(x) and I wish to use this to solve the problem x  L, it suffices to
define the predicate function t(x) = 1 if x  L, t(x)=0 if x  L.
– Viceversa, if I wish to compute function y = t(x) I could define the language

L  {x$ y | y   ( x)}
– Assuming that I can recognize L using some machine, then, for a fixed x, I could
enumerate all possible strings y over the output alphabet and for each of them ask the
machine if x$y  Lt: soon or late, if t(x) is defined, I will find the string for which
the machine answers positively: this is a way to compute y= (x).
The procedure is “a bit long” but at the moment we are not concerned about the
length of computations
3

• Concerning the machine … in fact there exist many, besides


the ones we know; and many more can be invented, so we might
be able to get results of the kind
{anbn | n > 0} is accepted by a PDA and a TM but not by a FA.
• However we noticed that it is not so easy to overcome the computing power
of the TM: adding tapes, heads, nondeterminism, … does not increase the
power, (i.e., the class of accepted languages);
It is not so difficult to have the TM do what a normal computer does: It
suffices to simulate the memory of one of the two by the other one

HENCE
there is a ultimate generalization:
4

Church Thesis (back to 1930’s!)


• There does not exist a computational device more powerful than
the TM or any other formalism that is equivalent to it
It is not a theorem (in principle, it should be checked every time
anyone comes up with a new computational model)
• No algorithm, independently from the tool used to implement it,
can solve problems that cannot be solved by a TM: the TM is the
most powerful computer that we have and will ever have!
• Then the question “Which are the problems that can be solved
algorithmically (or, with an equivalent term, “automatically”)?”
can be answered:
These are the problems that can be solved by the (relatively
simple) TM
5

Then let us focus on the TM

• Are there problems that cannot be solved by a TM?


• How can we find them?

The answers that we find hold also for C programs,


Java programs, supercomputers ….
6

A few simplifications, without loss of generality:


• Single tape TM, on a fixed alphabet A = {0, 1, _}
• NB: fy(x) =  by definition if My does not stop when it takes x
as input
• Conversely we stipulate
– if fy(x) =  then it means that the y-th TM does not stop on x
– it suffices to stipulate that any TM My that, on input x, stops in a non final state
(that does not define any significant output value fy(x)), is by convention equivalent
to a TM that enters a new state and continues forever, for instance by moving
indefinitely the head right
• Therefore, fy(x) =  if and only if My does not stop when it
takes x as input
7

First, relevant fact:

• We can algorithmically enumerate TM’s


• Enumeration of a set S:
• E: S N
• Algorithmic Enumeration: E can be computed by an
algorithm, hence (church Thesis…) by a TM
• Algorithmic Enumeration of {a, b}*:
• {e, a, b, aa, ab, ba, bb, aaa, aab, aba, abb, …}

• {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ….}


– Usually called the “lexicographical ordering”
8

• Every TM is identified by its transition function:


• d: Q  A  Q  A  {L, R, S}  {}
• Let us order all the machines by the number of states,
then we choose an arbitrary order for the tuples
defining the elements of the transition functions.
• In general: how many functions of type f: D  R are
there?
• |R||D| (for each xD we have |R| choices}
• With |Q| = 1, |A| = 3, (1⋅3⋅3+1)(1⋅3) = 1000 one-state TM
• Let's order them: {M0, M1, … M999};
• then we order in the same way those with two states, that
are (2⋅3⋅3+1)(2⋅3) = 196 = 47,045,881; and so on...
9

|Q| = 1: MT0 0 1 _ MT1 0 1 _

q0 ⊥ ⊥ ⊥ q0 (q0,0,L) ⊥ ⊥

MT2 0 1 _

q0 (q0,0,R) ⊥ ⊥ ...

MT999 0 1 _

q0 (q0,1,S) (q0,1,S) (q0,1,S)

|Q| = 2: MT1000 0 1 _ MT1001 0 1 _

q0 ⊥ ⊥ ⊥ q0 (q0,0,L) ⊥ ⊥

q1 ⊥ ⊥ ⊥ q1 ⊥ ⊥ ⊥

...
10

• We obtain an enumeration E: {TM}  N


• E is algorithmic (or effective): we can write a C program
(i.e., a TM…) which, given n, produces the n-th TM (for
instance by providing a table defining d) and vice versa,
given a (table describing a) TM M, tells the position E(M)
of M in the enumeration.
• E(M) is called the Goedel number of M, E a goedelization
• A further convention: since we are speaking of
numbers from now on we identify (for what concerns
computability)
• Solving a problem = computing a function f: N  N
• fy = function computed by the y-th TM
11

Second relevant fact:


• There exists a Universal Turing Machine (UTM): the TM that
computes the function g(y, x) = fy(x)
• The UTM seems not to belong to the family {My} because fy is a
function of one variable, while g is a function of two variables
• But we know that integer pairs can be effectively enumerated,
i.e., N  N  N : an example enumeration:

( x  y )( x  y  1)
6 d ( x, y )  x
3 2
1 4

0 2 5
12

• So we can devise a suitable g^(n) such that g^(n) = g(d-1(n))=g(y, x);


g(y,x) is encoded as g^(n), with n=d(y,x), i.e., <y,x>=d-1(n)
Notice that d and d-1 are both computable
• Sketch of the operation of the UTM that computes g^ (NB from now on
for simplicity we will simply write g instead of g^):
– Given n, the UTM computes d-1(n) =<y,x>
– Then it builds the transition function of My (by computing E-1(y)) and stores it on
some portion of a tape:

$ q a q’ a’ S $ .. ..

- In another tape portion it stores an encoding of the configuration of My

# 0 1 0 .. 1 q 1 1 0 #

NB: The special symbols #, $ and other ones are coded as binary strings
At the end the UTM leaves on the tape fy(x) if and only if My terminates on x
13

• The TM is a very abstract and simple model of a computer


• Let us pursue further the analogy:
• TM: computer with a single, built-in program
An “ordinary” TM always executes the same algorithm, i.e.,
it always computes the same function
• UTM: computer with memory-stored program:
y = program
x = input to the program
14
Back to the question
“which problems can be solved algorithmically?

• How many and which are the computable functions fy: N  N ?


• First, “how many” functions (not necessarily computable) are there?
• {f: N  N}  {f: N  {0,1}} 
|{f: N  N}|  |{f: N  {0,1}}| = |(N)| = 20
• On the other hand, the set {fy: N  N} of computable functions is
by definition denumerable:
NB: E: {My}  N induces E^: N  {fy} not one-to-one (in many
cases fy = fz, with z  y) but (a fortiori) it allows us to state that
• |{fy: N  N}| = 0 < 20 
• “most” of the functions (problems) cannot be solved algorithmically!
• There are (very many) more problems than programs!
15

Is this such a bad issue?


• In fact, how many problems can be defined?
• To define a problem we typically use a phrase (a string) of some language:
– f(x) = x2
x
f ( x)   g ( z )dz
a

– “the number that multiplied by itself is equal to y”


– …
• But any language (over some alphabet A) is a subset of A*, which also is a
denumerable set 
• Hence the set of the problems that can be defined is also denumerable, just
like the set of the problems that can be (algorithmically) solved
• Therefore we can still hope that they are the same
Certainly {Solvable Problems}  {Definable Problems}

(BTW, a TM defines a function, besides computing it)


16
Next we turn again to the question:
“Which problems can be solved?”
• The problem of termination
(it has quite “practical” implications):
– One can build a program
– One can provide input data for it
– One knows that in general the program might not terminate its
execution (in jargon: “run into a loop”)
– Can one determine if this will occur?
• NB: determine «in advance», not by running the program on the input and ...
• Stated in –completely equivalent– terms of TM:
– Given (predicate) function g(y, x) = 1 if fy(x), g(y,x) = 0 if fy(x)=
– Does there exist a TM that computes g? (i.e., is g computable?)
17

Answer: NO
• That’s why a computer (which is a program) cannot
warn us that the program we just wrote will run into an
endless execution on a given input datum (while it
easily signals a missing “}”):
• Determining if an arithmetic expression is well
parenthesized is a solvable (decidable) problem;
• Determining if a given program will run into an endless
execution on a given input is an algorithmically
unsolvable (undecidable) problem [we will see many
more ones: there are many things that a computer
cannot do]
18
Proof
• It employs a typical diagonal technique (adopted also in the Cantor theorem to show
that 0 < 20 )
• Let us assume (by contradiction) that the total function :
g(y,x) = 1 if fy(x) , g(y,x) = 0 if fy(x) =
is computable
• Then also the partial function
h(x) = 1 if g(x,x) = 0 (i.e., if fx(x) =),
 if g(x,x) = 1 (i.e., if fx(x) )
is computable
NB: we went on the diagonal y=x, we changed the no answer (g(x,x) = 0) into a yes
answer (h(x)=1), and we turned the yes (g(x,x) = 1) into a nontermination (h(x)=),
which can always be easily done by modifying the TM that (supposedly) computes g
• If h is computable then h = fx’ for some x’.
19
RECALL h(x) = 1 if g(x,x) = 0 (i.e., if fx (x) =), h(x) =  if g(x,x) = 1 (i.e., if fx (x) )

• Question: h(x’) = 1 or h(x’) =?


• Let us assume that h(x’) = fx’ (x’) = 1
• Then g(x’,x’) = 0, that is, fx’ (x’) =  :
• A contradiction

• Then let us assume the opposite: h(x’) = fx’ (x’) = 


• Then g(x’,x’) = 1, that is, fx’ (x’)   :
• Another contradiction
then the assumption was wrong QED
20
• A first corollary of the unsolvability of the halting problem for the TM
– The predicate (hence total function) characterizing the set of computable functions
that are defined when applied to themselves : h(x)=1 if fx(x) ; h(x)=0 if fx(x) =
is not computable
– By itself the assertion is not very meaningful (but it will be so later)
– Notice that h(x) is a special case of function g(y, x)
g(y,x) = 1 if fy(x) , g(y,x) = 0 if fy(x) =
[because h(x)=g(x,x)], and g was just proved to be uncomputable
– Notice that the uncomputability of h(x) is not a necessary consequence of the
uncomputability of g(y,x):
– NB: in general, if a problem is unsolvable, then a special case of it might be solvable
(e.g., some properties that cannot be decided for any language can be decided for
regular languages); instead a more general case of an unsolvable problem is
necessarily unsolvable.
On the contrary if a problem is solvable, any special case of it is certainly solvable,
while a generalization of it might be unsolvable.
21
Another important unsolvable problem
• The (predicate, hence total) function
k(y) = 1 if fy is total, i.e., fy(x)    xN; k(y) = 0 otherwise
is not computable

• From a practical viewpoint, this problem is perhaps even more relevant than the
halting problem:
• given a program, one wants to know if it will terminate the execution for every input
datum or if it may, for some datum, run into an endless execution.
• In the problem of termination, instead, one was interested to know if a given program
with some given input datum would terminate.
• NB: this result is a trivial consequence of the coming Rice Theorem, because function
k is a predicate characterizing total computable functions
22

• NB: it is a problem similar to but different from the previous one. Here we have a
quantification w.r.t. all possible input data.
• For this problem, testing is useless: In some cases one could be able to establish, for a
large set of values of variabile x, that fy(x) , without however being able to answer
the question “is fy a total function?” (Obviously, if one finds an x such that fy(x) =,
one can conclude that fy is not total, but what if one does not find it?)
• Vice versa, one could be able to conclude that fy is not total and however be unable to
decide whether fy(x)   for a given single x.
• (However, if one was able to conclude that fy is total there would be no doubt on
whether fy(x) for a given x)
23

Proof
• Standard technique: diagonal + contradiction, with some more technical
detail.
• Hypothesis: k(y) = 1 if fy is total, i.e., if fy(x)   xN; otherwise k(y) = 0
is computable and obviously, by definition, total
• Then define g(x) = w = index (Goedel number) of the x-th TM (in E) that
computes a total function.
• If k is computable and total, then so is g:
– compute k(0), k(1), …, let w0 the first value such that k(w0) = 1, then let g(0) = w0;
– then let g(1) = w1, w1 being the second value such that k(w1) = 1; …
– the procedure is algorithmic; furthermore, being total functions infinite in number,
g(x) is certainly defined for each x, hence it is total.
• g is also strictly monotonic: wx+1 > wx;
• hence g-1 is also a function, strictly monotonic too, though not total: g-1(w) is
defined only if w is the Goedel number of a total function.
24

Next define
(a) h(x) = fg(x)(x) + 1 = fw(x) + 1:
fw is computable and total hence so is h 
(b) h = fw0 for some w0;
since h is total, g-1(w0)  , let g-1(w0) = x0 (hence w0= g(x0))
• What is the value of h(x0) ?
– h(x0) = fg(x0)(x0) + 1 = fw0(x0) + 1 (from (a))
– h = fw0 hence h(x0) = fw0(x0) (from (b))
• Contradiction!
25
A crucial remark: knowing that a problem is solvable
does not mean being able to solve it!
• In mathematics we often have non-constructive proofs: one shows that a
mathematical object exists without providing a way to actually find (and
exhibit) it
• In our case:
– a problem is solvable if there exists a TM that solves it
– for some problems we can reach the conclusion that there exists a TM that solves
them, but, despite our knowledge of this, we are unable to find (build) it or we do not
know which one it is in a set of TM that certainly includes the “right one”
• Let us start with a trivial case
– The “problem” consists of answering a question with a yes/no answer (a so-called
closed question, whose answer does not depend on an input value/parameter):
10
• Is it true that the number of atoms in the universe is 10 101010 ?
• Is it true that the “perfect chess game” will end in parity?
• ….
26

• In such cases one knows a priori that the answer is either Yes or No, though one does
not know (or did not until some point in time) which one it is
• This fact is less surprising if we consider that
Problem = function; solve a problem = compute a function
What function can one associate to the above problems?
If one encodes TRUE=1; FALSE=0, all the above problems are expressed by one of
the following two functions: f1(x) = 1 x, or f0(x) = 0 x
Both functions are trivially computable (all constant functions are…), hence
Whatever the answer is, it is computable, though not necessarily known.
• More abstractly, considering for instance function g(y, x) of the halting problem:
g(10,20) = 1 if f10(20) , g(10,20) = 0 if f10(20) =;
g(100,200) = 1 if f100(200) , g(100,200) = 0 if f100(200) =; ...
Hence g(10,20) (i.e.: does TM M10 stop on input 20?), g(100,200), g(7,28) etc. are all
solvable problems, though we do not necessarily know the solution (i.e., the value of g
for those arguments).
27
Decidability and semidecidability
Or: 1/2 + 1/2 = 1
• Let us focus on the problems stated in such a way that the answer is binary:
Problem = “given set S  N and xN, x  S?”
(NB: all problems can be (re)phrased in such a way,
because they can all be viewed as a language)
• characteristic function or characteristic predicate of a set S: it is the
predicate characterizing the set
cS (x) = 1 if x  S, cS (x) = 0 if x  S
(NB: cS is total by definition)
• A set S is recursive (R) or decidable if and only if its characteristic function
is computable
– Note on terminology: It is also customary to say that solvable problems are decidable
28

• S is recursively enumerable (RE) (or semidecidable) if and only if:


– S is the empty set, or
– S is the image of a total, computable function gS, the generating function of S:
S  I g S  {x | x  g S ( y ), y  N }
notice that this implies
S  {g S (0), g S (1), g S (2), g S (3),...}
the term “recursively (i.e., algorithmically) enumerable” comes from this
“enumeration”
– The term “semidecidable” can also be explained intuitively:
given the question “xS?”, if xS then, by enumerating the elements of S,
soon or late one finds x and is able to get a correct (yes) answer to the
question;
but what if x  S ? In this case the above procedure does not work: using
function gS one continues indefinitely to generate elements of S without coming
to a conclusion.
– A formal characterization of this matter comes from the following ...
29

Theorem
• A) If S is recursive, it is also RE
(i.e., decidable is more than –not less than- semidecidable)
• B) S is recursive if and only if both S itself and its
complement S^ = N - S are RE
(two “semidecidabilities” make a “decidability”; or, when
answering NO is equivalent to (i.e., it is equally difficult
as) answering Yes
• (Corollary: the class of decidable sets (languages,
problems, …) is closed under complement)
• Proof:
30

A): S recursive implies S RE


• If S is empty it is RE by definition
• Let us then assume S   and call cs its characteristic
predicate: note that, since S  ,
 k  S, that is  k cs(k) = 1
• Let us define the generating function gs as follows:
gs(x) = x if cs(x) = 1, otherwise gs(x) = k (the k above)
• gs is total, computable (because so is cs), and Igs = S
• hence S is RE
• NB: it is a non-constructive proof:
do we know if S  ? not necessarily. We only know that if S 
 there exists gs: this is enough for us!
B) S is recursive if and only if both S and S^ = N-S are RE 31

B) equivalent to: (B.1 S recursive  both S and S^ RE) and


(B.2 both S and S^ RE  S recursive)
• B.1.1) S recursive  S RE (already proved in part A)
• B.1.2) S recursive  cS(x) (= 1 if x  S; = 0 if x  S) computable
 cS^(x) (= 0 if x  S; = 1 if x  S) computable
 S^ recursive  S^ RE
• B.2) S RE  construct the enumeration S  {g S (0), g S (1), g S (2), g S (3),...}
S^ RE  construct S ^  {g S (0), g S (1), g S (2), g S (3),...}
^ ^ ^ ^

But S  S^ = N, S  S^ = 
hence x  N , x belongs to exactly one of the two enumerations 
The following enumeration
{g S (0), g S ^ (0), g S (1), g S ^ (1), g S (2), g S ^ (2), g S (3), g S ^ (3),...}
certainly includes any x in exactly one position: if x is at an odd
position, then x  S, if it is at an even position then x  S^. Hence cS
can be computed.
32
Other very important results
• S is RE  S = Dh, with h computable and partial: S = Dh = {x| h(x)  }
and
S is RE  S = Ig, with g computable and partial: S = Ig = {x| y  N : x = g(y)}
• The above theorem allows us to view RE sets as characterizing precisely
the languages recognized/accepted by the Turing Machines
(NB not decided : decide and recognize/accept differ slightly)
• It can also serve as a Lemma to prove that:
• There exist semidecidable sets that are not decidable:
K = {x| fx(x)  } is semidecidable because K = Dh with h(x) = fx(x).
We know however that the characteristic function of K, (cK(x) = 1 if fx(x)  , 0 else) is
not computable  K is not decidable
• Conclusion:
33

(N )

RE sets
Recursive sets
K   K^
S  S^
of previous slide

Inclusions are all strict


Corollary: the class of RE sets (i.e., languages recognized by TM’s)
is not closed under complement
Why? Because if RE sets were closed under complement then all RE sets
would also be recursive (also their complement would be RE…), but we
know (from the previous slide) that this is not the case
34
The mighty Rice theorem
• Let F be a set of computable functions
The set S of (the indices of) TM’s that compute the functions of F
S = { x | fx  F }
is decidable if and only if F =  or F is the set of all computable functions
•  (alas!) in all non trivial cases (f s.t. fF and f s.t. f F) S is not decidable!
•  e.g., the following very interesting problems are unsolvable
– Program correctness: does P solve a given problem (identified by a computable
function f )? i.e., F={f}, P  Mp does p belong to the set S = { x | fx  { f } } ?
– Program equivalence (given My, same problem as above, with the set F={fy} )
– Does a program have any specified property concerning the function it computes
(function with only even values in the image, function with a limited image, …)?
– …
• There is an endless list of interesting problems whose unsolvability follows trivially
from the Rice theorem
35
How can we, in practice, determine that a problem/set
is (semi)decidable or not?

• If we find an algorithm that always terminates  decidable


• If we find an algorithm that may not terminate, but it always
terminates when the answer is positive  semidecidable
• If we think that the problem/set is not (semi)decidable, how can we
prove it?
• Do we have to build a new diagonal proof every time? … no way!
• There are easier means:
• A first, very powerful tool is the Rice theorem
– Applies to many «problems» concerning computation, e.g., software features
• Though implicitly, we have already used another very natural and
general technique:
36

Problem reduction
• If one has an algorithm to solve problem P one can use it to solve
problem P’:
– TRIVIAL EXAMPLE: One can compute the product of two numbers a and b if
one can compute the operations: sum, difference, division by 2, square. It suffices
to use the formula ab=((a+b)2-a2-b2)/2. Hence multiplication is reduced to {sum,
difference, division by 2, square}
– In general if there is an algorithm that, given a instance of a problem P’ builds its
solution by producing (algorithmically) an instance of another problem P that is
solvable, and such that from the solution of P one can obtain algorithmically that
of P’, then P’ has been reduced to P.
– Using the set inclusion formulation of a problem:
• I want to solve x  S’
• I can solve y  S for all possible y
• If I have a computable, total function t such that x  S’  t(x)  S
then I can answer algorithmically the question x  S’
• i.e., I have reduced the problem x  S’ to the problem y  S ( DecS  DecS’ )
37
• The method can work also in the opposite way:
– I want to know if I can solve x  S
– I know I cannot solve y  S’ (S’ is not decidable, DecS’ )
– If I reduce S’ to S, that is, ( DecS  DecS’ )
I find a computable total function t such that y  S’  t(y)  S
then I can conclude that x  S is not solvable (otherwise I could show that xS’ is
solvable by reducing it to xS) ( DecS  DecS’ hence DecS’ DecS)
• In fact, we already used implicitly this way of reasoning several times:
– From the undecidability of the halting problem for the TM we derived in general
the undecidability of the problem of termination of any computation on any
computer; for instance, concerning the termination of C programs:
• Consider a TM My and an integer x
• I can build a C program, P, that simulates My and I can store x in an input file f
• program P terminates its computation on file f if and only if fy(x)  
• If I could decide if P terminates its computation on f then I could solve also the halting
problem for the TM.
38
Reduction is a general, powerful technique
• Is the problem “does a generic program P access an uninitialized
variable?” decidable?
– Let us assume (by contradiction) that it is decidable and let us show by
reduction that in that case the halting problem would be decidable
– We can consider an instance P of the halting problem and reduce it to the
following “uninitialized variable access” problem P^:
• P^:
begin var x, y: …
P;
y := x
end
making sure that identifiers x and y are “fresh variables”, not used in P
• It is clear that the assignment statement y := x results in accessing an uninitialized
variable, because x and y do not occur in P
• Hence the uninitialized variable x is accessed in P^ if and only if P terminates.
– Then if I could solve the problem of “diagnosis of uninitialized variable access”
then I could solve also the termination problem, which cannot be.
39

• The same technique can be applied to prove the


undecidability of many other typical properties of program
execution:
– Array indices out of bounds
– Division by 0
– Dynamic type compatibility
– …
– Typical run time errors: concerning this issue ...
40
• Let us consider again the previous examples
– halt of the TM
– Division by 0 and other run-time errors, …
• The related sets are undecidable, but they are semidecidable:
a. if the TM stops (on a given input), soon or late I find it;
b. more general statement: if there exists any datum x, input of a
program P, such that P, executed on input x, eventually executes a
division by 0, then soon or late I can find it …
• Let us make a digression on the latter problem:
– How can I ensure the above result (b.):
• if I start to execute program P on x and P does not stop on x, how
can I find that P, executed on y  x, will execute a division by 0?
41
• In general: Theorem (abstract formulation of the various concrete cases above):
– The set of values x for which  z such that fx(z)   is semidecidable
(NB: here the “input parameter” of the problem is the TM index x)
– Sketch of the proof
• If I compute fx(0) and find it   then I can answer;
• But what if the computation of fx(0) does not terminate and fx(1)  : how can I find it?
• Then I use the following trick, known as dovetailing:
– I simulate 1 execution step of fx(0): if it stops, then I have answered positively the question;
– Otherwise I can simulate one computation step of fx(1);
– Again if it does not stop I can simulate 2 steps of fx(0); next 1 step of fx(2); 2 steps of fx(1); 3
of fx(0); and so on, according to the scheme in the figure:

input argument z
3

0 n. of steps
1 2 3 4

This way, if  z s.t. fx(z)  , eventually I find it because eventually I will simulate enough
computation steps of fx(z) to terminate
42

• Concluding the digression:


• we have therefore a significant number of problems/sets (typically, related to
run time errors in programs) that are not decidable, but are semidecidable.
• We must however pay attention to which is precisely the semidecidable
problem:
– detecting the presence of the error (i.e., if there is one I can find it)
• NB: the semidecidable set is the set of erroneous programs
– Not its absence! The set in question is that of error-free programs
• Notice however that, since the complement S of a set S (RE – R) is not
even RE (otherwise they would both be decidable),
The absence of errors (i.e., the correctness of a program with respect to an
error) is not only not decidable, but it is not even semidecidable!
• Important implications on verification by testing
– Famous statement by Dijkstra: testing can prove the presence of errors, not their
absence

• Hence, as an additional result, we obtain a systematic technique to prove that


a (unsolvable) problem is not RE: by proving that its complement is RE.

You might also like