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 n = xs.Count(); return xs.ElementAt(rand.Next(n)); } public static T SampleProportional(this IEnumerable elements, Random random, IEnumerable weights) { double total = weights.Sum(); var elemEnumerator = elements.GetEnumerator(); elemEnumerator.MoveNext(); var weightEnumerator = weights.GetEnumerator(); weightEnumerator.MoveNext(); var r = random.NextDouble() * total; var agg = weightEnumerator.Current; while (agg < r) { weightEnumerator.MoveNext(); elemEnumerator.MoveNext(); agg += weightEnumerator.Current; } return elemEnumerator.Current; } 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 += (x - meanX) * (x - meanX); ssY += (y - meanY) * (y - meanY); } 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); } } }