NativeMultiHashMap <int, int> GetBinnedStateKeys(PlanGraph <int, StateInfo, int, ActionInfo, StateTransitionInfo> planGraph)
        {
            var binned = new NativeMultiHashMap <int, int>(planGraph.StateInfoLookup.Count(), Allocator.Persistent);

            using (var stateKeys = planGraph.StateInfoLookup.GetKeyArray(Allocator.Temp))
            {
                foreach (var stateKey in stateKeys)
                {
                    binned.Add(stateKey.GetHashCode(), stateKey);
                }
            }
            return(binned);
        }
示例#2
0
        /// <summary>
        /// Will build a tree with N subnodes per node = actionsPerState * resultsPerAction;
        /// A depth of 1 will result in a single root node
        /// </summary>
        internal static PlanGraph <int, StateInfo, int, ActionInfo, StateTransitionInfo> BuildTree(int actionsPerState = 2, int resultsPerAction = 2, int depth = 10)
        {
            Debug.Assert(depth > 0);

            // tree
            float probabilityPerResult = 1f / resultsPerAction;
            int   nextStateIndex       = 0;
            var   subNodesPerNode      = actionsPerState * resultsPerAction;
            int   totalStates          = GetTotalNodeCountForTreeDepth(subNodesPerNode, depth);

            var planGraph = new PlanGraph <int, StateInfo, int, ActionInfo, StateTransitionInfo>(totalStates, totalStates, totalStates);
            var builder   = new PlanGraphBuilder <int, int> {
                planGraph = planGraph
            };
            var queue = new NativeQueue <int>(Allocator.TempJob);

            // Add root
            int rootStateIndex = nextStateIndex;

            nextStateIndex++;
            builder.AddState(rootStateIndex);
            queue.Enqueue(rootStateIndex);

            for (int horizon = 0; horizon < depth - 1; horizon++)
            {
                var statesInHorizon = Math.Pow(actionsPerState * resultsPerAction, horizon);
                for (int i = 0; i < statesInHorizon; i++)
                {
                    var state        = queue.Dequeue();
                    var stateContext = builder.WithState(state);

                    for (int actionIndex = 0; actionIndex < actionsPerState; actionIndex++)
                    {
                        var actionContext = stateContext.AddAction(actionIndex);

                        for (int j = 0; j < resultsPerAction; j++)
                        {
                            var newStateIndex = nextStateIndex;
                            nextStateIndex++;
                            actionContext.AddResultingState(newStateIndex, probability: probabilityPerResult);
                            queue.Enqueue(newStateIndex);
                        }
                    }
                }
            }

            queue.Dispose();

            return(planGraph);
        }
        public void SetupPartialPlanGraph()
        {
            m_PlanGraph = new PlanGraph <int, StateInfo, int, ActionInfo, StateTransitionInfo>(10, 10, 10);

            var builder = new PlanGraphBuilder <int, int>()
            {
                planGraph = m_PlanGraph
            };
            var stateContext = builder.AddState(k_RootState);

            stateContext.AddAction(k_ActionOne).AddResultingState(k_StateOne);
            stateContext.AddAction(k_ActionTwo).AddResultingState(k_StateTwo);

            // Add first half of actions to simulate action system
            builder.WithState(k_StateOne).AddAction(k_ActionOne);
            builder.WithState(k_StateTwo).AddAction(k_ActionTwo);
        }
示例#4
0
        internal static void AddRootCycles(PlanGraph <int, StateInfo, int, ActionInfo, StateTransitionInfo> planGraph, int rootKey, int actionKey = -2)
        {
            var builder = new PlanGraphBuilder <int, int> {
                planGraph = planGraph
            };
            var stateInfoLookup = planGraph.StateInfoLookup;

            using (var stateKeyArray = stateInfoLookup.GetKeyArray(Allocator.TempJob))
            {
                foreach (var stateKey in stateKeyArray)
                {
                    if (planGraph.ActionLookup.TryGetFirstValue(stateKey, out _, out _))
                    {
                        builder.WithState(stateKey).AddAction(actionKey).AddResultingState(rootKey);
                    }
                }
            }
        }
