Esempio n. 1
0
    private SimulationBoundary getCurrentSimulationBoundary()
    {
        SimulationBoundary result = null;
        // iterate over the boundaries and start the simulation on the
        // highest level according to them
        float observability = getObservability();

        foreach (SimulationBoundary sb in simulationBoundaries)
        {
            if (observability >= sb.minObservability && observability < sb.maxObservability)
            {
                result = sb;
                break;
            }
        }

        // if the player is outside every boundary start the simulation
        // at the shallowest LoD possible
        if (result == null)
        {
            result = simulationBoundaries.Aggregate((i, j) => i.level < j.level ? i : j);
        }

        Debug.Log(transform.parent.gameObject.name + "\n" + "Observability: " + observability + " Current LoD: " + result.level);
        return(result);
    }
Esempio n. 2
0
    // Use this for initialization
    void Start()
    {
        System.DateTime localDate = System.DateTime.Now;
        // System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("it-IT");
        logFileName = "algorithm_performances_" + localDate.Year + "-" + localDate.Month + "-" + localDate.Day + "_" +
                      localDate.Hour + "-" + localDate.Minute + "-" + localDate.Second + ".log";

        _lastObservedStates = new Dictionary <SimulationBoundary, TreeNode <WorldState> >();
        m_Point             = player.transform.position;

        // parse the JSON domain for each simulation boundary and assign the corresponding domain
        foreach (SimulationBoundary sb in simulationBoundaries)
        {
            Domain deserializedDomain = Newtonsoft.Json.JsonConvert.DeserializeObject <Domain>(File.ReadAllText(sb.jsonDomain), new Newtonsoft.Json.JsonSerializerSettings
            {
                TypeNameHandling  = Newtonsoft.Json.TypeNameHandling.Auto,
                NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
            });
            sb.domain = deserializedDomain;
        }

        int maxLoD = simulationBoundaries.Max(t => t.level);

        // set the initial state at the most detailed level
        TreeNode <WorldState> initialStateFullDetail = new TreeNode <WorldState>(
            Utils.roverWorldStateThirdLevel(getSimulationBoundaryAtLevel(maxLoD).domain)
            );

        // parse the most detailed state to every level of detaile and initialize
        // the last observed state of each boundary to the initial state
        foreach (SimulationBoundary sb in simulationBoundaries)
        {
            _lastObservedStates.Add(sb, new TreeNode <WorldState>(
                                        parseToLevelOfDetail(initialStateFullDetail.Data, sb.domain)
                                        )
                                    );
        }

        SimulationBoundary currentSimulationBoundary = getCurrentSimulationBoundary();

        _currentNode          = getInitialWorldStateAtLevel(currentSimulationBoundary.level);
        _currentLevelOfDetail = currentSimulationBoundary.level;

        StartCoroutine(randomSimulation());
    }
