List of articles

Amicable pairs: searching for them 10 times faster by Sergei Chernykh. November 6th, 2026
A collection of methods for finding type (i, 1) amicable pairs by Sergei Chernykh. May 10th, 2016
A million new amicable pairs every day: some new methods for finding amicable pair breeders by Sergei Chernykh. December 20th, 2015
Amicable pairs: searching for them efficiently by Sergei Chernykh. November 11th, 2015


Amicable pairs: searching for them 10 times faster

Sergei Chernykh
November 6th, 2026

Contents

1. Algorithmic improvements
   1.1. n is a linear function of p
   1.2. Sieving instead of trial division
   1.3. The sieve window
   1.4. How deep to sieve
   1.5. Ranges without amicable pairs
   1.6. Checking the survivors
   1.7. Near-degenerate ranges: the band sieve
   1.8. Large primes

2. GPU-specific improvements
3. CPU-specific improvements
4. Source code


Preface
This article continues "Amicable pairs: searching for them efficiently", so please read that one first.
It describes a new algorithm for the exhaustive search of amicable pairs that was developed to push the search limit up to 1022.
The main idea is simple: the larger members of potential amicable pairs are not checked one by one anymore. Instead, they're sieved, just like in the sieve of Eratosthenes, and only very few of them need further checks.

Both the CPU and the GPU versions of the program use the new algorithm. Compared to the previous versions, on typical work units of the 1022 search: The GPU version is still about 5 times faster than the CPU version on the same work units.
Both versions were checked against all 9,359,869 known amicable pairs below 1022 and found all of them.

Terminology
N, m, n, σ(m) - the same as in the previous article
p - the largest prime factor of m
m0 - m without its largest prime factor: m = m0 × p. The new algorithm is for the case when p doesn't divide m0 (99.998% of all known amicable pairs). Numbers divisible by p2 or p3 are still searched with the old algorithm.
range - all numbers m = m0 × p for a fixed m0, where p goes through all primes greater than the largest prime factor of m0 (and m ≤ N)
q - a small prime used for sieving, Q - the largest such prime
g = gcd(m0, σ(m0))

1. Algorithmic improvements

1.1. n is a linear function of p

As in the previous article, we iterate from m0 to m = m0 × p, and σ(m) is known right away. But let's look at the whole range at once:

σ(m) = σ(m0) × (p + 1)
n = σ(m) - m = σ(m0) × (p + 1) - m0 × p = (σ(m0) - m0) × p + σ(m0)

n = a × p + b, where a = σ(m0) - m0 and b = σ(m0) are the same for the whole range.

So n is a linear function of p! The target value is linear in p too: (m, n) is an amicable pair if and only if σ(n) = σ(m) = b × (p + 1).

Now take any prime power qk. If q doesn't divide a, then qk divides n if and only if

p ≡ -b × a-1 (mod qk)

This means that all p for which qk divides n form an arithmetic progression with step qk. This is exactly what a sieve needs!

If q divides a, there are two cases. If q doesn't divide b, then q never divides n. If q divides both a and b, then q divides gcd(a, b) = gcd(σ(m0) - m0, σ(m0)) = gcd(m0, σ(m0)) = g.
So n = g × (a/g × p + b/g) for every p in the range: g is a known factor of n, and the sieve works with a/g × p + b/g.

1.2. Sieving instead of trial division

The old algorithm takes every n of the range and does trial divisions (with all the tricks from the previous article) until it can prove that σ(n) ≠ σ(m).
It's fast, but it's still at least a few divisions per number, and a range can have billions of numbers.

The new algorithm processes the whole range at once. It takes an array with one element per p (I call them positions) and, for every prime q ≤ Q and every power qk, walks through the arithmetic progression of p where qk divides n, adding a value to every position it hits.
Just like in the sieve of Eratosthenes, it takes only a couple of additions per position on average and no divisions at all, and every position gets the full information about the small prime factors of its n.

What value is added? In the end, every position must have the sum

S(p) = Σ log(σ(qe)/qe)

over all primes q ≤ Q, where qe is the exact power of q dividing n.
So the progression of qk adds log(σ(qk)/qk) - log(σ(qk-1)/qk-1): when qe divides n, the values added by q, q2, ..., qe add up to log(σ(qe)/qe).
The logarithms are scaled and rounded to integers, so the sieve only adds integers.

Note that the sieve doesn't need to know which p are primes. It simply sieves all p not divisible by 2, 3 and 5 (or by 2, 3, 5 and 7), and only the few p that survive the sieve are tested for primality.
So the search doesn't even need a table of all primes up to 1011 anymore.

1.3. The sieve window

After the sieve, we know S(p) = log(σ(n1)/n1) for every position, where n = n1 × n2, n1 - factored portion of n (all prime factors ≤ Q) and n2 - unfactored portion of n (all prime factors > Q).
If (m, n) is an amicable pair, then σ(n1) × σ(n2) = σ(m), which can be written as

