For me the most fasinating thing about the Collatz Conjecture is how it so blantantly points to a deficiency in mathematics. It seems incredibly obvious that it is true. The problem lies in a way to say that no loops are created excluding one - a limited understanding of process dynamics.

Recently, I've changed the problem to eliminate the split condition - there is no reason to divide even numbers by two. Without the split we have a simplified algorithm, but it must work with larger numbers. This doesn't seem like an intuitive step.

1. y <= 1+Shr[Xor[x,x-1],1]

2. if x=y then step 5

3. x <= 3x + y

4. goto step 1

5. number is a power of two

The first step calculates the value of least set bit. Instead of dividing by two, one is scaled up to match the bit which would make (x) odd if it were down scaled. Only when a single bit is set does the algorithm end (step 2). (y) can be tracked progressively instead of looking at the complete representation of (x) as step 3 always clears the least set bit (or more). Of course, I've coded this in x86:

; check Collatz Conjecture on multi-percision numberTry a really big number - like 2^131072 + 3

;

; carry flag set on array overflow

; carry flag clear on pass

; (otherwise it loops forever: not likely, but hasn't been proven)

;

; NOTE: array should be twice the size of number to test - too large

; is not a problem as only active bits are operated on.

CollatzArrayQ:

label .arr at esp+4+32 ; BigInt

label .len at esp+8+32 ; length (dwords)

pushad

mov ebx,[.arr]

mov eax,[.len]

mov edx,1

mov esi,ebx

lea ebp,[ebx+eax*4]

; address past number in EDI (active end marker)

; (need at least one zero dword on end!)

.z: dec eax

test dword [ebx+eax*4],-1

je .z

lea edi,[ebx+eax*4+4]

cmp edi,ebp

je .over

; advance to lowest set bit

.0: test [esi],edx

jne .1

.0a: rol edx,1

jnc .0 ; HINT: taken

add esi,4

cmp esi,ebp ; end

cmovnc esi,ebx ; reset

jmp .0

; ESI[ECX] is first set bit, multiply by three and add ESI[ECX]

; all (virtual) lower bits are zero.

.1:

; test if buffer is == ESI[ECX] then done!

cmp [esi],edx

jne .kx ; HINT: taken

; if EDI==ESI+4 or (ESI+4==EBP && EDI==EBX)

; (faster than testing all of buffer)

mov ecx,edi

lea eax,[esi+4]

cmp edi,ebx

cmove ecx,ebp

cmp eax,ecx

je .x

.kx:

push edx

push esi

.2:

mov eax,3

mov ecx,edx

mul dword [esi]

add eax,ecx

adc edx,0

mov [esi],eax

add esi,4

cmp esi,ebp ; end

cmovnc esi,ebx ; reset

cmp esi,edi

jne .2

test edx,edx

je .5

cmp edi,[esp]

je .over

mov [edi],edx

add edi,4

cmp edi,ebp ; end

cmovnc edi,ebx ; reset

.5: pop esi

pop edx

jmp .0a ; we just cleared that bit

.x: popad

clc

retn 8

.over: popad

stc

retn 8

TestBuffer rb 32*1024 ; zero bytesWhy is this important? The algorithm is no longer concerned with value of (x) except for the exit condition - the same operation takes place each loop. It is sufficient to show that (y) -> (x) for all (x), and the conjecture is true. The multiplication by three is irrelavant because the addition propells the least set bit at a rate greater than the constant multiple!

mov dword [TestBuffer],3

mov dword [TestBuffer+16*1024],1

push 32*1024/4 ; L1 cache size (c:

push TestBuffer1

call CollatzArrayQ

; 3829ms on my machine

(c:

**Update:**

Status of the 3x+1 class record progress as of: Dec 13, 2007. Intervals areBasically, a trillion per day, per Ghz.

indicated in blocks of 20,000,000,000,000 (20 E+12 or 20 trillion numbers).

Calculation of a single block takes approximately 20 days of (idle) time on a

Pentium 1000 MHz.

Naturally, I'm currious how my routine compares:

Currently, they are working on 7 * 2^53 block of numbers. I ran a test of my algorithm for 2^24 numbers (in that block range) which took 38781ms. Which means it is roughly 25 times

**slower**. Their algorithm is tuned for this size and uses large data structures (to avoid processing numbers). I might be able to double the speed of my algorithm, but confirming ranges of numbers is not what it's designed for.

## 2 comments:

Every number (A) can be represented as: A = k * 2^m + 2^n, m > n >= 0 and k odd or zero.

A <- 3A + 2^n, as per the algorithm

We have to look at three cases:

1) m-n = 1

2) m-n = 2

3) m-n > 2

...and show a reduction in (k).

3) case three progresses to:

3^(m-n) * k * 2^m + 2^m

where (k) begins to get reduced - the other two cases are more direct.

Post a Comment