/// <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 TrainSOM(SOMNode[] nodes, ISOMInput[] inputs, SOMRules rules, bool returnEmptyNodes = false) { double mapRadius = MathND.GetRadius(MathND.GetAABB(nodes.Select(o => o.Weights))); SOMNode[] returnNodes = nodes. Select(o => o.Clone()). ToArray(); double timeConstant = rules.NumIterations / Math.Log(mapRadius); int iteration = 0; int remainingIterations = rules.NumIterations; while (remainingIterations > 0) { foreach (ISOMInput input in UtilityCore.RandomOrder(inputs, Math.Min(remainingIterations, inputs.Length))) { // Find closest node SOMNode closest = GetClosest(returnNodes, input).Item1; // Find other affected nodes (a node and distance squared) double searchRadius = mapRadius * rules.InitialRadiusPercent * Math.Exp(-iteration / timeConstant); Tuple <SOMNode, double>[] neigbors = GetNeighbors(returnNodes, closest, searchRadius); double learningRate = rules.LearningRate * Math.Exp(-(double)iteration / (double)rules.NumIterations); // Adjust the matched node (full learning rate) AdjustNodeWeights(closest, input.Weights, learningRate); foreach (var node in neigbors) { double influence = GetInfluence(rules.AttractionFunction, node.Item2, searchRadius); // Adjust a neighbor AdjustNodeWeights(node.Item1, input.Weights, learningRate * influence); } iteration++; } remainingIterations -= inputs.Length; } // See which images go with which nodes ISOMInput[][] inputsByNode = GetInputsByNode(returnNodes, inputs); SOMResult retVal = new SOMResult(returnNodes, inputsByNode, true); if (!returnEmptyNodes) { retVal = RemoveZeroNodes(retVal); } return(retVal); }