σ(n1)/n1 = (σ(m)/n) / (σ(n2)/n2)

All prime factors of n2 are greater than Q, so n2 can have only a few of them, and its abundancy is barely above 1: 1 ≤ σ(n2)/n2 ≤ ρ, where ρ is the largest abundancy of a number below n with all prime factors greater than Q.
For example, if Q = 32749 and n < 1022, then n2 has at most 4 prime factors and ρ < 1.00013.

Taking logarithms, we get:

log(σ(m)/n) - log(ρ) ≤ S(p) ≤ log(σ(m)/n)

This is the sieve window. It's very narrow (log(ρ) < 0.00013 in the example above), and σ(m)/n = b × (p + 1)/(a × p + b) changes very slowly with p, so the window is calculated once for a whole block of positions (using the smallest and the largest σ(m)/n of the block, plus a small margin for the rounding errors).
Only p with S(p) inside the window can give an amicable pair. I call them survivors.
Typically less than 1% of all positions survive. All other numbers are rejected with just one comparison, without ever looking at them individually!

1.4. How deep to sieve

A bigger Q makes the window narrower and gives fewer survivors, but it also makes the sieve slower: every prime q costs a modular inverse per range (to find where its progression starts) plus its hits.
So there's no single best Q. The program has several sieve depths, from Q = 1021 to Q = 32749, and chooses one for every range: short ranges are sieved with a small Q, long ranges with a bigger one.

The best depth also depends on how much abundancy n still needs. Let K be the known part of n: g, multiplied by 2 if n is always even. Then σ(n)/n ≥ σ(K)/K for every p, and the difference

W = log(σ(m)/n) - log(σ(K)/K) (for the largest p of the range)

tells how much abundancy the unknown factors of n must provide. I call it the window height.
If W is smaller than the width of the window, then every p where n has no small prime factors except those of K falls into the window, and the number of survivors explodes. A bigger Q makes the window narrower, so ranges with a small W are sieved deeper.

1.5. Ranges without amicable pairs

σ(m)/n = b × (p + 1)/(a × p + b) grows with p, and K divides n for all p of the range.
So if W < 0, i.e. σ(K)/K > σ(m)/n even for the largest p of the range, then σ(n)/n ≥ σ(K)/K > σ(m)/n for all p. This means σ(n) > σ(m), and the whole range can be skipped without sieving it!
It's the same idea as the condition (σ(g) - g) × (σ(m) - m) < g × m from the previous article ("the more abundant m is, the more deficient n must be"), but applied to a whole range at once.

This can be taken further with the check sum divisibility idea from the previous article.
Take a prime power qe that exactly divides K. If one more factor q would make the abundancy of n too big for every p of the range, then qe is the exact power of q in n for every possible amicable p. σ(qe) must divide σ(n) = σ(m) = b × (p + 1), so

σ(qe)/gcd(σ(qe), b) divides p + 1

All amicable p of the range must be in this arithmetic progression. And for p in this progression, the exact powers of some other small primes in n can be known in advance too, so K gets bigger, W gets smaller, and the same steps can be repeated.
If W becomes negative, the range has no amicable pairs. This proves many ranges empty: in some regions of the search, whole work units consist of such ranges.

The same check works inside the sieve: if a prime q divides n exactly once, then q + 1 = σ(q) must divide σ(m) = b × (p + 1), i.e. (q + 1)/gcd(q + 1, b) must divide p + 1.
The GPU version removes the positions where this fails in the ranges with the narrowest windows, which halves the number of survivors there.

1.6. Checking the survivors

A survivor still needs a full check: p must be a prime, and σ(n) must be equal to σ(m). The trial division from the previous article can do it, but the sieve already knows a lot about n, so the check can be much faster.

Small factors. S(p) is the exact sum of log(σ(qe)/qe) over the small prime factors of n. If the factors found so far explain all but δ of S(p), then every small prime factor q that is left satisfies log(1 + 1/q) ≤ δ, i.e. q ≥ 1/δ - 1/2, and the search for the next factor can jump right to that prime. When δ = 0, n1 is completely factored.

The rest of n. Now n = n1 × n2, where n1 is fully known and n2 has no prime factors ≤ Q. σ(n2) must be equal to σ(m)/σ(n1), so we also know the value

D = σ(m)/σ(n1) - n2 - 1

which must be the sum of all divisors of n2 except 1 and n2 itself (and if D < 0, the check is over right away). D tells a lot about n2.
Every prime factor q of n2 gives a divisor n2/q, so n2/q ≤ D, i.e.

all prime factors of n2 are ≥ n2/D

and trial division can start at n2/D instead of Q. For the hardest numbers D is tiny compared to n2, so trial division skips thousands of primes.

D also limits the number of prime factors of n2: So if D < 3×n22/3, then n2 can only be a prime (D = 0), q2 (D = q), q1×q2 (D = q1 + q2, the quadratic equation from section 2.3 of the previous article), q3 or q12×q2.
Each of these cases can be checked directly, without any trial division at all.

