Ken Keeler, who wrote the episode and has a PhD in Mathematics, created a theorem and proof with respect to the following problem:
Suppose there are k bodies and distinct mind switches are performed on these bodies. The condition of the switch is such that, if two bodies have performed mind-switching before, they cannot repeat this process with each other. How can we then restore the bodies with their original minds without violating the condition stated?
The proof of this theorem is written in the following screenshot, which we will further elaborate:

In the process of explaining the solution, we will translate it into a Python program. Firstly, we let the array A contain k Body objects, where the index of each Body object will correspond to its mind_id attribute.
The transcribed first part of the proof is as follows:
First let π be some k-cycle on [n] = {1 ... n} WLOG write:
π = 1 2 ... k k+1 ... n
2 3 ... 1 k+1 ... n
Let <a,b> represent the transposition that switches the contents of a and b.
By hypothesis π is generated by DISTINCT switches on [n].We have k bodies that are messed up. From the above diagram, the first row represents the body id, while the second row represents the mind id. We then arrange them such that each body will be to the right of the body that possesses its mind, i.e. body 2 will be on the right of body 1 as body 1 contains the mind of body 2, so on and so forth. There is an exception for bodies 1 and k, where the right of body k is body 1, so that the k bodies are arranged in a circle.
We define the Body class as follows:
class Body(object): def __init__(self, mind): self.mind = mind self.has_switched_with = [] def can_switch_with(self, other_body): if other_body in self.has_switched_with: return False else: return True def switching(self, other_mind, other_body): self.mind = other_mind self.has_switched_with.append(other_body)
The attribute
self.has_switched_withstores the body ids of other bodies it has performed a switch with, so that it may perform a check in the method can_switch_withto ensure that it has not already switched with the body it is currently trying to switch minds with. This should be an invariant throughout the entire proof, i.e.
self.has_switched_withshould always return True.The following code will obtain a user input for the number of bodies which will be passed as an argument into the program.
bodies = [] size = int(sys.argv[1]) # Assume distinct switches are already performed on bodies for i in range(size): body = Body((i+1)%size) body.has_switched_with.extend(range(size)) bodies.append(body) print str(i) + '\t', print '\n', for body in bodies: print str(body.mind) + '\t', print '\n'
First, we initialise the array of bodies such that each body has a mind id equal to the next body's body id, except for the last body which will have the mind id equivalent to the 1st body id. This corresponds to the arrangement of the k bodies in a circle. The line
body.has_switched_with.extend(range(size))assumes that each body has switched with every other body. (The body will include itself in the array according to the code, but it isn't necessary to remove it as it will never perform switching with itself.)
Transcribing the next part we have:
Introduce two "new bodies" {x,y} and write
π* = 1 2 ... k k+1 ... n x y
2 3 ... 1 k+1 ... n x y
Now we introduce two bodies that haven't been mind-swapped and initialise them with mind_ids corresponding to their body_ids:
# Introduce 2 bodies that haven't been mind-swapped body_x = Body(size) body_x_index = size body_y = Body(size+1) body_y_index = size+1 bodies.append(body_x) bodies.append(body_y) for i in range(len(bodies)): print str(i) + '\t', print '\n', for body in bodies: print str(body.mind) + '\t', print '\n'
And the last part:
For any i=1 ... k let σ be the (l-to-r) series of switches
σ = (<x,1> <x,2> ... <x,i>) (<y,i+1> <y,i+2> ... <y,k>) (<x,i+1>) (<y,1>)
Note each switch exchanges an element of [n] with one of {x,y}
so they are all distinct from the switches within [n] that generated π
and also from <x,y>. By routine verification
π* σ = 1 2 ... n x y
1 2 ... n y x
i.e. σ reverts the k-cycle and leaves x and y switched
(without performing <x,y>).
NOW let π be an ARBITRARY permutation on [n]. It consists of disjoint
(nontrivial) cycles and each can be inverted as above in sequence after
which x and y can be switched if necessary via , as was desired. Next, we pick a random body with index i
# Pick any k from 0 to size-1 k = random.randrange(size) print 'k = ' + str(k)
and do the following:
First, from the first body to the ith body, we perform switches with body X.
# Swap minds of start to index k with body_x for i in xrange(k+1): if not switch(body_x_index, i): print 'Error!' break
Next, from the i+1th body to the last body, we perform switches with body Y.
# Swap the rest of the minds with body_y for j in xrange(k+1, size): if not switch(body_y_index, j): print 'Error!' break
Now each body possesses its own mind except for index 0 and k+1 (and of course bodies X and Y). Body 0 has its mind in body Y and body k+1 has its mind in body X. Hence we do the following:
# Swap body_x's mind with the k+1th body if k+1 < size: if not switch(body_x_index, k+1): print 'Error!' # Swap body_y's mind with the 0th body if not switch(body_y_index, 0): print 'Error!'Voila! Now all the bodies, except for X and Y, possess their original minds. And it perfectly fine that X and Y are swapped, because they can simply perform a pairwise switch between themselves and get back their own bodies.
No comments:
Post a Comment