private void Learn(Path <RegressiveNode> path, WorldState initialState) { var learned = false; var currentState = new WorldState(initialState); foreach (var edge in path.Edges.Reverse()) { var action = edge.GetAction(); if (!action.IsExperience) { var experienceAction = new ExperienceAction(currentState, action); if (baseExperienceActions.Add(experienceAction)) { learned = true; if (experienceGraph.TryGetValue(currentState, out var value)) { value.Add(experienceAction); } else { experienceGraph.Add(currentState, new HashSet <ExperienceAction> { experienceAction }); } if (!experienceGraph.ContainsKey(experienceAction.TargetState)) { experienceGraph.Add(experienceAction.TargetState, new HashSet <ExperienceAction>()); } } } currentState = action.Apply(currentState); } if (learned) { CalculateShortcuts(); } }
private void Learn(Path <ForwardNode> path) { var learned = false; // Only update shortcuts, when new ExperienceActions have been learned foreach (var edge in path.Edges) { if (!edge.GetAction().IsExperience) { var state = edge.SourceNode.WorldState; var action = edge.GetAction(); var experienceAction = new ExperienceAction(state, action); if (baseExperienceActions.Add(experienceAction)) { learned = true; if (experienceGraph.TryGetValue(state, out var value)) { learned = value.Add(experienceAction); } else { experienceGraph.Add(state, new HashSet <ExperienceAction> { experienceAction }); } if (!experienceGraph.ContainsKey(experienceAction.TargetState)) { experienceGraph.Add(experienceAction.TargetState, new HashSet <ExperienceAction>()); } } } } if (learned) { CalculateShortcuts(); } }
// Parse experience graph for shortcuts and private void CalculateShortcuts() { var timer = new ResettableStopwatchExecutionTimer(); // Floyd-Warshall // Initialize Matrix var size = experienceGraph.Count; var graph = new double[size, size]; var actionList = new List <ExperienceAction> [size, size]; for (var i = 0; i < size; i++) { for (var j = 0; j < size; j++) { var initialAction = InitializeExperienceGraphMatrixNode(i, j); var initialActionList = new List <ExperienceAction>(); double initialCost; if (initialAction != null) { initialActionList.Add(initialAction); initialCost = initialAction.Cost; } else { initialCost = double.PositiveInfinity; } graph[i, j] = initialCost; actionList[i, j] = initialActionList; } } // Calculate shortcuts for (var k = 0; k < size; k++) { for (var i = 0; i < size; i++) { for (var j = 0; j < size; j++) { if (graph[i, k] + graph[k, j] < graph[i, j]) { graph[i, j] = graph[i, k] + graph[k, j]; actionList[i, j] = actionList[i, k]; actionList[i, j].AddRange(new List <ExperienceAction>(actionList[k, j])); } } } } for (var i = 0; i < size; i++) { for (var j = 0; j < size; j++) { if (graph[i, j] < double.PositiveInfinity) { var nextAct = actionList[i, j]; var baseActionList = new List <PlanningAction>(); foreach (var expAction in nextAct) { baseActionList.AddRange(expAction.Actions); } var shortcut = new ExperienceAction(nextAct.First().StartState, baseActionList.ToArray()); // if (experienceActions.Add(shortcut)) // UnityEngine.Debug.LogWarning("New shortcut action: " + shortcut); experienceActions.Add(shortcut); } } } UnityEngine.Debug.Log($"Time calculating shortcuts: {timer.ElapsedSeconds}"); }