Previously, I described a type of probabilistic oracle machines that I think is powerful enough to allow the implementation of a variant of AIXI that can reason about worlds containing other instances of this variant of AIXI. In this post, I describe how to implement a simplicity prior (a variant of Solomonoff induction) in this framework; there are some technical issues which will also come up when implementing AIXI that are easier to talk about in the context of Solomonoff-like induction.
Solomonoff induction is a prior probability distribution over infinite bit strings, . We want to define a similar prior using probabilistic oracle machines with reflective oracles instead of Turing machines---and then "implement" that prior as a probabilistic oracle machine with that oracle.
The basic idea is simple. Say that a probabilistic oracle machine is a hypothesis if, for every oracle , invoking almost surely outputs an infinite bit string. Fix some programming language for probabilistic oracle machines, and randomly choose a program implementing a hypothesis , where the probability of each program of length is proportional to . Then run , where is our actual, reflective oracle, to obtain a sample bit string. This concludes the definition of our prior.
This also suggests how we could implement this prior, as a probabilistic oracle machine that samples bit strings with these probabilities; it seems like all we need is a way to test whether or not a given program implements a hypothesis. I'll tackle that problem later in this post, but first let me point out a different problem: simply running the hypothesis that we've sampled in the first step is not an ideal way to implement the prior.
Suppose that we want to determine the probability that the output of starts with . Well, here's an idea: why don't we use our reflective oracle?
To do so, we need to write a query which returns if the output of has the right prefix, otherwise. Easy, or so it seems; run until it has outputted the first seven bits, check whether they're , return or accordingly. Then we can call our oracle on , for any , to check whether the probability of the prefix is greater or smaller than .
But a requirement for a machine to be a query is that it halts with probability one, for every oracle . In the implementation of given above, any way we might find to check whether an arbitrary program is a hypothesis will certainly involve a use of the reflective oracle, which means that if we run on an arbitrary oracle , we might end up choosing a "hypothesis" which loops forever without producing any output. Thus, the machine described in the previous paragraph also has a positive probability of looping forever when run on this bad oracle, which means that it isn't a query.
To fix this, let's change the definition of in such a way as to turn it into a hypothesis (i.e., into a machine that almost surely outputs an infinite bitstring, no matter what oracle it's run on). Then the described above will be a query, and we can use this method to compute the probabilities of arbitrary finite prefixes.
To do so, we need to make sure that once we sampled an , we definitely output an infinite bitstring, no matter what our oracle is and whether or not is actually a hypothesis. Of course, if is a hypothesis and we're running on a reflective oracle, then we want to output a sample from (with the correct distribution).
We can do this---with a simple trick. Let's start by letting be the machine which runs until it outputs its first bit, and then returns that bit. If is a hypothesis, then is a query.
So we call our oracle on the pair , and throw a fair coin.
- If the coin comes up heads and the oracle says "false" (the probability of returning is smaller than 0.5), we output a zero.
- If the coin lands heads and the oracle says "true", we output a one.
- If the coin lands tails and the oracle says "false", we call our oracle on and repeat the process; if the coin lands tails and the oracle says "true", we call the oracle on and repeat.
This way, if we're running on a reflective oracle, we output a bit with the same distribution as the first bit outputted by ; but no matter what oracle we're running on, we definitely output a bit with probability one (because in each step of the binary search described above, we have a 50% probability of producing output).
This technique generalizes beyond the particular query we were talking about above:
Lemma (Protecting queries). There is a computable function which takes the Gödel number of a probabilistic oracle machine and returns the Gödel number of a different probabilistic oracle machine, such that (i) is a query, and (ii) if is also a query, and is a reflective oracle, then has the same distribution as .
This gives us the first bit. Now we want to produce a second bit of output, whose probability distribution is the same as the distribution of the second bit of ---conditional on having produced the first bit that we just produced.
Here's a simple way to do so. Suppose that the first bit was a . Let now be the following machine: Run until it produces its first bit. If that bit is a , start over. If the bit is a , run it until it produces its second bit, and return that bit.
If is a hypothesis which has a positive probability of producing a as its first bit, then is a query. Assuming this is safe if we're running on a reflective oracle, since in this case the probabability that we choose as our first bit is equal to the probability that chooses as its first bit.
Now we apply the above lemma about queries, with this new . This gives us an actual query, which we can just run since it is guaranteed to halt, and which has the correct distribution if we're running on a reflective oracle.
We can use exactly the same procedure for each of the later bits, leading to a lemma exactly analogous to the earlier one for queries:
Lemma (Protecting hypotheses). There is a computable function which takes the Gödel number of a probabilistic oracle machine and returns the Gödel number of a different probabilistic oracle machine, such that (i) is a hypothesis, and (ii) if is also a hypothesis, and is a reflective oracle, then has the same distribution as .
Given this result, the main missing piece is how to test whether a given machine is a hypothesis. We need this test to give the correct result if we're running on a reflective oracle, and we also need it to halt no matter which oracle we're running on---in other words, we need it to be a query.
It turns out that this is quite straight-forward to implement, given our definition of reflective oracles as always returning "false" when passed anything other than a query. Given the source code of a machine that may or may not be a hypothesis, we first implement the following machine, ; has the property that it is a query if and only if is a hypothesis.
- first chooses a natural number, , according to any distribution that places positive probability on arbitrary large numbers.
- Then, it runs until has outputted bits.
- If halts before it has outputted bits, then loops forever. (If goes into an infinite loop before it has outputted bits, then does of course also loop forever.)
- If does in fact output bits, then outputs and halts.
Our test is now to call our oracle on the pair . Since this is only a single invocation of the oracle, it always halts. Moreover, if we're running on a reflective oracle, then there are two cases:
- If is a hypothesis, then halts with probability one; whatever number selects in the first step, eventually outputs that many bits. In this case, is a query that always outputs , implying that invoking the oracle on will return "true".
- If is not a hypothesis, there is a positive probability that it will halt or loop forever after outputting only some finite number of bits, and there is a positive probability that will choose a number larger than this. Hence, there is a positive probability that loops forever, which implies that it is not a query, and hence that invoking the oracle on will return "false".
We now have a query to test whether something is a hypothesis, and way of safely running a potential hypothesis, which will not go into infinite loops even if we're not running on a reflective oracle. Are we done?
Unfortunately not quite; there's still an annoying problem remaining, and so far I only have a slightly kludgy solution to it. The problem is that we would like our prior to, with probability one, choose a that actually is a hypothesis, and to do so it can't use the obvious method of trying random machines until finds one for which the query returns true.
Why not? Well, our query consists of a single oracle invocation---and if we're not running on a reflective oracle, all instances of that oracle invocation might return "false", in which case we would loop forever. And that would mean that our sampler would still not be a hypothesis, whose distribution we can probe with a reflective oracle.
My kludge is simple: Select only a single machine at random. If our test tells us that this isn't a hypothesis, then output an infinite stream of zeros. If our test tells us it is a hypothesis, then output a single before executing the protected version of . Then is a hypothesis, and we can use the tools detailed at the beginning of this post to figure out its distribution; and if we can find the probability of arbitrary finite prefixes of 's output, we can also compute the conditional probability, given that the first bit is a . This gives us the probability distribution we were initially looking for.
There's probably something more elegant, but I haven't yet been able to come up with an alternative that's both elegant and simple.