1.7. Near-degenerate ranges: the band sieve

Some ranges are much harder than the others. If W is very close to 0, the known part K of n has almost exactly the abundancy n needs.
Then almost every p for which n has no other small prime factors survives the sieve, no matter how big Q is, and these survivors are hard to check: n2 has no small factors, and D is tiny.
One example is the ranges with m0 = 2×5×7×11×23×41×2083 and its multiples: the old algorithm needed more than 15 minutes for the first such range alone.

But the previous section gives a very strong bound here: all prime factors of n2 are greater than L = n2/D.
It can also be shown that the smallest one is at most j×L + j + 2, where j ≤ log(n2)/log(L) is the number of prime factors of n2.
And in such a range D/n2 < eW - 1 for every number, so L > 1/(eW - 1) for all of them: we know in advance where to look for the smallest prime factor of n2!

So these ranges get a second sieve, the band sieve. It sieves the primes of a "band" around L (again, every prime gives an arithmetic progression of p) and marks every position with the smallest band prime that divides its n.
If a survivor's smallest prime factor must be inside the band, but no band prime divides its n, the survivor is rejected immediately. This rejects more than 90% of the survivors in these ranges without any trial division, and the others start their trial division right at the band prime.
The band sieve made such work units more than 10 times faster on both CPU and GPU.

1.8. Large primes

When p is very large, m0 = m/p is small. The search handles these numbers separately: for p > 1011 (with N = 1022), it takes a precomputed list of all numbers m0 that can be a part of an amicable pair m0 × p (about 2.4 billion numbers) and checks them against all primes p from an interval [P1, P2].

The sieve works here too: every m0 from the list is a range of p from P1 to P2.
Since all of them share the same interval of p, the primes of [P1, P2] are sieved only once, into a bitmap, and the survivors don't need a primality test at all.
Only the GPU version uses the sieve for large primes so far.

2. GPU-specific improvements

At first sight, a sieve is a bad fit for a GPU: it's all about writing to scattered places in memory, and GPUs prefer the opposite.
The first straight-forward version of the GPU sieve was 3.6 times slower than the old GPU code! Here's what made it fast: On GeForce RTX 5070, the new GPU version is 11-44 times faster than the old one on typical work units of the 1022 search, and up to 266 times faster on work units with near-degenerate ranges.

3. CPU-specific improvements

The CPU version uses the same algorithm (only for ranges with at least 512 primes: in shorter ranges the setup of the sieve costs more than it saves) and a few CPU-specific tricks: On Ryzen 9 9950X (all 32 threads), the new CPU version is 12-31 times faster than the old one on typical work units of the 1022 search, and more than 95 times faster on work units with near-degenerate ranges.

4. Source code

The source code of the CPU version
The source code of the GPU version



A collection of methods for finding type (i, 1) amicable pairs/breeders

Sergei Chernykh
May 10th, 2016

Contents

1. Exhaustive methods
   1.1. Exhaustive search
   1.2. Exhaustive search with unknown largest prime factor

2. Constructive methods
   2.1. The general formula to construct type (i, 1) amicable pairs/breeders
   2.2. Type (2, 1) amicable pairs/breeders
   2.3. Type (3, 1) amicable pairs/breeders
   2.4. Type (4, 1) amicable pairs/breeders
   2.5. Type (5+, 1) amicable pairs/breeders
   2.6. Other constructive methods

3. Conclusion

1. Exhaustive methods

1.1. Exhaustive search

- Take two sets of numbers (a and u)
- Sort one of sets by ratio: (S(a)-a)/a or (u-1)/S(u)
- Iterate through the second set and find all pairs which satisfy (S(a)-a)/a = (u-1)/S(u)

For details refer to the previous article.

1.2. Exhaustive search with unknown largest prime factor

It allows to find many more breeders in the same amount of time as the regular exhaustive search.

- Take two sets of numbers (a and u)
- Sort first set by ratio: (S(a)-a)/a
- Iterate through the second set and find all pairs which satisfy (S(a)-a)/a = (u×p-1)/(S(u)×(p+1)) for some prime p (p is the largest prime factor in u×p)

For each (u, a) pair: (S(a)-a)/a=(u×p-1)/(S(u)×(p+1))

After simplyfying:

p=(a+D)/(a×u-D) where D=(S(a)-a)×S(u) (1)

If p from (1) is integer and prime, then we've found a breeder (u×p, a). We know that p > p0 (largest factor in u) which puts restrictions on the value of x=(u×p-1)/(S(u)×(p+1))=(S(a)-a)/a

(u×p0-1)/(S(u)×(p0+1)) < x < u/S(u)
or
(u×p0-1)/(S(u)×(p0+1)) < (S(a)-a)/a < u/S(u)

which limits the set of values of 'a' to check against. The larger p0 is, the smaller this set will be, so it makes sense to explicitly check first few primes pi > p0 until this set gets small enough. A rule of thumb: if 'k' is how many values (pi > p0, i = 1, 2, ..., k) you check explicitly, then you end up with

