/// <summary> /// Given a planner, a mediation tree node, and a mediation tree, return an event revision plan and state to set for the node. /// </summary> /// <param name="planner">The planner to use.</param> /// <param name="node">The current node in the mediation tree.</param> /// <param name="tree">The mediation tree.</param> /// <returns>A plan state pair for the current node.</returns> public static void EventRevision(Planner planner, MediationTreeNode node, MediationTree tree) { // Compute the event revision problem and domain for the current node. Tuple <Domain, Problem> pair = GetEventRevisionPair(node, tree); // Use the planner to find an event revision plan. Plan plan = PlannerInterface.Plan(planner, pair.First, pair.Second); if (plan.Steps.Count > 0) { Tuple <Plan, State> planState = GetPlanStatePair(plan, node, tree); node.Plan = planState.First; node.State = planState.Second; node.Problem.Initial = node.State.Predicates; } }
public static void DomainRevision(Planner planner, MediationTreeNode node, MediationTree tree) { // Store the incoming action. Operator incoming = node.Incoming.Action as Operator; // Create a new plan object. Plan newPlan = new Plan(); List <Tuple <Operator, State> > knowledge = EventRevisor.GetWorldKnowledge(tree.Player, node, tree); knowledge.RemoveAt(knowledge.Count - 1); List <Operator> observedActions = new List <Operator>(); foreach (Tuple <Operator, State> pair in knowledge) { if (pair.First != null) { if (pair.First.Name.Equals(incoming.Name)) { observedActions.Add(pair.First); } } } // Examine each exceptional effect. foreach (Predicate effect in incoming.ExceptionalEffects) { // Create a new domain object. Domain newDomain = node.Domain.Clone() as Domain; newDomain.Operators = new List <IOperator>(); // If the current effect is conditional... if (incoming.IsConditional(effect)) { bool observed = false; // If the conditional effect has not been observed by the player. foreach (Operator action in observedActions) { if (!observed) { foreach (IAxiom conditional in action.Conditionals) { if (conditional.Effects.Contains(effect) && !observed) { observed = true; } } } } // Remove the conditional effect from the domain. if (!observed) { // Copy the current operator templates into a list. List <IOperator> templates = new List <IOperator>(); foreach (IOperator templ in node.Domain.Operators) { templates.Add(templ.Clone() as IOperator); } // Create a clone of the incoming action's unbound operator template. IOperator temp = incoming.Template() as Operator; // Find the incoming action template in the domain list. Operator template = templates.Find(t => t.Equals(temp)) as Operator; // Remove the incoming action template from the domain list. templates.Remove(template); // Create a clone of the incoming action. Operator clone = incoming.Clone() as Operator; // Create a list of conditional effects to remove from the template. List <IAxiom> remove = new List <IAxiom>(); foreach (IAxiom conditional in clone.Conditionals) { if (conditional.Effects.Contains(effect)) { remove.Add(conditional); } } // Remove each conditional effect from the template. foreach (IAxiom rem in remove) { template.Conditionals.Remove(rem.Template() as IAxiom); } // Add the modified template to the domain list. templates.Add(template); // Push the modified list to the new domain object. newDomain.Operators = templates; // Clone the modified incoming action template. Operator newAction = template.Clone() as Operator; // Bind the cloned action with the incoming action's bindings. newAction.Bindings = incoming.Bindings; MediationTreeEdge newEdge = new MediationTreeEdge(newAction, ActionType.Exceptional, node.Incoming.Parent, node.ID); Problem newProblem = node.Problem.Clone() as Problem; newProblem.Initial = tree.GetSuccessorState(newEdge).Predicates; // Find a new plan. newPlan = PlannerInterface.Plan(planner, newDomain, newProblem); // If the modified domain can accommodate the player's action... if (newPlan.Steps.Count > 0) { node.Plan = newPlan; node.Incoming.Action = newAction; node.State = tree.GetSuccessorState(node.Incoming); node.Domain = newDomain; } } } } }
/// <summary> /// Given an event revision plan, a mediation tree node, and a mediation tree, returns the plan and state to set in the node. /// </summary> /// <param name="plan">The full event revision plan from the original initial state.</param> /// <param name="node">The current node in the mediation tree.</param> /// <param name="tree">The mediation tree object.</param> /// <returns>The current state to set in the node after event revision and the plan from the state forward.</returns> public static Tuple <Plan, State> GetPlanStatePair(Plan plan, MediationTreeNode node, MediationTree tree) { // Reformat the event revision plan to get a regular plan. Plan formattedPlan = ReformatPlan(plan, tree.Root.Domain, tree.Root.Problem); // Create a list to hold event revision steps. List <IOperator> pastSteps = new List <IOperator>(); // Create another list to hold future plan steps. List <IOperator> futureSteps = new List <IOperator>(); // Loop through the steps in the formatted event revision plan... for (int i = 0; i < formattedPlan.Steps.Count; i++) { // If the step happened before the current state, it is an event revision step. if (i < node.Depth) { pastSteps.Add(formattedPlan.Steps[i]); } // If the step happens at or after the current state, it is a future plan step. else { futureSteps.Add(formattedPlan.Steps[i]); } } // Create a new state object by cloning the initial state of the original planning problem. State current = tree.Root.State.Clone() as State; // Loop through each of the event revision steps... foreach (IOperator step in pastSteps) { // And update the state object by applying the action. current = new State(current.ApplyAction(step as Operator, node.Problem.Objects)); } // Return the future plan along with the computed state. return(new Tuple <Plan, State>(new Plan(node.Domain, node.Problem, futureSteps), current)); }
/// <summary> /// Given a character, node, and tree, returns the character's knowledge of the world history. /// </summary> /// <param name="character">The character.</param> /// <param name="node">The node that corresponds to the current state.</param> /// <param name="tree">The mediation tree.</param> /// <returns>A list of action-state pairs that represent what the character knows.</returns> public static List <Tuple <Operator, State> > GetWorldKnowledge(string character, MediationTreeNode node, MediationTree tree) { // An object to hold the character's knowledge of the world history. List <Tuple <Operator, State> > knowledge = new List <Tuple <Operator, State> >(); // Get the objective world history. List <MediationTreeNode> history = GetWorldHistory(node, tree); // Loop through the nodes in the world history branch... foreach (MediationTreeNode current in history) { // Create a new action. Operator action = null; // Make sure the current node is not the root. if (current.Incoming != null) { // Check if the character observes the incoming action. if (KnowledgeAnnotator.Observes(character, current.Incoming.Action, current.State.Predicates)) { // If so, remember that the character observed the action. action = current.Incoming.Action.Clone() as Operator; } } // Create a new state consisting only of terms the character observed. State state = new State(KnowledgeAnnotator.FullKnowledgeState(tree.Root.Domain.Predicates, tree.Root.Problem.ObjectsByType, current.State.Predicates, character)); // Store the observed action-state pair as a tuple. knowledge.Add(new Tuple <Operator, State>(action, state)); } // Return the sequence of observed action-state pairs. return(knowledge); }
/// <summary> /// Given a mediation tree and a node in the tree, returns the node's world history. /// </summary> /// <param name="node">The node.</param> /// <param name="tree">The tree.</param> /// <returns>The path through the tree from the root to the node.</returns> public static List <MediationTreeNode> GetWorldHistory(MediationTreeNode node, MediationTree tree) { // Create an empty list object to hold the history. List <MediationTreeNode> history = new List <MediationTreeNode>(); // Add the node to the world history. history.Add(node); // Remember the current node's ID. int current = node.ID; // While the current node's parent is not null... while (tree.GetParent(current) != -1) { // Store the current node's parent object. MediationTreeNode parent = tree.GetNode(tree.GetParent(current)); // Remember the parent's ID. current = parent.ID; // Insert the parent node into the world history. history.Insert(0, parent); } // Return the world history. return(history); }
/// <summary> /// Given a mediation tree and a node in the tree, returns a event revision domain and problem. /// </summary> /// <param name="node">The mediation tree node.</param> /// <param name="tree">The mediation tree.</param> /// <returns>The event revision problem and domain for the node.</returns> public static Tuple <Domain, Problem> GetEventRevisionPair(MediationTreeNode node, MediationTree tree) { // Create a clone of the node's original domain. Domain revisionDomain = node.Domain.Clone() as Domain; // Create a clone of the node's original problem. Problem revisionProblem = tree.Root.Problem.Clone() as Problem; // Get the series of actions and state literals the player has observed. List <Tuple <Operator, State> > playerKnowledge = GetWorldKnowledge(tree.Player, node, tree); // Rename the problem to the automated slot. revisionProblem.Name = "rob"; // Add the initial state tracking literal to the problem's initial state. revisionProblem.Initial.Add(new Predicate("state-depth", new List <ITerm> { new Term("depth1", true) }, true)); revisionDomain.AddTypePair("depth", "state"); revisionDomain.Predicates.Add(new Predicate("state-depth", new List <ITerm> { new Term("?depth", "", "state") }, true)); // For every operator in the cloned domain... foreach (Operator op in revisionDomain.Operators) { // Add a state tracking precondition that prevents it from being applied until after the event revision operations have been performed. op.Preconditions.Add(new Predicate("state-depth", new List <ITerm> { new Term("depth" + playerKnowledge.Count.ToString(), true) }, true)); } // Loop through the action-state pairs in the player knowledge. for (int i = 1; i < playerKnowledge.Count; i++) { // For each of these, add a new state tracker to the list of objects. revisionProblem.Objects.Add(new Obj("depth" + i.ToString(), "depth")); // If the player did not observed the current action, add a set of unobserved templates to the list of operators. if (playerKnowledge[i].First == null) { revisionDomain.Operators.AddRange(GetUnobservedActionTemplates(i, tree.GetTurnAtIndex(i - 1), node.Domain, playerKnowledge[i - 1].Second)); } // If the player did observe the current action, add the observed template to the list of operators. else { revisionDomain.Operators.Add(GetObservedActionTemplate(i, playerKnowledge[i].First)); } } // Add the final state tracking object to the problem. revisionProblem.Objects.Add(new Obj("depth" + playerKnowledge.Count.ToString(), "depth")); // Return the domain-problem pair. return(new Tuple <Domain, Problem> (revisionDomain, revisionProblem)); }