Accidentally Turing-Complete
beza1e1.tuxen.de
beza1e1.tuxen.de
There is a guy who run Doom with only mov instructions, but it is of course incredibly slow, one frame every 7 hours :) [2]
> Our result is also highly unusual in that all moves of both players are forced in the construction. This shows that even recognising who will win a game in which neither player has a non-trivial decision to make for the rest of the game is undecidable.
At first I thought this was pretty mind-blowing for a game, but actually this is directly comparable with a Turing machine; each step is forced, mechanical and very easy to derive, and yet, the overall behaviour is generally undecidable.
Python pickle files are a sequence of op-codes that run on the pickle VM. By default the VM allows calls to arbitrary Python functions. I'm still puzzling whether Python pickles without access to Python globals (e.g. using https://docs.python.org/3/library/pickle.html#restricting-gl...) are Turing complete. I don't think so, because the pickle VM has no branching or looping, but it does have a stack and my understanding of automata theory is not great.
My research/tinkering so far is https://github.com/moreati/pickle-fuzz
N.B: "Turing complete" really means a lot less than you seem to believe.
(A pushdown automaton can do branching if it wants, but the lack of looping / going left is critical.)
[1] https://en.wikipedia.org/wiki/Total_functional_programming
The overall loss of expressiveness is surprisingly small, but the number of details you have to work around is annoying.
I've used a scripting system for a server that was intentionally written this way to bound the harm a misbehaving script could have on the server.
RE2 is also designed along these lines https://swtch.com/~rsc/regexp/regexp3.html
This is the problem. Interesting computing is some impossibly complex (undecidable, in fact) subset of all computing, that you try to get inside of via the practice of software engineering. Turing's theory of computation provides reasoning tools which allow us to bring rigor to the idea that building correct software that does useful things is generally difficult.
> Designing a computing model that only covers what's useful while also making it convenient appears to be a long standing open problem.
Per the above point, depending on how you characterize this goal, it's probably impossible to accomplish.
I totally disagree here. Or at least I totally disagree that it's a resolved question. All of those nasty problems that face some interesting programs don't face programs we actually write. For example, there is a subset of all turing complete programs that halt. The boundary of that subset isn't decidable, but when I'm writing a program that needs to halt, I write a program I know will halt (why are you pushing to prod if you don't know this program will halt?). Expending a ton of proof effort, I could prove that it halts. So I think the stuff we actually build in practical software is really far from the boundary of the nasty stuff.
Suppose I had a programming language that had a termination checker and only allowed programs it can prove will terminate. We know that the termination checker will have to return yes, no, and who knows. It can't just say yes and no without being wrong sometimes, because it's an undecideable problem. Maybe there's some termination checker that can correctly say yes to all the programs we really care about. Since I could prove that my programs terminate, this checker must exist. A language that only allows these programs must not be turing complete.
So there must be some non turing-complete languages that can express all the programs I would push to prod at work. Maybe some of those languages are even worth using.
So you can have a practical, useful, non-Turing-complete language by forcing every function to have a limit on the number of steps it can take. It can be implicit if you want. In practice, most embedded scripting systems use this route, which is why you don't really need a separate language just for non-Turing-completeness.
For example, finding out whether a time-bounded Turing machine outputs 0 all inputs is still undecidable. (coRE-complete, in fact. That's better in some sense than the Pi_2-completeness of the same problem for Turing machines without the time bound, but since neither admits a solution in the form of a computer program, a lot of people would consider the difference an academic curiosity only.)
Is that a problem? I mean, if you're installing a timeout then haven't you already decided that the answer is "no"?
I singled out "outputting 0" on every input because it's among the simplest possible specs you could try try to check with the kind of "very powerful semantic analysis" tool the top-level post was hoping for. In practice you probably want to check a more complex spec -- you want your code to solve a specific problem on whatever input it receives -- but if the "always output 0" spec is impossible to automatically check, then what hope do more relevant specs have?
No it's not; call the time bound N; the TM can only inspect N symbols, so there are 2^N possible inputs; a exhaustive check takes O(N*2^N) operations.
Call the time bound c|x|^k, where x is the input and c and k are constants.
I see what point you're making, and I agree that you get yourself a nice, merely coNP-complete problem if you're willing to cut off the space of inputs at a point by enforcing a constant time bound or whatever. More than anything, this kind of argument makes me shudder at just how hard the very worst stuff in NP must be.
But yes, it should reduce to NP territory. If you actually had a nondeterministic CPU, then for most use cases you could fully evaluate these machines in seconds.
This is backwards; I meant that if you have any time bound whatsoever, the number of inputs you can inspect is limited to (a architecture-specific finite multiple of) the number of operations you can execute (because inspecting a input is such a operation).
That is literally the problem statement you gave. I was pointing out that it is very much not undecidable.
It might be (almost certainly is, in this case) computationally intractable both in the general case and in practice, but it's still decidable.
Each of these things aims to allow the user to specify a task in a restricted model of computation. In turn, it tends to be possible for the engineer writing the solver to build an engine capable of very radical transformations, optimizations, and analyses, that generally can't be matched by compilers and interpreters for Turing-complete programming languages.
Nope. I'm going to argue this every time I see it. It only demonstrates basic arithmetic. When an external actor has to come along and take each iteration's output and manually do things with it, you don't have Turing completeness.
Edit: ok I get it. Still, GP observation is hardly at that level from my (limited) perspective. Not being able to advance by itself means it's not a standalone system - otoh external actor is obviously implicit for many other examples as well. I suppose they (and me) are taking the word machine too literally.
But "pens are Turing-complete" seems a bit, well, diluted.
This fantastic hack escapes the game, loads a couple bootstrapping sequences and then proceeds to turn Pokemon into a MIDI player.
It's really cool, but it's notably different from using actual ingame mechanics to compute.
And there are much more fun versions of pokemon yellow total control than the link you and the article have. https://www.youtube.com/watch?v=zZCqoHHtovQ
Sure, they didn't set out saying "we want to design a Turing-complete generics system" (because what kind of problem statement is that?), but templates were explicitly designed to be as general-purpose as possible. Turing-completeness was the result of that design goal:
"...I had aimed for generalty (and gotten Turing completeness modulo translation limits). I opposed restrictions to C++ immediately when Erwin Unruh presented what is widely believed to be the first template metaprogram to the ISO Standards committee's evolution working group."
PCRE can do that too (for numbers in unary). https://www.masteringperl.org/2013/06/how-abigails-prime-num...
Also, executable config files (deterministic or not) aren't so easy or pretty to programmatically modify. If the config file can define arbitrary functions and use them to compute the config, then if you want to tweak the config with a tool like an IDE or package manager, then it will need to try to recognize a pattern in the config file, or add a chunk of code at the bottom that just mutates the config file after your handwritten code.