(u×pk-1)/(S(u)×(pk+1)) < (S(a)-a)/a < u/S(u) (2)

You should then choose k such that the number of values of 'a' satisfying (2) is less than k and stop as soon as it gets less than k. This reduces asymptotic complexity to check each value of 'u' from O(N) to O(sqrt(N)).

This method proved to be effective for generating lots of small breeders (10-30 digits for u). Small breeders have the highest chances to generate other breeders/amicable pairs using te Riele's rule or any other constructive rule.

When used with parameteres u = p1×p2×p3×p4×p5 ≤ 1015, a ≤ 106, it found (among many others) the following breeder:

u=71×73×1061×3019×4211×65521001603
a=2×5×13×59

which in turn generated the first type (8, 1) amicable pair using te Riele's rule:

81 Chernykh 2016
14438796350376953678174322791271636288778421212339464839728409858893107308551670=2×5×13×59×71×73×1061×3019×4211×65521001603×4841941814273029742117557×84877110421196263915758493
14865176913743789894174101450879657763077918214583046351774081022511427255902730=2×5×13×59×1938093469849255527271721180036461246815895464743552327480323470992363397119

2. Constructive methods

2.1. The general formula to construct type (i, 1) amicable pairs/breeders

If we take any pair of numbers (u, a) then (u×p×q, a) is a breeder if:

S(a)/a=(u×pq+S(u)×(pq+p+q+1)-1)/S(u)/(pq+p+q+1)

for some prime numbers p and q. After simplifying we get this BDE:

(E×p-D)(E×q-D)=a×(E+D×u) (3)

where D=(S(a)-a)×S(u), E=u×a-D

If (u, a) is already a breeder then (3) becomes this after further simplifying:

(p-(u-1))(q-(u-1))=u×(u-1)+1 (4)

This is te Riele's rule to generate new breeders from existing breeders. Other rules for generating new breeders from existing breeders were given in the previous article.

2.2. Type (2, 1) amicable pairs/breeders

These have the form (p×q, a), so u = 1 in this case. Substituting (1, a) into (3) and simplifying:

(D×p-E)(D×q-E)=a2 (5)

where D = a×2 - S(a), E = S(a)-a

This BDE is very convenient: it doesn't require factorization of the right side so we can just iterate all posible factorizations of 'a' in given range. I solved this BDE for all a ≤ 1.2 × 1013 and for many a ≤ 1018 with small prime factors. The most suitable choice of 'a' for BDE (5) is such that D(a)=1 or D(a)/g(a)=1 where g(a)=GCD(a, S(a)). It turns (5) into:

(p - E/g)(q - E/g) = a2/g2 (6)

Let's find as many such values of 'a' as possible.

It's easy to see that D=1 for a=2n. Only a few amicable pairs of the form (2n×p×q, 2n×r) are known however because 2n grows very quickly and demolishes all chances for p, q, r to be prime at the same time. But it's possible to find many more relatively small values of 'a' such that D(a)/g(a)=1.

For example, for a=2n×p:

D=2n+1×p - (2n+1-1)×(p+1) = 2n+1×p - 2n+1×p - 2n+1 + p + 1 = p+1 - 2n+1

if D=2 then p = 2n+1 + 1, S(p)=2n+1 + 2, g(a) = GCD(a, S(a)) = 2, D/g=1
if D=4 then p = 2n+1 + 3, S(p)=2n+1 + 4, g(a) = GCD(a, S(a)) = 4, D/g=1
...
if D=2n+1 then p=2n+2-1, S(p)=2n+2, g(a) = GCD(2n+1×p, (2n+2-1)×2n+2) = 2n+1, D/g=1

so we can take

a = 2n × (2n+1 + 2k - 1) (7)

where k = 1, 2, ..., n+1 and the number in brackets is prime.

Then comes the case where we can take any 'a' with D(a)/g(a) = A ≥ 1 and find p and q such that D(a×p×q)/g(a×p×q) = k:

The first case is when p doesn't divide g(a×p):

a×2×pq - S(a)×(pq+p+q+1) = k×g×d, d divides a/g

simplifying it, we get:

(A×p-b)(A×q-b) = b×(b+A) + A×k×d (8)
where A = (a×2-S(a))/g
b = S(a)/g
d divides a/g
k=A generates new values with the same D(a)/g(a)
k=1 generates new values with D(a)/g(a)=1
"A×k×d" generates new values with D(a)/g(a)=k, 1 ≤ k ≤ A

for a=2n we have n+1 equations (0 ≤ k ≤ n):

(p-(2n+1-1))(q-(2n+1-1))=(2n+1-1)×2n+1+2k (8.1)

The second case is when p divides g(a×p). Let's consider this case only for D(a)/g(a) = A = 1:

(a×2-S(a))×pq-S(a)×(p+q+1)=g×d×p

simplifying it, we get:

(p-b)(q-b-d))=b×(b+d+1) (9)
where b = S(a)/g
d divides a/g