Esempio n. 3
0
    private IEnumerator randomSimulation()
    {
        int lastLoD = _currentLevelOfDetail;

        while (true)
        {
            SimulationBoundary currentSimulationBoundary = getCurrentSimulationBoundary();
            _currentLevelOfDetail = currentSimulationBoundary.level;


            // switch the simulation the change of value is controlled
            // by the LevelOfDetailSwitcher script attached to each boundary
            if (_currentLevelOfDetail != lastLoD)
            {
                // Refinement
                if (_currentLevelOfDetail > lastLoD)
                {
                    StreamWriter writer = new StreamWriter(logFilePath + logFileName, true);

                    // // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                    // // this portion is to test normal BFS with no subgoals
                    // // from last detailed state straight to current abstract

                    // var otherWatch = System.Diagnostics.Stopwatch.StartNew();

                    // TreeNode<WorldState> otherSolution = Utils.breadthFirstSearch(
                    //     _lastObservedStates[currentSimulationBoundary].Data, _currentNode.Data);
                    // otherWatch.Stop();

                    // long otherElapsedMs = otherWatch.ElapsedMilliseconds;

                    // writer.WriteLine("Normal BFS search time: " + otherElapsedMs + " ms\n");
                    // writer.WriteLine("Normal BFS search explored nodes: " + Utils.bfsExploredNodes + "\n");

                    // Stack<string> normalBFSSolution = new Stack<string>();
                    // while (otherSolution.IsRoot == false)
                    // {
                    //     normalBFSSolution.Push(otherSolution.ParentAction.ShortToString());
                    //     otherSolution = otherSolution.Parent;
                    // }

                    // string normalBFSSolutionInverse = "The solution found by the normal BFS is composed by the following actions:\n";
                    // while (normalBFSSolution.Count > 0)
                    //     normalBFSSolutionInverse += normalBFSSolution.Pop() + "\n";

                    // writer.WriteLine(normalBFSSolutionInverse);

                    // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

                    // roll back the simulation until we reach the root of the current level of detail
                    while (_currentNode.IsRoot == false)
                    {
                        _currentNode = _currentNode.Parent;
                    }

                    TreeNode <WorldState> lastNodeAtCurrentLevel = _lastObservedStates[currentSimulationBoundary];

                    int  expandedNodes        = 0;
                    long elapsedTimeForSearch = 0;


                    string s = "The solution found by the Subgoals BFS is composed by the following actions:\n";
                    // translate each action performed in the previous level of detail to an equivalent list of
                    // actions in the current level of detail. each translation is applied to the last observed
                    // state at current level of detail which in the end will be up to date.
                    while (_currentNode.IsLeaf == false)
                    {
                        // double desiredAccuracy = 1; // How accurate should be the translation 0 <= x <= 1
                        // int cutoff = 10;            // After how many levels we stop looking

                        _currentNode = _currentNode.Children.First();

                        var watch = System.Diagnostics.Stopwatch.StartNew();

                        TreeNode <WorldState> solution = Utils.breadthFirstSearch(lastNodeAtCurrentLevel.Data, _currentNode.Data);

                        watch.Stop();
                        long elapsedMs = watch.ElapsedMilliseconds;

                        expandedNodes        += Utils.bfsExploredNodes;
                        elapsedTimeForSearch += elapsedMs;

                        // Debug.Log("BFS time: " + elapsedMs + " ms");
                        // Debug.Log("BFS explored nodes: " + Utils.bfsExploredNodes);

                        s += "Abstract: ";
                        s += string.Join(", ", _currentNode.ParentAction.shortToString().ToArray());
                        s += "\n";

                        // solution is a leaf node we need to apply the actions in the reversed order (from root to leaf)
                        Queue <Action> sortedActions = new Queue <Action>();
                        while (solution.IsRoot == false)
                        {
                            // the bfs returns a game tree branch with ParentActions that contain only
                            // one Action since they're took from the domain and so are atomic.
                            // thus we can just enqueue the first action of the set
                            sortedActions.Enqueue(solution.ParentAction.First());
                            solution = solution.Parent;
                        }

                        // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                        // modify here

                        s += "Detailed All Sequetial:\n";

                        foreach (Action a in sortedActions.Reverse())
                        {
                            s += a.shortToString() + "\n";
                            lastNodeAtCurrentLevel = lastNodeAtCurrentLevel.AddChild(
                                lastNodeAtCurrentLevel.Data.applyAction(a), new HashSet <Action>()
                            {
                                a
                            }
                                );
                        }

                        // group actions depending on the entity which is performing it
                        Dictionary <ActionParameter, Queue <Action> > actionsForEachActor = Utils.explodeActionQueue(sortedActions);
                        // get a shallow list of entities which could be perform some actions
                        HashSet <Entity> activeActors = _currentNode.Data.getActiveEntities();

                        bool weStillHaveActionsToAssign          = true;
                        Queue <List <Action> > sequentialActions = new Queue <List <Action> >();

                        // we have to assign at least all the actions contained in the longest queue
                        // so, instead of iterating the dictionary to find out the longest one, we go on
                        // assigning actions until we get only NOOPS from all active entities
                        while (weStillHaveActionsToAssign)
                        {
                            weStillHaveActionsToAssign = false;
                            List <Action> parallelActions = new List <Action>();

                            // assign one action to each active entity
                            foreach (Entity e in activeActors)
                            {
                                Queue <Action>  actorActions;
                                ActionParameter activeActor = new ActionParameter(e, ActionParameterRole.ACTIVE);

                                // check if the current actor still has some action in the dictionary
                                bool actorIsDefined = actionsForEachActor.TryGetValue(activeActor, out actorActions);
                                // if it has some action then we put it in the parallel list for the current "turn"
                                // this resets the "weStillHaveActionsToAssign" check since some non trivial action was
                                // assigned
                                if (actorIsDefined && actorActions.Count > 0)
                                {
                                    parallelActions.Add(actorActions.Dequeue());
                                    weStillHaveActionsToAssign = true;
                                }
                                // if the actor has no action left in the dictionary then we assign a NOOP
                                else
                                {
                                    Action actionIdle = new Action(new HashSet <IRelation>(), "IDLE",
                                                                   new HashSet <ActionParameter>()
                                    {
                                        activeActor
                                    }, new HashSet <IRelation>());
                                    parallelActions.Add(actionIdle);
                                }
                            }

                            // if some non-trivial action was assigned then we enqueue
                            // the parallel actions in the current turn
                            if (weStillHaveActionsToAssign)
                            {
                                sequentialActions.Enqueue(parallelActions);
                            }
                        }

                        s += "Detailed Sequetial Lists of Parallel Actions:\n";
                        int i = 0;
                        foreach (List <Action> listOfParallelActions in sequentialActions)
                        {
                            s += "Turn [" + i + "]:\n";
                            i++;
                            foreach (Action a in listOfParallelActions)
                            {
                                s += a.shortToString() + "\n";
                            }
                        }
                        s += "\n";
                    }

                    writer.WriteLine(s);

                    _currentNode = lastNodeAtCurrentLevel;

                    writer.WriteLine("Subgoals BFS search time: " + elapsedTimeForSearch + " ms");
                    writer.WriteLine("Subgoals BFS search explored nodes: " + expandedNodes);

                    writer.Close();
                }
                // Abstraction
                else if (_currentLevelOfDetail < lastLoD)
                {
                    if (currentSimulationBoundary != null)
                    {
                        WorldState worldStateAbstract = parseToLevelOfDetail(_currentNode.Data, currentSimulationBoundary.domain);

                        // start a new path the old history is kept in lastObservedStates
                        _currentNode = new TreeNode <WorldState>(worldStateAbstract);
                    }
                    else
                    {
                        Debug.LogError("No domain in simulationBoundaries corresponds to this LoD");
                    }
                }
                lastLoD = _currentLevelOfDetail;
            }

            // this is the actual simulation, for now we just pick a random action
            // remember to use lastLoD while updating the lastObservedState because
            // in the meantime it could have changed
            HashSet <Action> parallelRandomActions = getRandomPossibleAction(_currentNode);

            if (parallelRandomActions == null || parallelRandomActions.Count <= 0)
            {
                Debug.Log("There are no more available actions, shutting down the simulation");
                break;
            }

            string chosenCombination = transform.parent.gameObject.name + "\n";
            foreach (Action a in parallelRandomActions)
            {
                chosenCombination += a.shortToString() + ", ";
            }
            chosenCombination = chosenCombination.Substring(0, chosenCombination.Length - 2);
            Debug.Log(chosenCombination);

            // Debug.Log("The Simulator is requesting the following Action: " + randomAction.ShortToString());

            bool simulationInteractive = getSimulationBoundaryAtLevel(lastLoD).interactive;
            if (simulationInteractive)
            {
                //Debug.Log("Player is interacting");

                bool result = false;
                yield return(StartCoroutine(visualizer.interact(parallelRandomActions, value => result = value)));

                if (result)
                {
                    // The action has been allowed, go next
                    // Debug.Log("Interactive Action Allowed");

                    WorldState resultingState = _currentNode.Data.applyParallelActions(parallelRandomActions);
                    _currentNode = _currentNode.AddChild(resultingState, parallelRandomActions);

                    setLastObservedStateAtLevel(lastLoD, _currentNode);
                }
                else
                {
                    // The action has been denied, roll back
                    // Debug.Log("Interactive Action Denied");
                }
            }
            else
            {
                //Debug.Log("Player is visualizing");
                //print("Visualization is requested by: " + transform.parent.name);
                bool result = false;
                yield return(StartCoroutine(visualizer.visualize(parallelRandomActions, value => result = value)));

                lastActionPerformed = parallelRandomActions.Last();
                if (result)
                {
                    // The action has been visualized, go next
                    // Debug.Log("Non Interactive Action Visualized");
                    WorldState resultingState = _currentNode.Data.applyParallelActions(parallelRandomActions);
                    _currentNode = _currentNode.AddChild(resultingState, parallelRandomActions);

                    setLastObservedStateAtLevel(lastLoD, _currentNode);
                }
                else
                {
                    // The were some problems with the visualization, roll back
                    // Debug.Log("Non Interactive Action NOT Visualized");
                }
            }

            yield return(null);
        }
    }