using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HeuristicLab.Common { public static class Extensions { public static bool IsAlmost(this double x, double y) { return Math.Abs(x - y) < 1.0e-6; } public static T SelectRandom(this IEnumerable xs, Random rand) { var xsArr = xs.ToArray(); return xsArr[rand.Next(xsArr.Length)]; } public static IEnumerable SampleProportional(this IEnumerable source, Random random, IEnumerable weights) { var sourceArray = source.ToArray(); var valueArray = weights.ToArray(); double total = valueArray.Sum(); while (true) { int index = 0; double ball = valueArray[index], sum = random.NextDouble() * total; while (ball < sum) ball += valueArray[++index]; yield return sourceArray[index]; } } public static double RSq(IEnumerable xs, IEnumerable ys) { // two pass implementation, but we don't care var meanX = xs.Average(); var meanY = ys.Average(); var s = 0.0; var ssX = 0.0; var ssY = 0.0; foreach (var p in xs.Zip(ys, (x, y) => new { x, y })) { s += (p.x - meanX) * (p.y - meanY); ssX += Math.Pow(p.x - meanX, 2); ssY += Math.Pow(p.y - meanY, 2); } if (s.IsAlmost(0)) return 0; if (ssX.IsAlmost(0) || ssY.IsAlmost(0)) return 0; return s * s / (ssX * ssY); } } }