JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

The Loophole: Why Recognizers May Loop

The previous guide drew the line between deciding and merely recognizing. This one walks straight into the loophole that creates that line — the third fate, looping forever — and shows exactly why a recognizer is allowed to never answer, why that single permission makes recognizable strictly weaker than decidable, and why you can never tell from the outside whether a silent machine is thinking or stuck.

Three fates, and the one that hides

By now you know the Turing machine as an endless notebook you can read, erase, and rewrite, and you know its computation on an input can end in one of three ways. It can halt in the accept state. It can halt in the reject state. Or — and this is the fate that does all the mischief in this rung — it can loop forever, never stopping at all. A DFA, a turnstile that only remembers its current state, never had this problem: it reads each input symbol exactly once and stops the instant the string runs out. The Turing machine, free to walk back and forth across its tape as many times as it likes, can quite literally run on for eternity.

The previous guide pinned down two classes that differ on exactly this third fate. A language is decidable (also called recursive) if some Turing machine — a decider — accepts every string in the language and rejects every string not in it, and crucially HALTS on every input, no looping ever. A language is recognizable (also called recursively enumerable, or just r.e.) if some Turing machine accepts exactly the strings in the language — but on a string NOT in the language it is allowed to do the loophole thing: it may reject, or it may simply run forever and never answer. A decider promises a verdict on everything; a recognizer only promises to eventually say 'yes' to the members.

Where the loop actually comes from

It is tempting to think a loop is just a bug — a machine someone designed carelessly. Sometimes it is. But the deep point of this rung is that for some languages looping is UNAVOIDABLE: no matter how cleverly you design the machine, there is no way to recognize the language AND always halt. To feel where the loop comes from, picture the most natural way to recognize a language: try things and see if one works. Suppose your language is 'all strings w such that some computation, somewhere, eventually does X'. The obvious recognizer searches: try the first candidate, then the second, then the third. If an answer exists, the search finds it and accepts. But if no answer exists, the search never ends — there is always one more candidate to try. The loop is not sloppiness; it is the shape of an unbounded search with no built-in stopping point.

Here is the trap that makes it genuinely impossible to fix in general. To turn that searching recognizer into a decider, you would need to detect 'I have searched enough; no answer will ever come' and halt with a reject. But for the hardest languages, deciding that the search will never succeed is itself an undecidable question — it is, in disguise, the very halting problem you will meet in the next rung. So you are stuck: you can recognize the language (accept when you find an answer), but you cannot in general recognize the ABSENCE of an answer in finite time, which is exactly what a clean reject would require. That gap between 'find a yes' and 'be sure of a no' is the entire reason recognizable is strictly weaker than decidable.

Why you can't just add a timeout

The most common beginner reflex is: 'Fine — just stop the machine after, say, a million steps and reject if it hasn't accepted.' This patches a SPECIFIC input but breaks the language. A real member of the language might genuinely need two million steps before it accepts; cut it off at a million and you now WRONGLY reject a string that belongs. Whatever finite cutoff you pick, some legitimate computation needs more. There is no single number that is 'enough' for all inputs, because the running time of the members has no finite upper bound. The timeout trades the loop for incorrectness, which is no fix at all.

There is a subtler illusion too: 'just detect when the machine repeats a configuration, and if it does, declare a loop.' Remember a configuration is the complete snapshot of (current state, entire tape contents, head position). If a deterministic machine ever returns to a configuration it has been in before, then yes, it is doomed to repeat that cycle forever, and you could safely reject. The catch is that the tape is unbounded: a machine can loop forever WITHOUT ever exactly repeating a configuration, simply by writing new symbols onto fresh tape on every pass — like a clerk who never stops because the ledger never runs out of blank pages. Non-repetition does not imply termination. So configuration-cycle detection catches some loops, never all of them.

What the loophole costs the closure properties

The loophole leaves a precise fingerprint on which set operations the two classes survive. Recall from the regular-language rungs that a class is closed under an operation if applying it to languages in the class always lands you back inside the class. The decidable languages are beautifully closed: under union, intersection, complement, concatenation, and the Kleene star, the result is always decidable again. The reason complement works is simple and rests on halting: take a decider for L, run it, and FLIP its answer — accept becomes reject, reject becomes accept. Because the decider always halts, the flipped machine always halts too, so it decides the complement of L.

Now watch the same flip trick fail for recognizers, and watch the loophole be the saboteur. The recognizable languages ARE closed under union and intersection — for union, run two recognizers in parallel (interleaving their steps, a move you will study as dovetailing in a later guide) and accept if either accepts. But they are NOT closed under complement. Try the flip: take a recognizer for L and swap accept and reject. The problem is the loop. On a string not in L, the original recognizer might loop forever — and a machine that never halts has no answer to flip. The flip only works when the machine halts, and a recognizer is exactly the kind of machine that might not. So 'flip a recognizer' produces a machine that still loops on those same strings, accepting nothing on them, which fails to recognize the complement.

Operation      Decidable (recursive)   Recognizable (r.e.)
-------------  ---------------------   -------------------
union             closed (yes)            closed (yes)
intersection      closed (yes)            closed (yes)
complement        closed (yes)            NOT closed   <-- the loophole
concatenation     closed (yes)            closed (yes)
Kleene star       closed (yes)            closed (yes)

Why complement splits the two classes:
  decider for L  --> always halts --> FLIP accept/reject --> decides complement.  works.
  recognizer for L --> may LOOP on non-members --> nothing to flip --> fails.
A side-by-side closure table. The single row where the two classes disagree is complement, and the cause is the loop: you can always flip a machine that halts, but you cannot flip a non-answer.

The complement is the real prize

That failure of complement is not a technicality — it is the whole hinge of the next guide, so let it land. The complement of a recognizable language has its own name: a language is co-recognizable if its complement is recognizable. Think of a co-recognizable language as one where you can reliably confirm NON-membership but the membership 'yes' might loop. It is the recognizable picture held up to a mirror: instead of a trustworthy yes and an unreliable no, you get a trustworthy no and an unreliable yes.

Now the punchline you will prove next time, stated here so you can see where the loophole is leading. A language is decidable EXACTLY when it is both recognizable AND co-recognizable: decidable equals recognizable plus co-recognizable. The intuition is gorgeous. If you have one machine whose 'yes' is trustworthy (recognizer for L) and a second machine whose 'no' is trustworthy (recognizer for the complement of L), run both at once. On any input, exactly one of them will eventually halt and answer — and whichever speaks first gives you the correct verdict, with no possibility of looping forever. Two unreliable halves, each covering the other's blind spot, combine into one reliable decider.

Step back and place the three classes on a map you can keep. Every decidable language is recognizable (a decider is in particular a recognizer that happens never to loop), so decidable is a strict subset of recognizable. The same flip argument shows decidable is also a subset of co-recognizable. And the overlap — recognizable AND co-recognizable — is exactly decidable, no more and no less. Outside both lie languages so wild they cannot even be recognized at all. That clean three-ring picture is the destination, and the only thing that carved the rings apart was the small, unfixable permission to loop forever.