for a=2n we have n+1 equations (0 ≤ k ≤ n):

(p-(2n+1-1))(q-((2n+1-1)+2k))=(2n+1-1)×(2n+1+2k) (9.1)

Applying (8) and (9) to a=2n, a=2n×p found before produced a lot of new values a=2n×p1×p2×...×pk. (8) and (9) were applied to these new values again and again as long as it was manageable to factorize right sides of these equations. I also ran a big exhaustive search for 'a' such that D(a)/g(a) ≤ 104, a ≤ 1018 and substituted found values into (8) and (9) with k = 1. As a result, I found almost 170,000 values of 'a' with D(a)/g(a) = 1 and solved (6) for all of them. It produced hundreds of new type (2, 1) amicable pairs. The record for the largest type (2, 1) amicable pair was also increased from 329 digits (Garcia, 1998) to 545 digits: 29 new pairs were larger than the previous record.

2.3. Type (3, 1) amicable pairs/breeders

These have the form (p×q×r, a), so u = p in this case. Substituting it into (3) we get

D = (S(a)-a)×(p+1)
E = p×a-D = p×a-(S(a)-a)×(p+1) = p×a-S(a)×(p+1)+a×(p+1) = p×a-S(a)×p-S(a)+a×p+a = p×(a×2-S(a))-(S(a)-a)

E must be > 0 which sets a lower bound for p:

p > (S(a)-a)/(a×2-S(a)) (10)

A rule of thumb: for each 'a' try just the first few primes larger than the right side of (10) to get the highest chances to find a solution of (3)

There is also a higher bound for p:

p < 3×(S(a)-a)/(a×2-S(a)) (11)

Exhaustive search is still manageable, and I was able to find most (3, 1) amicable pairs with a < 1012. Values of 'a' with D(a)/g(a) = 1 are also suitable here and generated hundreds of new amicable pairs as well.

2.4. Type (4, 1) amicable pairs/breeders

u = p×q×r×s, so an exhaustive search is not feasible here. But trying first few possible values for p and q and solving (3) for r and s is very fruitful. (10) still holds for p, and we have this lower bound for q:

q > (S(a)-a)×(p+1)/(a×p - (S(a)-a)×(p+1)) (12)

I tried p = smallest prime satisfying (10) and q = first few primes (up to a hundred) satisfying (12) for given p, and vice versa: p = first few primes (up to a hundred) satisfying (10) and q = smallest prime satisfying (12) for given p. In each case, I considered equation (3) for r and s, and if E was relatively small after dividing out common factors (≤ 104 in general or ≤ 106 in the case of smallest possible p and q), it was solved.

This approach resulted in finding over 1,000 new type (4, 1) amicable pairs and over 25,000 breeders of the form (p×q×r×s, a). More than 109 equations (3) were solved in the process.

2.5. Type (5+, 1) amicable pairs/breeders

It's possible to use the same approach as in 2.4. for type (5, 1), but it doesn't produce as many new pairs. The smallest (5+, 1) amicable pairs were found by some form of an exhaustive search (1.1 or 1.2), the other pairs were found by te Riele's rule or other constructive methods.

2.6. Other constructive methods

A rule to generate breeders of the form (u×q, a×p) from (u, a) was described in the previous article. A Thabit rule for amicable pairs/breeders was also described there.

There is also a small modification of te Riele's rule that can generate some more pairs/breeders: if (u, a) is a breeder, then (3) becomes (4), i.e. E becomes equal to 1. But if (u, a) is "almost" a breeder, then E becomes very small and (3) is still likely to have a solution. By "almost" a breeder I mean pairs (u, a) which satisfy

S(a)/a = (u+S(u)-1)/S(u) + ε (13)

for some very small ε. Breeder (u, a) produces "almost" breeders of these types:

(u, a×p) where p > S(u)×S(a)/a and is prime (14)
(u×p, a) where p > u and is prime (15)

For example, take one of Euler's amicable pairs:

21 Euler 1750
11498355=34×5×11×29×89
12024045=34×5×11×2699

u=2581=29×89
a=4455=34×5×11

(14) gives lower bound for p: p > 2700×8712/4455 = 5280. If we take p = 5281 for (14) then solve (3), we'll generate a breeder (29×89×13674611×4202577551, 34×5×11×5281) which is also a type (4, 1) amicable pair found by te Riele (of course) in 1982:

41 TeRiele 1982
3489655839073826955942266055=34×5×11×5281×29×89×13674611×4202577551
3650550738768150894849977145=34×5×11×5281×155165267043476524799

Another example:

u=397×479×141403=26889618689
a=32×52×13×29=84825

(15) gives lower bound for p: p > u = 26889618689. If we take p = 26889618697 for (15) then solve (3), we'll generate a breeder (397×479×141403×26889618697×80339065939437225367×735307463850521298183292182550219351727, 32×52×13×29) which is also a type (6, 1) amicable pair:

