private static void WriteBox( TextWriter writer, AliquotChainLink link) { var node = link.Current; var factors = link.Factorisation; var driver = link.Factorisation.Driver(); string color = CalcColor(node, factors); if(driver.Length > 0) { writer.WriteLine("{0} [shape=record,label=\"<f0>{0}|<f1>{1}|<f2>{2}\",color={3}];", node, factors, driver, color); } else { writer.WriteLine("{0} [shape=record,label=\"<f0>{0}|<f1>{1}\",color={2}];", node, factors, color); } }
public static AliquotDatabase Create( IPrimes p, int dbLimit, Progress<ProgressEventArgs> progressIndicator = null, CancellationToken? maybeCancellationToken = null) { var creationProperties = new Dictionary<string, string>(); creationProperties["Create.ChainStartLimit"] = dbLimit.ToString(); BigInteger upperLimit = BigInteger.Parse("1000000000000000"); // 10^15 Utilities.LogLine("AliquotDatabase: Create to {0}, Successor Limit {1} ({2} digits)", dbLimit, upperLimit, upperLimit.ToString().Length); creationProperties["Create.UpperLimit"] = upperLimit.ToString(); var links = new Dictionary<BigInteger, AliquotChainLink>(); DateTime dtStart = DateTime.UtcNow; int progress = 0; // Set up a parallel run across the collection var range = Enumerable.Range(1, dbLimit); var parOpts = new ParallelOptions(); parOpts.CancellationToken = maybeCancellationToken.Value; // We *could* set this, but really .NET should be able to figure it out! // parOpts.MaxDegreeOfParallelism = System.Environment.ProcessorCount; Parallel.ForEach(range, (i) => { // Build the chain onwards from this number BigInteger n = i; while (n > 1 && n < upperLimit) { // Get the new link var s = new AliquotChainLink(p, n); // Abandon if we would go above the limit if (s.Successor > upperLimit) { break; } // Synchronize on the links collection since this is in parallel lock(links) { // We exit if we are joining an existing chain if (links.ContainsKey(n)) { break; } // It's a new link - add it to the database links[n] = s; } // Go to next element in chain n = s.Successor; } // Indicate progress int newProgress = (int)(100.0 * i / dbLimit); if (newProgress > progress) { if(maybeCancellationToken.HasValue) { maybeCancellationToken.Value.ThrowIfCancellationRequested(); } double s = (DateTime.UtcNow - dtStart).TotalSeconds; double expected = s * (dbLimit - i) / i; ProgressEventArgs.RaiseEvent(progressIndicator, newProgress, "ADB: i {0} Time Used (min) {1:N} Estimated time Left (min) {2:N}".FormatWith(i, s / 60.0, expected / 60.0)); progress = newProgress; } } ); creationProperties["Create.FinishTimeUtc"] = DateTime.UtcNow.ToString(); creationProperties["Create.Seconds"] = (DateTime.UtcNow - dtStart).TotalSeconds.ToString("N2"); return new AliquotDatabase(links, creationProperties); }
public void Reader(BinaryReader reader) { Links = new Dictionary<BigInteger, AliquotChainLink>(); CreationProperties = new Dictionary<string, string>(CreationProperties); // format string adbFormat = reader.ReadString(); Utilities.LogLine("ADB format: {0}", adbFormat); if (adbFormat != "adb.1") { throw new InvalidDataException(string.Format("Unexpected ADB Format [{0}]", adbFormat)); } // # properties UInt64 numProperties = reader.ReadUInt64(); for(UInt64 ip = 0; ip != numProperties; ++ip) { string propertyKey = reader.ReadString(); string propertyValue = reader.ReadString(); CreationProperties[propertyKey] = propertyValue; Utilities.LogLine("ADB property [{0}]=[{1}]", propertyKey, propertyValue); } if (!CreationProperties.ContainsKey("Count")) { throw new InvalidDataException("ADB file did not have 'Count' property"); } UInt64 n = UInt64.Parse(CreationProperties["Count"]); // read links UInt64 n100 = n / 100; UInt64 c = 0; DateTime dtStart = DateTime.UtcNow; for(UInt64 i = 0; i < n; ++i) { if (c++ == n100) { c = 0; // Check for cancellation ThrowIfCancellationRequested(); // Raise progress message string message = "AliquotDB: Read {0:N0} of {1:N0}".FormatWith(i, n); BigInteger b_i = i; BigInteger b_n = n; BigInteger b_percent = b_i * 100 / b_n; int percent = int.Parse(b_percent.ToString()); ProgressEventArgs.RaiseEvent(myProgressIndicator, percent, message); } UInt64 current = reader.ReadUInt64(); UInt64 successor = reader.ReadUInt64(); var pf = PrimeFactorisation.Create(reader); Links[current] = new AliquotChainLink(current, successor, pf); } DateTime dtEnd = DateTime.UtcNow; double sec = (dtEnd - dtStart).TotalSeconds; Utilities.LogLine("ADB Read Time: {0:N2} sec", sec); }