{"id":303,"date":"2007-02-06T22:05:30","date_gmt":"2007-02-06T22:05:30","guid":{"rendered":"http:\/\/scientopia.org\/blogs\/goodmath\/2007\/02\/06\/basics-the-halting-problem\/"},"modified":"2007-02-06T22:05:30","modified_gmt":"2007-02-06T22:05:30","slug":"basics-the-halting-problem","status":"publish","type":"post","link":"http:\/\/www.goodmath.org\/blog\/2007\/02\/06\/basics-the-halting-problem\/","title":{"rendered":"Basics: The Halting Problem"},"content":{"rendered":"<p> Many people would probably say that things like computability and the halting<br \/>\nprogram aren&#8217;t basics. But I disagree: many of our basic intuitions about numbers and<br \/>\nthe things that we can do with them are actually deeply connected with the limits of<br \/>\ncomputation. This connection of intuition with computation is an extremely important<br \/>\none, and so I think  people should have at least a passing familiarity with it. <\/p>\n<p> In addition to that, one of the recent trends in crappy arguments from creationists is to try to invoke ideas about computation in misleading ways &#8211; but if you&#8217;re familiar with what the terms they&#8217;re using really mean, you can see right through their<br \/>\nsilly arguments. <\/p>\n<p> And finally, it really isn&#8217;t that difficult to understand the basic idea.<br \/>\nReally getting it in all of its details is a bit harder, but just the basic idea that there <em>are<\/em> limits to computation, and to get a sense of just how amazingly common uncomputable things are, you don&#8217;t need to really understand the depths of it.<\/p>\n<p><!--more--><\/p>\n<p> It makes sense to start with a bit of history. Before people actually built real<br \/>\ncomputers, there was a lot of interest in what could be done by a purely mechanical<br \/>\nprocess. In fact, <a href=\"http:\/\/scienceblogs.com\/goodmath\/2006\/06\/extreme_math_1_1_2.php\">the great<br \/>\nproject of mathematics in the early 20th century was the attempt to create a perfect<br \/>\ncomplete mathematics<\/a>, which meant a new formalization of math in terms of a logic<br \/>\nin which <em>every<\/em> true statement was provably true; every false statement was<br \/>\nprovably false; and given any statement, you could follow a completely mechanical<br \/>\nprocess to find out whether it was true or false.<\/p>\n<p> You most commonly hear about how G&ouml;del wrecked that with his incompleteness theorems. But Alan Turing did something that demonstrates the same basic principle: defining the <em>limit<\/em> of what could be done by a purely mechanical computation process. In the end, what Turing showed about computability is really the same concept as what G&ouml;del showed about logic with incompleteness: the limits of<br \/>\nmechanical\/axiomatic processes.<\/p>\n<p> Fundamentally, what Turing did was prove that there are things that cannot be<br \/>\ncomputed. He did that two ways: first, by defining an easy to understand problem which<br \/>\ncannot be solved by any mechanical device; and second, by showing how common<br \/>\nnon-computable things are.<\/p>\n<p> The first of Turings two proofs is commonly known as <em>the Halting problem<\/em>.<br \/>\nThe simplest version of the halting problem is the following. Suppose you have<br \/>\na computing machine M, and some program, P which can be run on M. Can you write a program which can by looking at P can determine whether or running P will eventually stop?<\/p>\n<p> I actually find the more formalized presentation to be clearer. Take a computing<br \/>\nmachine, which we&#8217;ll call &phi;. (Don&#8217;t ask why &phi;, it&#8217;s just tradition!) Now,<br \/>\nsuppose we have a program <em>P<\/em> for &phi; which computes some function on its<br \/>\ninput. We&#8217;ll call that function &phi;<sub>P<\/sub>. So &phi;<sub>P<\/sub>(i) is the<br \/>\nresult of running the program P on the input i using the machine &phi;.<\/p>\n<p> So the halting problem is really the question: given a machine &phi;, is there<br \/>\na program H where &phi;<sub>H<\/sub>(P,i) = YES if and only if &phi;<sub>P<\/sub>(i) will halt, and will return &#8220;NO&#8221; if &phi;<sub>P<\/sub>(i) would <em>not<\/em> halt. The program H is called a <em>halting oracle<\/em> &#8211; so the question is, is it possible to write a halting oracle?<\/p>\n<p> The answer is <b>no<\/b>. You can&#8217;t write a program like that &#8211; no such program can possibly exist. And it&#8217;s actually really quite easy to show you why &#8211; because if there <em>were<\/em> a halting oracle H, it&#8217;s very easy to write a program for which <em>H<\/em> is guaranteed to get the wrong answer.<\/p>\n<p> Take the halting oracle program H. Write a program T which <em>includes<\/em><br \/>\nH, and which does the following:<\/p>\n<ul>\n<li> If &phi;<sub>H<\/sub>(T,i)=YES (meaning that the halting oracle says that T<br \/>\nwill halt on input I), then T will run an endless loop, thus never halting.<\/li>\n<li> If &phi;<sub>H<\/sub>(T,i)=NO (meaning that the halting oracle says that T will<br \/>\n<em>not<\/em> halt on input i), then T will immediately halt.<\/li>\n<\/ul>\n<p> So T completely defeats the Halting oracle. No matter what you do, for any program that claims to be able to tell whether other programs halt, there are programs for which they can&#8217;t get the right answer. There&#8217;s always a program that for a given halting oracle will do exactly what the oracle says it won&#8217;t. And that, in turn,<br \/>\nmeans that there are some functions that simply <em>cannot<\/em> be computed. And here&#8217;s the neat twist: given a halting oracle H, it&#8217;s easy to write a program which will<br \/>\n<em>generate<\/em> the program that defeats H &#8211; that is, the Halting oracle is non-computable, but if it were computable, then the program that defeats it would<br \/>\nalso be computable.<\/p>\n<p> Turing, genius that he was, was not satisfied with that as a result. He wanted to<br \/>\nunderstand <em>more<\/em> about what could and could not be computed. Did you need to<br \/>\nhave a program which looked at itself to cause a problem? Was it just meta-programs that were the problem? Or were there simply natural functions which just could not be computed?<\/p>\n<p> The answer was that there are <em>lots<\/em> of things that can&#8217;t be computed &#8211; in fact, <em>most<\/em> functions are not computable! Just like most numbers are irrational, most functions are not computable. I&#8217;m not going to go through the proof here &#8211; but here&#8217;s a very basic sketch:<\/p>\n<p> Suppose we limit ourselves to just thinking about functions on the natural numbers: {f | f:<b>N<\/b>&rarr;<b>N<\/b>}. How many functions are there in that set? It&#8217;s an infinite set &#8211; and it&#8217;s an infinite set <em>larger than<\/em> the infinite set of natural numbers. For a computing machine, you can map every one of its programs to a natural number &#8211; so the computing machine can only have as many programs as there are natural numbers. So there have to be values in that infinite set of functions that have no program that compute them.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many people would probably say that things like computability and the halting program aren&#8217;t basics. But I disagree: many of our basic intuitions about numbers and the things that we can do with them are actually deeply connected with the limits of computation. This connection of intuition with computation is an extremely important one, and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[74,54],"tags":[],"class_list":["post-303","post","type-post","status-publish","format-standard","hentry","category-basics","category-programming"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4lzZS-4T","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/comments?post=303"}],"version-history":[{"count":0,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/303\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/media?parent=303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/categories?post=303"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/tags?post=303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}