Estimate the number of discrepancy 2 sequences
From Polymath Wiki
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace EDP { class Program { static double[] answers = { 1, 2, 4, 6, 12, 18, 28, 44, 88, 100, 152, 240, 370, 556, 882, 750, 1500, 2250, 2784, 4284, 6438, 6062, 9526, 14856, 22944, 26164, 39528, 35122, 54800, 80940, 81326, 122422, 244844, 234934, 356154, 309068, 388042, 589796, 900000, 813466, 1212450, 1837030, 1882194, 2921946, 4544342, 2274560, 3542738, 5495686, 8436986, 9597362, 11352364, 10876536, 16040144, 23626898, 24060696, 22332908, 34665316, 32813078, 48774494, 77333978, 79086932, 118815026, 181723488, 101003862, 202007724, 171112060, 175332604, 266556200, 388397590, 379477372, 355489350, 544231036, 685850834, 1035438526, 1600139990, 967443184, 1435672238, 1335563798, 1305891128, 1985108178, 2984972718, 2245417744, 3449035210, 5401519132, 5272055840, 4470731784, 7013199284, 6544305958, 10138992314, 15284191798, 9839916650, 8579138578, 13353765596, 12170187396, 18839898968, 17144676512, 26322363104, 39457407576 }; static void Run() { double logLower = 0; double logUpper = 0; double log = 0; double epsilon = 0.000001; for (int idx = 1; idx <= answers.Length - 1; idx++) { int HAPs = 0; for (int i = 1; i <= idx; i++) { if (i != idx && idx % i == 0 && (((idx / i) - 1) % 2) == 0) HAPs++; } double badTransition = 0.5; double goodTransition = 0.5; double oddsBad = badTransition / goodTransition; // generalize again: foreach HAP f that constrains you now, go back a step // in that HAP and foreach HAP g that constrains THAT step, calculate its // bias towards or away from 0 by saying that f had wlog bias +1 just before there // and doing some independence-assumptions prob on where its +1 went // in (or not in) g // (note: same loop as above, combine) // check each f for factor of idx and whether its HAP would be on an odd step at idx for (int f = 1; f <= idx; f++) { // does HAPf constrain us? if (f != idx && idx % f == 0 && (((idx / f) - 1) % 2) == 0) { // it does, here's its last step int idxm1 = idx - f; // check each g for factor of idxm1 and whether its HAP would be on // an odd step at idxm1 for (int g = 1; g <= idxm1; g++) { // does HAPg constrain us? if (g != idxm1 && idxm1 % g == 0 && (((idxm1 / g) - 1) % 2) == 0) { // it does! set up some numbers int k = ((idx / f) - 1) / 2; int m = ((idxm1 / g) - 1) / 2; int mult = lcm(f, g); int s = ((2 * k - 1) * f) / mult; int ns = 2 * m - s; double sharedPlus = ((double)k) / (2 * k - 1); // that's wrong, fix it! double nonsharedPlus = 0.5; if (ns > 0) nonsharedPlus = ((idxm1 - 2 * k - 1) / 2.0) / (idxm1 - 2 * k); // this is wrong too, fix it! double plusses = (s * sharedPlus + ns * nonsharedPlus) / (s + ns); // this is wrong too, not sure how to fix it yet though double plus2 = bin(2*m, m + 1) * Math.Pow(plusses, m + 1) * Math.Pow(1 - plusses, 2*m - (m + 1)); double plus0 = bin(2*m, m) * Math.Pow(plusses, m) * Math.Pow(1 - plusses, 2*m - (m)); double plusn2 = bin(2*m, m - 1) * Math.Pow(plusses, m - 1) * Math.Pow(1 - plusses, 2*m - (m - 1)); // normalize double norm = plus2 + plus0 + plusn2; plus2 /= norm; plus0 /= norm; plusn2 /= norm; // apply to find the probability of a bad transition (away from 0) // (wlog f had bias 1 so we use the -2 and a 50/50 of the 0 to get a +, // which is the direction away from 0 with bias 1) double badProb = plusn2 + 0.5 * plus0; double extraEvidence = (badProb / (1 - badProb)) * (goodTransition / badTransition); oddsBad *= extraEvidence; } } } } badTransition = oddsBad / (1 + oddsBad); goodTransition = 1 - badTransition; double middleProb = goodTransition; double edgeProb = (1 - goodTransition) / 2; double p1 = Math.Pow(middleProb + edgeProb, HAPs) - Math.Pow(middleProb, HAPs); double p2 = Math.Pow(middleProb, HAPs); double multiplier = p1 + p1 + 2 * p2; double lowerEV = Math.Log(2 * Math.Floor(Math.Exp(logLower + Math.Log(multiplier)) / 2 + epsilon)); double upperEV = Math.Log(2 * Math.Ceiling(Math.Exp(logUpper + Math.Log(multiplier)) / 2 - epsilon)); double EV = log + Math.Log(multiplier); logLower = lowerEV; logUpper = upperEV; log = EV; if (idx < answers.Length) Console.WriteLine(idx + ":\t" + HAPs + "\t" + Math.Exp(lowerEV) + "\t" + Math.Exp(upperEV) + "\t" + answers[idx] / Math.Exp(upperEV)); else Console.WriteLine(idx + ":\t" + HAPs + "\t" + Math.Exp(lowerEV) + "\t" + Math.Exp(upperEV) + "\t" + Math.Exp(EV)); } Console.ReadLine(); return; } static int lcm(int A, int B) { int AB = A * B; while (A > 0) { if (A < B) { int t = A; A = B; B = t; } A = A % B; } return AB / B; } static double hyp(int N, int m, int n, int k) { return bin(m, k) * bin(N - m, n - k) / bin(N, n); } static double bin(int N, int k) { double r = 1; for (int i = 0; i < k; i++) { r *= N - i; r /= i + 1; } return r; } static void Main(string[] args) { Run(); return; } } }