static void EvaluateSolution(string name, Assembly ass, Bitmap image, int colormapSize, TextWriter wri) { Color[] colors = null; object[] arguments = new object[] { image, colormapSize, colors }; // memory cleanup and report: long memOccupied = GC.GetTotalMemory(true); Process procObj = Process.GetCurrentProcess(); Options.LogFormatMode("debug", $"Evaluating '{name}' [{(memOccupied >> 20)}M - {(procObj.PrivateMemorySize64 >> 20)}M - {(procObj.VirtualMemorySize64 >> 20)}M - {(procObj.WorkingSet64 >> 20)}M - {(procObj.PagedMemorySize64 >> 20)}M - {(procObj.PagedSystemMemorySize64 >> 10)}K - {(procObj.NonpagedSystemMemorySize64 >> 10)}K]"); string msg = null; // running the solution function: sw.Restart(); try { ass.GetType("cmap" + name + ".Colormap").GetMethod("Generate").Invoke(null, arguments); } catch (Exception e) { msg = (e.InnerException ?? e).Message; } sw.Stop(); colors = arguments[2] as Color[]; double minS = EvalOptions.options.minS; double minV = EvalOptions.options.minV; double maxV = EvalOptions.options.maxV; // quantile statistics for elapsed time and color variance double elapsed = sw.ElapsedMilliseconds * 0.001; double sumVar = 0.0; int N = 1; if (colors != null && colors.Length > 1) { qtime.Add(elapsed); N = 0; for (int i = 0; i < colors.Length - 1; i++) { for (int j = i + 1; j < colors.Length; j++) { N++; double La, Lb, Aa, Ab, Ba, Bb; Arith.ColorToCIELab(colors[i], out La, out Aa, out Ba); Arith.ColorToCIELab(colors[j], out Lb, out Ab, out Bb); La -= Lb; Aa -= Ab; Ba -= Bb; sumVar += Math.Sqrt(La * La + Aa * Aa + Ba * Ba); } } qvariance.Add(sumVar / N); } // report: bool best = EvalOptions.options.best.Contains(name); wri.Write(string.Format(CultureInfo.InvariantCulture, "<tr><td class=\"t\">{0}{1}{2}</td><td class=\"p t r\">{3:f2}s</td><td class=\"p t r\">{4:f1}</td>", best ? "<b>" : "", name, best ? "</b>" : "", elapsed, sumVar / N)); if (!string.IsNullOrEmpty(msg) || colors == null || colors.Length == 0) { Util.Log($"Error: '{msg}'"); wri.WriteLine($"<td>Error: {msg}</td>"); wri.WriteLine("</tr>"); return; } // optional color unification: if (EvalOptions.options.uniqueColors) { List <Color> nc = new List <Color>(); foreach (Color c in colors) { bool isNew = true; foreach (Color oc in nc) { if (oc.R == c.R && // ignoring the 'alpha' channel oc.G == c.G && oc.B == c.B) { isNew = false; break; } } if (isNew) { nc.Add(c); } } colors = nc.ToArray(); } // optional color ordering: if (EvalOptions.options.sortColors) { Array.Sort(colors, (a, b) => { double La, Lb, A, B; Arith.ColorToCIELab(a, out La, out A, out B); Arith.ColorToCIELab(b, out Lb, out A, out B); return(La.CompareTo(Lb)); }); } // SVG color visualization: int width = EvalOptions.options.imageWidth; int widthBin = width / Math.Max(6, colormapSize); int height = 50; int border = 2; wri.WriteLine($"<td><svg width=\"{width}\" height=\"{height}\">"); int x = 0; foreach (var col in colors) { string rgb = string.Format("#{0:X2}{1:X2}{2:X2}", col.R, col.G, col.B); wri.WriteLine("<rect x=\"{0}\" y=\"{1}\" width=\"{2}\" height=\"{3}\" fill=\"{4}\" />", x + border, border, widthBin - 2 * border, height - 2 * border - 14, rgb); wri.WriteLine("<text x=\"{0}\" y=\"{1}\" class=\"rgb\" text-anchor=\"middle\">{2}</text>", x + widthBin / 2, height - border, rgb); x += widthBin; } wri.WriteLine("</svg></td>"); wri.WriteLine("</tr>"); }