61 Chernykh 2016
3623171640394727379955351072502990492618130497038578416351325756458993451782755208025=32×52×13×29×397×479×141403×26889618697×80339065939437225367×735307463850521298183292182550219351727
3639906844276458222356992416948731788196043339981019887096597468959958779504615339175=32×52×13×29×42910779183925236927285498578823834815161135749849924987876185899911096722718719

3. Conclusion

The methods described in this article were successfully used to generate thousands new amicable pairs of type (i, 1) and over 70,000 new breeders.
Borho's rule was applied to most of these new amicable pairs/breeders which resulted in bringing the total number of known amicable pairs to 1,000,000,000.

The most productive breeder was this one:

u=163×1042759×773144273090265929×3071110954662140597
a=3×53×72×101×109×193×269×563

It generated 17,010,927 new amicable pairs of type (5, 2).



A million new amicable pairs every day: some new methods for finding amicable pair breeders

Sergei Chernykh
December 20th, 2015

Contents

1. An almost exhaustive search for breeders
2. Generating new breeders from known breeders
3. Thabit rule for generating new huge breeders from known breeders

Preface
For a definition of what breeder is and how it can be used to generate amicable pairs, refer to
"Amicable pairs, a survey" by M. Garcia, J.M. Pedersen, H.J.J. te Riele - section 5, "Searches of amicable pairs of a special form", definition 5.4.

1. An almost exhaustive search for breeders

If (au, a) is a breeder for Borho's rule then by definition there is a natural number x such that:

au + ax = S(au) (1)
and
S(au) = S(a)(x + 1) (2)

Let's assume that gcd(a, u) = 1. It cuts some breeders, but simplifies a lot of things:

(2) becomes S(a)×S(u) = S(a)×(x+1), so x = S(u) - 1
(1) then becomes a×u + a×(S(u) - 1) = S(a)×S(u)

divide both sides by a: S(a)/a×S(u) = u+S(u)-1
divide both sides by S(u) and we get

S(a)/a = (u+S(u)-1)/S(u) (3)

Searching for breeders is now just finding all pairs of numbers (a, u) for which (3) holds.
I used the following algorithm to find (almost) all such pairs in the specified range.
  1. Generate as many values of (S(a)-a)/a as can fit in the available physical memory.
    Use "increasing largest prime factor order" and consider only values of "a" for which 0.5 < (S(a)-a)/a < 1 holds.
    We know that they're all between 0.5 and 1, so their binary representation will be "0.1..."
    We can store 64 bits which come after "0.1" for each (S(a)-a)/a value, and round the last bit to nearest,
    so maximal absolute error will not exceed 2-66. Such high precision gives very few false positives when searching,
    and they all can be filtered by checking the exact values in (3), rewritten as S(a)×S(u) = (u+S(u)-1)×a to avoid rounding errors because of division.

  2. Iterate over all values of u, starting from 1. Use modified Sieve of Eratosthenes to get all values of S(u) in range and avoid doing factorizations for each u in range.
    Typical range size would be around 106...107 for optimal performance. For each (u, S(u)) pair calculate (u-1)/S(u) and if it's between 0.5 and 1,
    search for this value in the set of (S(a)-a)/a values generated in step 1. I stored (S(a)-a)/a values in ascending order which allowed binary search,
    plus I used some tweaks like cache-friendly binary search. Hash map would be faster, but it wastes memory: we need to store as many values as possible in all available memory, every byte counts here.
    For each "u" value which gave a match, save (u, S(u)) pair to a file on disc.

  3. Generate the same (a, S(a)) values as in step 1 again and match them against the set of (u, S(u)) pairs found in step 2.
    This time, use the exact formula S(a)×S(u) = (u+S(u)-1)×a for matching.
I ran the algorithm described above with the following parameters: As a result of this search and a number of smaller searches, I found 3884 breeders, most of them were new.

Source code for the described algorithm: BreederSearch_2015.zip

2. Generating new breeders from known breeders

The rule for generating new breeders described below is new. It wasn't published anywhere before.

Given a pair (a, u) which corresponds to a breeder (au, a), find prime numbers p, q such that (a×p, u×q) give a new breeder (ap×uq, ap).

Substitute (a×p, u×q) into (3):

S(a)×(p+1)/(a×p) = (u×q+S(u)×(q+1)-1)/S(u)/(q+1)

After some boring calculations and getting rid of "a" by substituting (S(a)-a)/a = (u - 1)/S(u) and S(a)/a×S(u)=(u+S(u)-1) we get this Bilinear Diophantine Equation (BDE):

(p-(u+S(u)-1))×(q-u) = (u+S(u)-1)×(u+1) (4)

Example:
a=8, u=253, S(u)=288
(4) becomes (p-540)×(q-253) = 137160
which has a solution p=541, q=137413
We've successfully generated (8×541, 253×137413) from (8, 253).

