public BrainBurden(int index, Set2D[] brainSets, Item2D[] io) { this.Index = index; this.Brain = brainSets[index]; this.Size = this.Brain.Items.Sum(o => o.Size); _io = io; }
private static bool IOLinks_PostAdjust_MoveNext(BrainBurden[] ioLinks, Tuple<int, double>[][] brainLinks, Set2D[] brainSets, Item2D[] io) { List<Tuple<BrainBurden, int, double, double>> candidates = new List<Tuple<BrainBurden, int, double, double>>(); // Find brains that have excess links to give away, and which ones to hand to foreach (BrainBurden ioLink in ioLinks.Where(o => o.LinksOrig.Count > 0)) { foreach (Tuple<int, double> brainLink in brainLinks[ioLink.Index]) { double otherBurden = ioLinks.First(o => o.Index == brainLink.Item1).Burden; if (ioLink.Burden > otherBurden + brainLink.Item2) { candidates.Add(Tuple.Create(ioLink, brainLink.Item1, ioLink.Burden - (otherBurden + brainLink.Item2), brainLink.Item2)); } } } // Iterate over them with the largest distance first (can't just pull the top, because an individual io link may represent too big of a burden // to be able to shift) foreach (var candidate in candidates.OrderByDescending(o => o.Item3)) { // Try to move a link if (IOLinks_PostAdjust_MoveNext_Brain(candidate.Item1, ioLinks.First(o => o.Index == candidate.Item2), candidate.Item4, brainSets, io)) { return true; } } return false; }
private static bool IOLinks_PostAdjust_MoveNext_Brain(BrainBurden from, BrainBurden to, double linkBurden, Set2D[] brainSets, Item2D[] io) { // Cache the sizes of the current io links double fromIOSize = UtilityCore.Iterate(from.LinksOrig, from.LinksMoved).Sum(o => io[o].Size); double toIOSize = UtilityCore.Iterate(to.LinksOrig, to.LinksMoved).Sum(o => io[o].Size); // See what the new burdens would be for from and to for each io link var newBurdens = from.LinksOrig.Select(o => new { IOIndex = o, FromBurden = BrainBurden.CalculateBurden(fromIOSize - io[o].Size, from.BrainSize), ToBurden = BrainBurden.CalculateBurden(toIOSize + io[o].Size, to.BrainSize), }). Where(o => o.FromBurden >= linkBurden + o.ToBurden). // throw out any moves that cause a reverse in burden Select(o => new { IOIndex = o.IOIndex, FromBurden = o.FromBurden, ToBurden = o.ToBurden, Distance = (brainSets[to.Index].Center - io[o.IOIndex].Position).Length, //TODO: Other scoring criterea here }). ToArray(); if (newBurdens.Length == 0) { return false; } // Come up with the best io to move //TODO: Things to consider // Distance between io and to brain // Types of IO that from and to have (try to specialize) // // When combining scores, can't just score things linearly, then add up the score. Average performers of multiple categories // would win var best = newBurdens.OrderBy(o => o.Distance).First(); // Move the link to.LinksMoved.Add(best.IOIndex); from.LinksOrig.Remove(best.IOIndex); return true; }
private static Tuple<int, int>[] IOLinks_PostAdjust(Tuple<int, int>[] initial, Set2D[] brainSets, Item2D[] io) { // Get the links and distances between brain sets Tuple<int, double>[][] brainLinks = IOLinks_PostAdjust_BrainBrainLinks(brainSets); // Turn the initial links into something more usable (list of links by brain) BrainBurden[] ioLinks = initial. GroupBy(o => o.Item1). Select(o => new BrainBurden(o.Key, o.Select(p => p.Item2))). ToArray(); // Make sure there is an element in ioLinks for each brainset (the groupby logic above only grabs brainsets that have links) int[] missing = Enumerable.Range(0, brainLinks.Length).Where(o => !ioLinks.Any(p => p.Index == o)).ToArray(); ioLinks = UtilityCore.Iterate(ioLinks, missing.Select(o => new BrainBurden(o, Enumerable.Empty<int>()))).ToArray(); // Move one link at a time while (true) { // Figure out how burdened each brain set is foreach (BrainBurden brain in ioLinks) { brain.Recalc(brainSets, io); } // Find the best link to move if (!IOLinks_PostAdjust_MoveNext(ioLinks, brainLinks, brainSets, io)) { break; } } // Just build it manually //return ioLinks.Select(o => new { BrainIndex = o.Index, UtilityCore.Iterate(o.LinksOrig, o.LinksMoved) //var test = ioLinks. // Select(o => new { BrainIndex = o.Index, Links = UtilityCore.Iterate(o.LinksOrig, o.LinksMoved).ToArray() }). // ToArray(); List<Tuple<int, int>> retVal = new List<Tuple<int, int>>(); foreach (BrainBurden brain in ioLinks) { foreach (int ioIndex in UtilityCore.Iterate(brain.LinksOrig, brain.LinksMoved)) { retVal.Add(Tuple.Create(brain.Index, ioIndex)); } } return retVal.ToArray(); //return initial; }
private static Tuple<int, double>[][] IOLinks_PostAdjust_BrainBrainLinks(Set2D[] brainSets) { // Get the AABB of the brain sets, and use the diagonal as the size var aabb = Math2D.GetAABB(brainSets.Select(o => o.Center)); double maxDistance = (aabb.Item2 - aabb.Item1).Length; // Get links between the brains and distances of each link var links = Math2D.GetDelaunayTriangulation(brainSets.Select(o => o.Center).ToArray(), true). Select(o => new { Brain1 = o.Item1, Brain2 = o.Item2, Distance = (brainSets[o.Item1].Center - brainSets[o.Item2].Center).Length }). // break here, get stats on lengths, omit links that are excessively long Select(o => new { Brain1 = o.Brain1, Brain2 = o.Brain2, Resistane = (o.Distance / maxDistance) * IOPOSTMERGE_LINKRESISTANCEMULT }). // calculate the wire's resistance (in terms of burden) ToArray(); //string dots = string.Join("\r\n", brainSets.Select(o => string.Format("_linksIO2D.Add(AddDot(new Point({0}, {1}), Brushes.Black, Brushes.Gray));", o.Center.X, o.Center.Y))); //string lines = string.Join("\r\n", links.Select(o => string.Format("_linksIO2D.Add(AddLine(new Point({0}, {1}), new Point({2}, {3}), Brushes.White));", brainSets[o.Brain1].Center.X, brainSets[o.Brain1].Center.Y, brainSets[o.Brain2].Center.X, brainSets[o.Brain2].Center.Y))); //string combined = dots + "\r\n\r\n" + lines; Tuple<int, double>[][] retVal = new Tuple<int, double>[brainSets.Length][]; for (int cntr = 0; cntr < brainSets.Length; cntr++) { // Store all links for this brain retVal[cntr] = links. Where(o => o.Brain1 == cntr || o.Brain2 == cntr). // find links between this brain and another Select(o => Tuple.Create(o.Brain1 == cntr ? o.Brain2 : o.Brain1, o.Resistane)). // store the link to the other brain and the resistance ToArray(); } return retVal; }
private static Tuple<int, int>[] IOLinks_Initial(Set2D[] brains, Item2D[] io, VoronoiResult2D voronoi) { List<Tuple<int, int>> retVal = new List<Tuple<int, int>>(); List<int> remainingIO = Enumerable.Range(0, io.Length).ToList(); // store the remaining so that they can be removed as found (avoid unnecessary IsInside checks) for (int brainCntr = 0; brainCntr < brains.Length; brainCntr++) { Edge2D[] edges = voronoi.EdgesByControlPoint[brainCntr].Select(o => voronoi.Edges[o]).ToArray(); if (edges.Length == 1) { throw new ApplicationException("finish this"); } foreach (int ioIndex in remainingIO.ToArray()) { if (Edge2D.IsInside(edges, io[ioIndex].Position)) { retVal.Add(Tuple.Create(brainCntr, ioIndex)); remainingIO.Remove(ioIndex); } } } return retVal.ToArray(); }
public void Recalc(Set2D[] brainSets, Item2D[] io) { this.BrainSize = brainSets[this.Index].Items.Sum(o => o.Size); this.Burden = CalculateBurden(UtilityCore.Iterate(this.LinksOrig, this.LinksMoved).Sum(o => io[o].Size), this.BrainSize); // size of the links / size of the brain }
public LinkIO(Set2D brains, int io, Item2D[] allIO) { this.Brains = brains; this.IOIndex = io; this.IO = allIO[io]; }
public LinkBrain2D(Set2D brains1, Set2D brains2) { this.Brains1 = brains1; this.Brains2 = brains2; }
private static Tuple<int, double>[][] BrainBrainDistances(Set2D[] brainSets, double brainLinkResistanceMult) { // Get the AABB of the brain sets, and use the diagonal as the size var aabb = Math2D.GetAABB(brainSets.Select(o => o.Center)); double maxDistance = (aabb.Item2 - aabb.Item1).Length; // Get links between the brains and distances of each link List<Tuple<int, int, double>> links2 = new List<Tuple<int, int, double>>(); for (int outer = 0; outer < brainSets.Length - 1; outer++) { for (int inner = outer + 1; inner < brainSets.Length; inner++) { double distance = (brainSets[outer].Center - brainSets[inner].Center).Length; double resistance = (distance / maxDistance) * brainLinkResistanceMult; links2.Add(Tuple.Create(outer, inner, resistance)); } } Tuple<int, double>[][] retVal = new Tuple<int, double>[brainSets.Length][]; for (int cntr = 0; cntr < brainSets.Length; cntr++) { // Store all links for this brain retVal[cntr] = links2. Where(o => o.Item1 == cntr || o.Item2 == cntr). // find links between this brain and another Select(o => Tuple.Create(o.Item1 == cntr ? o.Item2 : o.Item1, o.Item3)). // store the link to the other brain and the resistance OrderBy(o => o.Item2). ToArray(); } return retVal; }