private static LinkIO[] IOLinks(Item2D[] brains, Item2D[] io, SortedList<Tuple<int, int>, double> allBrainLinks, IOLinkupPriority ioLinkupPriority, double brainLinkResistanceMult) { // Look for brains that are really close together, treat those as single brains Set2D[] brainSets = Worker2D_Voronoi.IOLinks_PreMergeBrains(brains, allBrainLinks); #region Brain-IO Distances // Figure out the distances between io and brains var distancesIO = Enumerable.Range(0, io.Length). Select(o => new { IOIndex = o, BrainDistances = Enumerable.Range(0, brainSets.Length). Select(p => Tuple.Create(p, (brainSets[p].Center - io[o].Position).Length)). //Item1=BrainIndex, Item2=DistanceToBrain OrderBy(p => p.Item2). // first brain needs to be the shortest distance ToArray() }); switch (ioLinkupPriority) { case IOLinkupPriority.ShortestDistFirst: distancesIO = distancesIO.OrderBy(o => o.BrainDistances.First().Item2); break; case IOLinkupPriority.LongestDistFirst: distancesIO = distancesIO.OrderByDescending(o => o.BrainDistances.First().Item2); break; case IOLinkupPriority.RandomOrder: //TODO: Come up with a less expensive way of doing this //.Select(o => new { Orig=o, Key=Guid.NewGuid }).OrderBy(o => o.Key).Select(o => o.Orig) Random rand = StaticRandom.GetRandomForThread(); distancesIO = distancesIO. Select(o => new { Orig = o, Key = rand.Next(int.MaxValue) }). OrderBy(o => o.Key). Select(o => o.Orig); break; default: throw new ApplicationException("Unknown IOLinkupPriority: " + ioLinkupPriority.ToString()); } distancesIO = distancesIO.ToArray(); #endregion // Brain-Brain Distances var distancesBrain = BrainBrainDistances(brainSets, brainLinkResistanceMult); // Link IO to brains BrainBurden[] links = Enumerable.Range(0, brainSets.Length).Select(o => new BrainBurden(o, brainSets, io)).ToArray(); foreach (var distanceIO in distancesIO) { int ioIndex = distanceIO.IOIndex; int closestBrainIndex = distanceIO.BrainDistances[0].Item1; AddIOLink(links, ioIndex, io[ioIndex].Size, closestBrainIndex, distancesBrain[closestBrainIndex]); } // Build the return List<LinkIO> retVal = new List<LinkIO>(); foreach (BrainBurden brain in links) { foreach (int ioIndex in brain.IOLinks) { retVal.Add(new LinkIO(brain.Brain, ioIndex, io)); } } return retVal.ToArray(); }
public static void GetLinks(out LinkBrain2D[] brainLinks, out LinkIO[] ioLinks, Item2D[] brains, Item2D[] io, IOLinkupPriority ioLinkupPriority = IOLinkupPriority.ShortestDistFirst, double brainLinkResistanceMult = 10) { if (brains == null || brains.Length == 0) { brainLinks = null; ioLinks = null; return; } else if (brains.Length == 1) { brainLinks = null; ioLinks = Enumerable.Range(0, io.Length).Select(o => new LinkIO(0, o, brains, io)).ToArray(); return; } // Link brains:brains SortedList<Tuple<int, int>, double> allBrainLinks; Worker2D_Voronoi.BrainLinks(out allBrainLinks, out brainLinks, brains); // Link brains:io ioLinks = IOLinks(brains, io, allBrainLinks, ioLinkupPriority, brainLinkResistanceMult); }