Applying this rule to the list of 3884 breeders found before, I got 480 breeders in the second generation and 27 breeders in the third generation.
It directly follows from the left side of (4) that q > u which means u×q > u2, so each child breeder is at least twice as long as its parent breeder.
Indeed, first generation breeders were up to 13 digits long, second generation - up to 38 digits, third generation - up to 75 digits.
I also applied this rule to many of the previously known breeders extracted from known amicable pairs.
My list grew to 18035 breeders as a result, 563 of them are 50 digits or bigger.

Second and third generation breeders produced an awful lot of new amicable pairs - more than 36 millions in just 3 weeks!

Source code is not provided since it's just a straight-forward BDE solver for equation (4).

3. Thabit rule for generating new huge breeders from known breeders

Borho and Hoffman in "Breeding Amicable Numbers in Abundance" [1986] give a Thabit rule for generating amicable pairs from breeders of the form (au, a):

If t = u + S(u) is a prime number then for n = 1,2,3,...
A=au×tn×[tn(u+1)-1]
B=a×tn×[tn(u+1)(t-u)-1]
are an amicable pair if both numbers in square brackets are prime.

It's easy to see that (A, B) is an amicable pair of type (i, 1) which means that the same rule can be modified to find new breeders:

If t = u + S(u) is a prime number then for n = 1,2,3,...
A=a×tn
U=u×[tn(u+1)-1]
are a breeder if the number in square brackets is prime.

This rule generates very huge breeders due to quickly growing tn.
Applying it to breeders in my list produced 1378 new 50+ digit breeders, the largest having 4852 decimal digits for "u".
This breeder can potentially produce 15000+ digit amicable pairs. I tried some smaller breeders and found 4 new 1000+ digit amicable pairs.



Amicable pairs: searching for them efficiently

Sergei Chernykh
November 11th, 2015

Contents

0. Straight-forward algorithm
1. Avoiding factorization of m
2. Trimming down factorization of n
2.1. Check sum bounds
2.2. Check sum divisibility
2.3. The finish line of trial division
3. Reducing search space
4. Conclusion and source code


Preface
This article summarizes all techniques for an exhaustive search of amicable pairs currently known to me.
The C++ source code implementing these techniques is provided.
This source code implements the leading-edge algorithm for running an exhaustive search of amicable pairs.
It was successfully used to push the exhaustive search limit from 1014 up to 1017 (finding 282,197 new amicable pairs)
and then to find over 1 million new amicable pairs above 1017.

Terminology
N - the limit for the search. The algorithm must find all amicable pairs with smaller member m ≤ N
m - smaller number in a pair
n - larger number in a pair, or an arbitrary natural number when used in enumerations (i.e. p1, ..., pn)
σ(m) - sum of all divisors of m, including 1 and m.

0. Straight-forward algorithm

The following basic algorithm can be derived from the very definition of amicable pairs: This is very inefficient because it requires 1 and in many cases 2 full factorizations per iteration.

1. Avoiding factorization of m

Straight-forward algorithm iterates from m to m + 1 on each step.

One way to eliminate factorization of m is to store factor table of sufficient size.
It was first used by David and Paul Moews: A SEARCH FOR ALIQUOT CYCLES BELOW 1010 (1991)
For example, if m=p1k1×...×pnkn then we know that p1 divides m+p1, p2 divides m+p2 and so on.
We only need to store factors for all numbers between m and m + sqrt(N) at each step.
If we store this data from the beginning of search, we'll effectively eliminate factorization of m at each step.

This approach has several downsides: A better way to eliminate factorization of m is to change iteration order!
Instead of iterating from m to m + 1, we'll iterate from m to m × p where p is a prime.
Thus we'll know the factorization for each m right away. We don't even need to store the actual factorization, what we need to store is σ(m).
This idea was first used by David Einstein in the beginning of 2000's.

One more benefit from this iteration order is that amicable numbers (more precisely, smaller members of amicable pairs) tend to have only small prime factors in their factorization.
This iteration order finds more than a half of all amicable pairs below N in only a small fraction of the total search time.

A simple recursive algorithm implements this iteration order: There are two cases here: Both cases require only two multiplications, one addition, no divisions at all and only a fixed and small amount of memory to iterate from m to m1.
As a result, we get m and σ(m) already calculated. Perfect!

2. Trimming down factorization of n

One can notice that factorization of n is not what's needed. What's actually needed is to check that σ(n) = σ(m).
Knowing that, we can try to find ways to prove that σ(n) ≠ σ(m) way before completing factorization.

2.1. Check sum bounds

First and obvious thing is to check that min(σ(n)) ≤ σ(m) ≤ max(σ(n)) after each trial division step.
Indeed, we know that n = n1 × n2, where n1 - factored portion of n and n2 - unfactored portion of n.
Hence σ(n) = σ(n1) × σ(n2). We know σ(n1) and we know that n2=p1k1×...×pnkn where p0 ≤ p1 < p2 < ... < pn, p0 - smallest prime factor we haven't tried yet.

