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-12; } 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; var xEnum = xs.GetEnumerator(); var yEnum = ys.GetEnumerator(); while (xEnum.MoveNext() & yEnum.MoveNext()) { var x = xEnum.Current; var y = yEnum.Current; s += (x - meanX) * (y - meanY); ssX += Math.Pow(x - meanX, 2); ssY += Math.Pow(y - meanY, 2); } if (xEnum.MoveNext() | yEnum.MoveNext()) throw new ArgumentException("lengths are not equal"); if (s.IsAlmost(0)) return 0; if (ssX.IsAlmost(0) || ssY.IsAlmost(0)) return 0; return s * s / (ssX * ssY); } } }