private static int GetEstimatedNumberOfLinks_Final(int brainCount, int ioCount, ItemLinker_ExtraArgs extra) { return -1; }
private static Tuple<int, int>[] Link12_Extra(Tuple<int, int>[] initial, LinkItem[] items1, LinkItem[] items2, DistributeDistances distances, ItemLinker_ExtraArgs extraArgs) { Random rand = StaticRandom.GetRandomForThread(); int wholePercent = extraArgs.Percent.ToInt_Floor(); List<int> addOrder = new List<int>(); if (extraArgs.BySize) { double totalSize = items2.Sum(o => o.Size); double maxSize = extraArgs.Percent * totalSize; double usedSize = 0; if (extraArgs.EvenlyDistribute) { #region by size, evenly distribute // Add some complete passes if over 100% percent for (int cntr = 0; cntr < wholePercent; cntr++) { addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length)); } usedSize = wholePercent * totalSize; #endregion } #region by size, distribute the rest //NOTE: Building this list by size so that larger items have a higher chance of being chosen var bySize = items2. Select((o, i) => Tuple.Create(i, o.Size / totalSize)). OrderByDescending(o => o.Item2). ToArray(); // Keep selecting items unti the extra size is consumed (or if no more can be added) while (true) { bool foundOne = false; for (int cntr = 0; cntr < 1000; cntr++) // this is an infinite loop detector { int attemptIndex = UtilityCore.GetIndexIntoList(rand.NextDouble(), bySize); // get the index into the list that the rand percent represents attemptIndex = bySize[attemptIndex].Item1; // get the index into items2 if (items2[attemptIndex].Size + usedSize <= maxSize) { foundOne = true; usedSize += items2[attemptIndex].Size; addOrder.Add(attemptIndex); break; } } if (!foundOne) { // No more will fit break; } } #endregion } else { if (extraArgs.EvenlyDistribute) { #region ignore size, evenly distribute // Add some complete passes if over 100% percent for (int cntr = 0; cntr < wholePercent; cntr++) { addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length)); } // Add some items based on the portion of percent that is less than 100% int remainder = (items2.Length * (extraArgs.Percent - wholePercent)). ToInt_Round(); addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length, remainder)); #endregion } else { #region ignore size, randomly distribute int totalCount = (items2.Length * extraArgs.Percent). ToInt_Round(); //NOTE: UtilityCore.RandomRange stops when the list is exhausted, and makes sure not to have dupes. That's not what is wanted //here. Just randomly pick X times addOrder.AddRange(Enumerable.Range(0, totalCount).Select(o => rand.Next(items2.Length))); #endregion } } return AddLinks(items1, items2, distances, addOrder, initial); }
private void btn3DLinksBrainIO_Click(object sender, RoutedEventArgs e) { try { PrepFor3D(); ClearTempVisuals(); LinkItem[] brains = _brains3D. Select(o => new LinkItem(o.Position.Value, o.Size)). ToArray(); LinkItem[] io = _inputs3D. Concat(_outputs3D). Select(o => new LinkItem(o.Position.Value, o.Size)). ToArray(); ItemLinker_OverflowArgs overflowArgs = new ItemLinker_OverflowArgs() { LinkResistanceMult = trk3DLinkResistMult.Value, }; ItemLinker_ExtraArgs extraArgs = null; if (!trk3DExtraLinkPercent.Value.IsNearZero()) { extraArgs = new ItemLinker_ExtraArgs() { Percent = trk3DExtraLinkPercent.Value / 100d, BySize = chk3DExtraLinkBySize.IsChecked.Value, EvenlyDistribute = chk3DExtraLinkEvenDistribute.IsChecked.Value, }; } Tuple<int, int>[] links = ItemLinker.Link_1_2(brains, io, overflowArgs, extraArgs); // Draw _linksIO3D.AddRange(DrawBrainIOLinks3D(_viewportFull, links, _brains3D.ToArray(), _inputs3D.Concat(_outputs3D).ToArray(), _ioLinkColor, chk3DRainbowLinks.IsChecked.Value)); } catch (Exception ex) { MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error); } }
/// <summary> /// Every item in 2 will have at least one link to a 1. There could be some item1s that don't have a link /// </summary> /// <param name="overflowArgs"> /// Item2s get matched to the nearest Item1. /// If this args is null then, it stays that way. /// If this is populated, then links will move from burdened item1s to less burdened /// </param> /// <returns> /// Item1=index into item1 list /// Item2=index into item2 list /// </returns> public static Tuple<int, int>[] Link_1_2(LinkItem[] items1, LinkItem[] items2, ItemLinker_OverflowArgs overflowArgs = null, ItemLinker_ExtraArgs extraArgs = null) { if (items1 == null || items2 == null || items1.Length == 0 || items2.Length == 0) { return new Tuple<int, int>[0]; } Tuple<int, int>[] retVal = null; if (overflowArgs == null) { // Just link to the closest retVal = Link12_Closest(items1, items2); } if (overflowArgs == null && extraArgs == null) { // Nothing special to do, exit early return retVal; } DistributeDistances distances = GetDistances(items1, items2, overflowArgs); if (overflowArgs != null) { // Consider item1s burden when linking them retVal = Link12_Distribute(items1, items2, distances); } if (extraArgs != null) { // Add more links retVal = Link12_Extra(retVal, items1, items2, distances, extraArgs); } return retVal; }