Lower bound for σ(n): σ(n) = σ(n1) × σ(n2) ≥ σ(n1) × (n2 + 1) (σ(n2) = n2 + 1 when n2 is prime)
Upper bound for σ(n): σ(n) = σ(n1) × σ(n2) ≤ σ(n1) × max(σ(n2)) where max(σ(n2)) is a maximal sum of divisors for all numbers satisfying these conditions: We can pre-calculate a look-up table which gives max(σ(n2)) for each pair (p0, t), where both p0 and t are taken from fixed sets of numbers.
Herman te Riele in "Computation of All the Amicable Pairs Below 1010" (1986) gives more details about this table.
He uses analytical estimation of max(σ(n2)) though, but it's possible (and it's actually implemented in the code) to calculate the exact values of max(σ(n2)) for each given (p0, t).

This table is of course has an upper limit for p0, because we don't have infinite amounts of memory.
My implementation calculates it for all p0 < 216, t is a primorial number < 264, so it can be used for all numbers < 264 and containing 4 or more prime factors.

What about cases where n2 has 3 or 2 prime factors? The table can't be used here, but it's possible to get formulas for max(σ(n2)) for such simple cases.

I derived these formulas:

max(σ(n2)) ≤ n2 + p0 + n2/p0 + 1 when n2 has at most 2 factors, both ≥ p0
max(σ(n2)) ≤ n2 + (n2/p0 + p02 + p0) × 2 when n2 has at most 3 factors, all of them ≥ p0

2.2. Check sum divisibility

The next observation is that if σ(n) = σ(n1) × σ(n2) and σ(n) = σ(m) then σ(n2) = σ(m) / σ(n1).
n2 is an integer, σ(n2) is of course also an integer which means that σ(m) / σ(n1) must be an integer.
If σ(n1) doesn't divide σ(m) then we can immediately conclude that σ(n) ≠ σ(m) and stop factorization.
This technique prunes numbers very effectively. It discards most candidates after finding just a few smallest prime factors.

2.3. The finish line of trial division

If in spite of all previous filters we got to a case where σ(n) = σ(n1) × σ(n2) where n2 can have at most two factors, then we can just calculate these factors instead of doing trial divisions!
Indeed, n2 can be either a prime, or a perfect square, or a product of two distinct prime numbers.

First two cases are simple to check, the last case gives two equations (implying that we want to check if "σ(n) = σ(m)" is true)

p×q = n2
(p+1)×(q+1)=σ(m)/σ(n1)

Simplifying it, we'll get this:

p×q = n2
p+q = σ(m)/σ(n1)-n2-1

which is a Vieta's formula for this quadratic equation:

x2 - (σ(m)/σ(n1)-n2-1)×x + n2 = 0

Find roots, check that they're distinct positive integers satisfying equations for p and q, and you're done!

3. Reducing search space

The algorithm can be even faster if it doesn't need to iterate over all numbers between 1 and N, right? Some numbers can never be a member an amicable pair.

For example, all numbers divisible by 6 can't be a part of an even-even amicable pair.
They can still be a part of an even-odd amicable pair, but such pairs must have a very special form which can be easily and quickly searched for separately.

Another consideration: m must be abundant, i.e. σ(m) > m × 2

The greatest common divisor of m and n must be deficient because n must be deficient: σ(g) < g×2 where g = gcd(m,σ(m))
In fact, we can use even stronger restrictions: if (m,n) is an amicable pair, m < n, then σ(m)=σ(n)=m+n

Dividing it by m and n respectively, we get:
σ(m)/m-1 = n/m = x
σ(n)/n-1 = m/n = 1/x

1/x = σ(n)/n-1 > σ(g)/g-1 because n = g × n1, n1 > 1
σ(g)/g - 1 < 1/x

Let's try to transform it to the form F1(g, m) < F2(g, m) so we can use it for filtering values of m:

σ(g)/g - 1 < 1/x
σ(g)/g - 1 < 1/(σ(m)/m-1)
σ(g) - g < g/(σ(m)/m-1)
σ(g) - g < (g × m)/(σ(m)-m)
(σ(g) - g)×(σ(m) - m) < g × m

(σ(g) - g) × (σ(m) - m) < g × m

This formula has another equivalent form (pointed to me by David Einstein): m/σ(m) + g/σ(g) > 1
But it involves floating-point divisions and thus can be unreliable when dealing with huge numbers.

The general meaning of both formulas is "the more abundant m is, the more deficient n (and g) must be".

So, the final set of requirements for m is: Very few numbers satisfy all three requirements combined, so it significantly speeds up the search.

4. Conclusion and source code

My implementation of the algorithm described above finds all amicable pairs < 1013 in just ~24 minutes on Core i7-4770K (8 parallel threads).
The asymptotic complexity of the algorithm seems to be O(N×log(log(N))).
I have no strict proof of it, but run times for N=1010...1017 align almost perfectly with C×N×log(log(N)).

Download the source code: Amicable.zip
The latest source code is also available on GitHub: https://github.com/SChernykh/Amicable