Ось інший підхід, заснований на итеративно знайти номери , які не можуть з'являтися серед { 1 , ... , 6 } . Назвемо безліч А більш-аппроксимацией а «S , якщо ми знаємо , що { 1 , ... , а 6 } ⊆ A . Точно так же, B є overapproximation з Ь «и , якщо ми знаємо , що { Ь 1 , ... , б 6 } ⊆ B . Очевидно, що менший A{a1,…,a6}Aa{a1,…,a6}⊆ABb{b1,…,b6}⊆BA, Тим більше корисно це по-наближення, і те ж саме відноситься і до B . Мій підхід ґрунтується на ітераційному уточненні цих надмірних наближень, тобто ітеративному зменшенні розміру цих наборів (оскільки ми виключаємо все більше і більше значень як неможливих).B
Основою цього підходу є метод доопрацювання : задавши перевищення апроксимації A для a та надмірне наближення B для b , знайдіть нове перевищення A ∗ для такого a , що A * ⊊ . Зокрема, як правило , * буде менше , ніж А , так що це дозволяє нам уточнити Надмірна наближення для через «с.AaBbA∗aA∗⊊AA∗Aa
За допомогою симетрії, по суті, той самий трюк дозволить нам уточнити наше надмірне наближення для b : з огляду на перевищення наближення A для a та надмірне наближення B для b , воно призведе до нового -приближення B ∗ для b 's.bAaBbB∗b
Отже, дозвольте мені розповісти, як зробити уточнення, тоді я зберу все, щоб отримати повний алгоритм цієї проблеми. Далі, нехай D позначає множину різниць, тобто D = { a i - b j : 1 ≤ i , j ≤ 6 } ; ми зосередимося на пошуку доопрацьовуватися наближення А * , враховуючи , B .DD={ai−bj:1≤i,j≤6}A∗A,B
How to compute a refinement. Consider a single difference d∈Dd∈D. Consider the set d+B={d+y:y∈B}d+B={d+y:y∈B}. Based on our knowledge that BB is an over-approximation of the bb's, we know that at least one element of d+Bd+B must be an element of {a1,…,a6}{a1,…,a6}. Therefore, we can treat each of the elements in d+Bd+B as a "suggestion" for a number to possibly include in AA. So, let's sweep over all differences d∈Dd∈D and, for each, identify which numbers are "suggested" by dd.
Now I'm going to observe that the number a1a1 is sure to be suggested at least 6 times during this process. Why? Because the difference a1−b1a1−b1 is in DD, and when we process it, a1a1 will be one of the numbers it suggests (since we're guaranteed that b1∈Bb1∈B, (a1−b1)+B(a1−b1)+B will surely include a1a1). Similarly, the difference a1−b2a1−b2 appears somewhere in DD, and it'll cause a1a1 to be suggested again. In this way, we see that the correct value of a1a1 will be suggested at least 6 times. The same holds for a2a2, and a3a3, and so on.
So, let A∗A∗ be the set of numbers a∗a∗ that have been suggested at least 6 times. This is sure to be an over-approximation of the aa's, by the above comments.
As an optimization, we can filter out all suggestions that are not present in AA immediately: in other words, we can treat the difference dd as suggesting all of the values (d+B)∩A(d+B)∩A. This ensures that we will have A∗⊆AA∗⊆A. We are hoping that A∗A∗ is strictly smaller than AA; no guarantees, but if all goes well, maybe it will be.
Putting this together, the algorithm to refine A,BA,B to yield A∗A∗ is as follows:
Let S=∪d∈D(d+B)∩AS=∪d∈D(d+B)∩A. This is the multi-set of suggestions.
Count how many times each value appears in SS. Let A∗A∗ be the set of values that appear at least 6 times in SS. (This can be implemented efficiently by building an array aa of 251 initially, initially all zero, and each time the number ss is suggested, you increment a[s]a[s]; at the end you sweep through aa looking for elements whose value is 6 or larger)
A similar method can be built to refine A,BA,B to get B∗B∗. You basically reverse things above and flip some signs: e.g., instead of d+Bd+B, you look at −d+A−d+A.
How to compute an initial over-approximation. To get our initial over-approximation, one idea is to assume (wlog) that b1=0b1=0. It follows that each value aiai must appear somewhere among DD, thus the list of differences DD can be used as our initial over-approximation for the aa's. Unfortunately, this doesn't give us a very useful over-approximation for the bb's.
A better approach is to additionally guess the value of one of the aa's. In other words, we assume (wlog) that b1=0b1=0, and use A=DA=D as our initial over-approximation of the aa's. Then, we guess which one of these 36 values is indeed one of the aa's, say a1a1. That then gives us an over-approximation B=a1−DB=a1−D for the bb's. We use this initial over-approximation A,BA,B, then iteratively refine it until convergence, and test whether the result is correct. We repeat up to 36 times, with 36 different guesses at a1a1 (on average 6 guesses should be enough) till we find one that works.
A full algorithm. Now we can have a full algorithm to compute a1,…,a6,b1,…,b6a1,…,a6,b1,…,b6. Basically, we derive an initial over-approximation for AA and BB, then iteratively refine.
Make a guess: For each z∈Dz∈D, guess that a1=za1=z. Do the following:
Initial over-approximation: Define A=DA=D and B=z−DB=z−D.
Iterative refinement: Repeatedly apply the following until convergence:
- Refine A,BA,B to get a new over-approximation B∗B∗ of the bb's.
- Refine A,B∗A,B∗ to get a new over-approximation A∗A∗ of the aa's.
- Let A:=A∗A:=A∗ and B:=B∗B:=B∗.
Check for success: If the resulting sets A,BA,B each have size 6, test whether they are a valid solution to the problem. If they are, stop. If not, continue with the loop over candidate values of zz.
Analysis.
Will this work? Will it eventually converge on A={a1,…,a6}A={a1,…,a6} and B={b1,…,b6}B={b1,…,b6}, or will it get stuck without completely solving the problem? The best way to find out is probably to test it. However, for your parameters, yes, I expect it will be effective.
If we use method #1, as long as |A|,|B||A|,|B| are not too large, heuristically I expect the sizes of the sets to monotonically shrink. Consider deriving A∗A∗ from A,BA,B. Each difference dd suggests |B||B| values; one of them correct, and the other |B|−1|B|−1 can be treated (heuristically) as random numbers. If xx is a number that does not appear among the aa's, what is the probability that it survives the filtering and is added to A∗A∗? Well, we expect aa to be suggested about (|B|−1)×36/251(|B|−1)×36/251 times in total (on average, with standard deviation about the square root of that). If |B|≤36|B|≤36, the probability that a wrong xx survives the filtering should be about p=0.4p=0.4 or so (using the normal approximation for the binomial, with continuity correction). (The probability is smaller if |B||B| is smaller; e.g., for |B|=30|B|=30, I expect p≈0.25p≈0.25.) I expect the size of A∗A∗ to be about p(|A|−6)+6p(|A|−6)+6, which will strictly improve the over-approximation since it is strictly smaller than |A||A|. For instance, if |A|=|B|=36|A|=|B|=36, then based upon these heuristics I expect |A∗|≈18|A∗|≈18, which is a big improvement over |A||A|.
Therefore, I predict that the running time will be very fast. I expect about 3-5 iterations of refinement to be enough for convergence, typically, and about 6 guesses at zz should probably be enough. Each refinement operation involves maybe a few thousand memory reads/writes, and we do that maybe 20-30 times. So, I expect this to be very fast, for the parameters you specified. However, the only way to find out for sure is to try it and see if it works well or not.