/// <summary> /// This fires in an arbitrary thread. It looks at what's in the map, and builds instructions that will be run in the main thread /// (adds/removes) /// </summary> public void Update_AnyThread(double elapsedTime) { MapOctree snapshot = _map.LatestSnapshot; if (snapshot == null) { return; } IEnumerable <MapObjectInfo> allItems = snapshot.GetItems(); //_map.GetAllItems(true) //TODO: May want to use this to get disposed items // Look for too few/many ChangeInstruction[] asteroids = ExamineAsteroids(allItems, _boundry); ChangeInstruction[] minerals = ExamineMinerals(allItems, _boundry, _mineralTypesByValue); // Store these instructions for the main thread to do if (asteroids != null || minerals != null) { ChangeInstruction[] instructions = UtilityCore.ArrayAdd(asteroids, minerals); if (instructions.Length > MAXCHANGES) { instructions = UtilityCore.RandomOrder(instructions, MAXCHANGES).ToArray(); } _instructions = instructions; } }
private static SOMResult ProcessNewItemBatch(SOMItem[] newItemBatch, bool discardDupes, double dupeDistSquared, SOMResult existing) { const int TOTALMAX = BATCHMAX * 10; // Items only make it here when they aren't too similar to the som nodes, but items within this list may be dupes if (discardDupes) { newItemBatch = DedupeItems(newItemBatch, dupeDistSquared); } if (newItemBatch.Length > BATCHMAX) { // There are too many, just take a sample newItemBatch = UtilityCore.RandomRange(0, newItemBatch.Length, BATCHMAX). Select(o => newItemBatch[o]). ToArray(); } SOMItem[] existingItems = null; if (existing != null) { existingItems = existing.InputsByNode. SelectMany(o => o). Select(o => ((SOMInput <SOMItem>)o).Source). ToArray(); } SOMItem[] allItems = UtilityCore.ArrayAdd(existingItems, newItemBatch); //TODO: This is too simplistic. See if existingItems + newItemBatch > total. If so, try to draw down the existing nodes evenly. Try //to preserve previous images better. Maybe even throw in a timestamp to get a good spread of times // //or get a SOM of the new, independent of the old. Then merge the two pulling representatives to keep the most diversity. Finally, //take a SOM of the combined if (allItems.Length > TOTALMAX) { allItems = UtilityCore.RandomRange(0, allItems.Length, TOTALMAX). Select(o => allItems[o]). ToArray(); } SOMInput <SOMItem>[] inputs = allItems. Select(o => new SOMInput <SOMItem>() { Source = o, Weights = o.Weights, }). ToArray(); //TODO: May want rules to persist from run to run SOMRules rules = GetSOMRules_Rand(); return(SelfOrganizingMaps.TrainSOM(inputs, rules, true)); }
/// <summary> /// This will move the types in transfer from the from array to the to array. The arrays passed in won't be affected, /// but the return will be the new from and to /// </summary> private static Tuple <Type[], Tuple <Type, int>[]> TransferTypes(Type[] existingFrom, Tuple <Type, int>[] existingTo, Tuple <Type, int>[] transfer) { // Only keep the types that aren't in transfer Type[] newFrom = existingFrom.Where(o => !transfer.Any(p => p.Item1.Equals(o))).ToArray(); if (newFrom.Length == 0) { newFrom = null; } // Add transfer to existing Tuple <Type, int>[] newTo = UtilityCore.ArrayAdd(existingTo, transfer); return(Tuple.Create(newFrom, newTo)); }
/// <summary> /// This allows items to be updated that aren't added to the map /// </summary> public void AddNonMapItem(IPartUpdatable item, long token) { if (item.IntervalSkips_MainThread != null) { _nonmapItemsMain.Add(Tuple.Create(item.IntervalSkips_MainThread.Value, item, token)); } lock (_lockTypesAny) { if (item.IntervalSkips_AnyThread != null) { _nonmapItemsAny = UtilityCore.ArrayAdd(_nonmapItemsAny, Tuple.Create(item.IntervalSkips_AnyThread.Value, item, token)); } } }