示例#5
0
        internal static PlanGraph <int, StateInfo, int, ActionInfo, StateTransitionInfo> BuildLattice(int midLatticeDepth = 10)
        {
            int nextStateIndex = 0;
            int totalStates    = (int)Math.Pow(2, midLatticeDepth) * 2;

            var planGraph = new PlanGraph <int, StateInfo, int, ActionInfo, StateTransitionInfo>(totalStates, totalStates, totalStates);
            var builder   = new PlanGraphBuilder <int, int> {
                planGraph = planGraph
            };
            var queue = new NativeQueue <int>(Allocator.TempJob);

            // Add root
            int rootStateIndex = nextStateIndex;

            nextStateIndex++;
            builder.AddState(rootStateIndex);
            queue.Enqueue(rootStateIndex);

            for (int horizon = 0; horizon < midLatticeDepth; horizon++)
            {
                var statesInHorizon = Math.Pow(2, horizon);
                for (int i = 0; i < statesInHorizon; i++)
                {
                    var state        = queue.Dequeue();
                    var stateContext = builder.WithState(state);

                    var leftIndex = i == 0 ? nextStateIndex : nextStateIndex - 1;
                    nextStateIndex++;
                    stateContext.AddAction(0).AddResultingState(leftIndex);
                    if (i == 0)
                    {
                        queue.Enqueue(leftIndex);
                    }

                    var rightIndex = nextStateIndex;
                    nextStateIndex++;
                    stateContext.AddAction(1).AddResultingState(rightIndex);
                    queue.Enqueue(rightIndex);
                }
            }

            for (int horizon = midLatticeDepth - 1; horizon >= 0; horizon--)
            {
                var statesInHorizon = Math.Pow(2, horizon);
                for (int i = 0; i < statesInHorizon; i++)
                {
                    var state        = queue.Dequeue();
                    var stateContext = builder.WithState(state);

                    if (i > 0)
                    {
                        var leftIndex = nextStateIndex - 1;
                        stateContext.AddAction(0).AddResultingState(leftIndex);
                        //queue.Enqueue(leftIndex);
                    }

                    if (i < statesInHorizon - 1)
                    {
                        var rightIndex = nextStateIndex;
                        nextStateIndex++;
                        stateContext.AddAction(1).AddResultingState(rightIndex);
                        queue.Enqueue(rightIndex);
                    }
                }
            }

            queue.Dispose();

            return(planGraph);
        }
        public void MatchManyExistingStates()
        {
            const int kRootState   = 0;
            const int kActionCount = 1000;

            PlanGraph <int, StateInfo, int, ActionInfo, StateTransitionInfo> planGraph = default;
            NativeMultiHashMap <int, int> binnedStateKeys = default;
            NativeQueue <int>             newStatesQueue  = default;
            NativeList <StateTransitionInfoPair <int, int, StateTransitionInfo> > statesToProcess = default;
            NativeQueue <int> newStatesToDestroy = default;

            Measure.Method(() =>
            {
                var stateTransitionInfoLookup = planGraph.StateTransitionInfoLookup;
                var resultingStateLookup      = planGraph.ResultingStateLookup;

                var expansionJob = new GraphExpansionJob <int, int, TestStateDataContext, int>
                {
                    BinnedStateKeys             = binnedStateKeys,
                    NewStateTransitionInfoPairs = statesToProcess.AsDeferredJobArray(),

                    ActionLookup              = planGraph.ActionLookup.AsParallelWriter(),
                    ActionInfoLookup          = planGraph.ActionInfoLookup.AsParallelWriter(),
                    StateTransitionInfoLookup = stateTransitionInfoLookup.AsParallelWriter(),
                    ResultingStateLookup      = resultingStateLookup.AsParallelWriter(),
                    NewStates        = newStatesQueue.AsParallelWriter(),
                    PredecessorGraph = planGraph.PredecessorGraph.AsParallelWriter(),
                    StateDataContext = new TestStateDataContext(),
                    StatesToDestroy  = newStatesToDestroy.AsParallelWriter(),
                };

                expansionJob.Schedule(statesToProcess, default).Complete();
            }).SetUp(() =>
            {
                // One root node and all children nodes of a single depth
                planGraph = PlanGraphUtility.BuildTree(kActionCount, 1, 1);
                planGraph.ExpandBy(kActionCount, kActionCount);

                newStatesQueue     = new NativeQueue <int>(Allocator.TempJob);
                newStatesToDestroy = new NativeQueue <int>(Allocator.TempJob);

                // Extend graph by one depth with the same number of actions / resulting states that loop back on themselves
                statesToProcess = new NativeList <StateTransitionInfoPair <int, int, StateTransitionInfo> >(kActionCount, Allocator.TempJob);
                for (var i = 0; i < kActionCount; i++)
                {
                    statesToProcess.Add(new StateTransitionInfoPair <int, int, StateTransitionInfo>(kRootState, i, i, new StateTransitionInfo()
                    {
                        Probability = 1, TransitionUtilityValue = 1
                    }));
                }

                binnedStateKeys = GetBinnedStateKeys(planGraph);
            }).CleanUp(() =>
            {
                planGraph.Dispose();
                newStatesQueue.Dispose();
                statesToProcess.Dispose();
                binnedStateKeys.Dispose();
                newStatesToDestroy.Dispose();
            }).WarmupCount(1).MeasurementCount(30).IterationsPerMeasurement(1).Run();

            PerformanceUtility.AssertRange(4.3, 6.25);
        }