// Get the set of exceptional and constituent edges. public static List <StateSpaceEdge> GetPossibleActions(Domain domain, Problem problem, Plan plan, State state) { // Make the set of outgoing edges. List <StateSpaceEdge> actions = new List <StateSpaceEdge>(); // Find the current constituent action. StateSpaceEdge constituent = GetConstituentAction(domain, problem, plan, state); // Add the constituent action to the possible actions. actions.Add(constituent); // Find and add the current exceptional actions. List <StateSpaceEdge> exceptionals = GetExceptionalActions(domain, problem, plan, state); // Remove any exceptional actions that correspond to the constituent step. foreach (StateSpaceEdge exception in exceptionals) { if (!exception.Action.Equals(constituent.Action)) { actions.Add(exception); } } // Return the outgoing edges. return(actions); }
public StateSpaceNode(StateSpaceNode parent, StateSpaceEdge incoming, State state) { this.parent = parent; this.incoming = incoming; systemActions = new List <IOperator>(); this.state = state; outgoing = new List <StateSpaceEdge>(); children = new Hashtable(); plan = new Plan(); problem = new Problem(); domain = new Domain(); id = System.Threading.Interlocked.Increment(ref Counter); satisfiesGoal = false; }
public StateSpaceNode() { parent = null; incoming = null; systemActions = new List <IOperator>(); state = new State(); outgoing = new List <StateSpaceEdge>(); children = new Hashtable(); plan = new Plan(); problem = new Problem(); domain = new Domain(); id = System.Threading.Interlocked.Increment(ref Counter); satisfiesGoal = false; }
// Creates a list of all possible things the player can do. public static List <StateSpaceEdge> GetAllPossibleActions(Domain domain, Problem problem, Plan plan, State state) { // Create a list of possible player actions in the current state. List <Operator> possibleActions = GetPlayerActions(domain, problem, state); // Create a list of the causal links that span the state. List <CausalLink> spanningLinks = (List <CausalLink>)GetSpanningLinks(plan); // Create an empty list of exceptional actions. List <StateSpaceEdge> exceptionalActions = new List <StateSpaceEdge>(); // Store the exceptional actions to be removed later. List <Operator> exceptions = new List <Operator>(); // Store exceptional effects. Hashtable exceptionalEffects = new Hashtable(); // Loop through every possible action. foreach (Operator action in possibleActions) { // Loop through every action's effects. foreach (Predicate effect in action.Effects) { // Loop through every spanning link. foreach (CausalLink link in spanningLinks) { // If the effect is the inverse of the protected predicate... if (effect.IsInverse(link.Predicate)) { // Identify the exceptional effect. if (exceptionalEffects.ContainsKey(action.Predicate.ToString())) { List <IPredicate> list = exceptionalEffects[action.Predicate.ToString()] as List <IPredicate>; list.Add(effect.Clone() as Predicate); exceptionalEffects[action.Predicate.ToString()] = list; } else { exceptionalEffects[action.Predicate.ToString()] = new List <IPredicate> { effect.Clone() as Predicate } }; // Add the current action to the list of exceptional actions. exceptionalActions.Add(new StateSpaceEdge(action.Clone() as Operator, ActionType.Exceptional)); // Add the actual action to the exception list. exceptions.Add(action); } } } //Loop through the action's axioms foreach (IAxiom conditional in state.ApplicableConditionals(action, problem.Objects)) { // Loop through every conditional's effects. foreach (IPredicate effect in conditional.Effects) { // Loop through every spanning link. foreach (IDependency link in spanningLinks) { // If the effect is the inverse of the protected predicate... if (effect.IsInverse(link.Predicate)) { // Identify the exceptional effect. if (exceptionalEffects.ContainsKey(action.Predicate.ToString())) { List <IPredicate> list = exceptionalEffects[action.Predicate.ToString()] as List <IPredicate>; list.Add(effect.Clone() as Predicate); exceptionalEffects[action.Predicate.ToString()] = list; } else { exceptionalEffects[action.Predicate.ToString()] = new List <IPredicate> { effect.Clone() as Predicate } }; // Add the current action to the list of exceptional actions. exceptionalActions.Add(new StateSpaceEdge(action.Clone() as Operator, ActionType.Exceptional)); // Add the actual action to the exception list. exceptions.Add(action); } } } } } // Remove the exceptions from the possible actions. foreach (Operator exception in exceptions) { possibleActions.Remove(exception); } // This is a hack to remove duplicate exceptional actions with a Remove By Property method. List <int> remove = new List <int>(); // Remove duplicate actions. for (int i = 0; i < exceptionalActions.Count - 1; i++) { for (int j = i + 1; j < exceptionalActions.Count; j++) { if (exceptionalActions[i].Action.Equals(exceptionalActions[j].Action)) { remove.Add(j); } } } for (int i = exceptionalActions.Count - 1; i >= 0; i--) { if (remove.Contains(i)) { exceptionalActions.RemoveAt(i); } else { exceptionalActions[i].Action.ExceptionalEffects = exceptionalEffects[exceptionalActions[i].Action.Predicate.ToString()] as List <IPredicate>; } } // Create an empty list of consistent actions. List <StateSpaceEdge> consistentActions = new List <StateSpaceEdge>(); // Loop through the remaining actions. foreach (Operator action in possibleActions) { // Add the current action to the list of consistent actions. consistentActions.Add(new StateSpaceEdge(action.Clone() as Operator, ActionType.Consistent)); } // Make the set of outgoing edges. List <StateSpaceEdge> actions = new List <StateSpaceEdge>(); // Find the current constituent action. StateSpaceEdge constituent = GetConstituentAction(domain, problem, plan, state); // Add the constituent action to the possible actions. actions.Add(constituent); // Remove any exceptional actions that correspond to the constituent step. foreach (StateSpaceEdge exception in exceptionalActions) { if (!exception.Action.Equals(constituent.Action)) { actions.Add(exception); } } // Remove any exceptional actions that correspond to the constituent step. foreach (StateSpaceEdge consistent in consistentActions) { if (!consistent.Action.Equals(constituent.Action)) { actions.Add(consistent); } } // Return the outgoing edges. return(actions); }
// Creates a child node. private static StateSpaceNode CreateChild(Planner planner, Domain domain, Problem problem, Plan plan, State state, StateSpaceEdge edge) { // Create a new problem object. Problem newProblem = new Problem(); // Create a new domain object. Domain newDomain = domain; // Create a new plan object. Plan newPlan = new Plan(); // Store actions the system takes. List <IOperator> systemActions = new List <IOperator>(); // If the outgoing action is an exceptional step... if (edge.ActionType == ActionType.Exceptional) { // Count the exceptional edge. Exceptional++; // Create a new problem object. newProblem = NewProblem(newDomain, problem, state, edge.Action); // Find a new plan. newPlan = PlannerInterface.Plan(planner, newDomain, newProblem); // If the action was accommodated and the first step of the new plan isn't taken by the player... if (newPlan.Steps.Count > 0) { // Add the action to the system action list. systemActions = GetSystemActions(newPlan, new List <string> { problem.Player }, new List <IOperator>()); // Update the problem object with the system's next move. newProblem = NewProblem(newDomain, newProblem, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), systemActions); // Update the plan with the system's next move. newPlan = newPlan.GetPlanUpdate(newProblem, systemActions); } else if (CEDeletion) { // Try to find a domain revision alibi. Tuple <Domain, Operator> alibi = ReviseDomain(planner, newDomain, problem, state, edge.Action as Operator); // If domain revision worked. if (alibi != null) { // Remember the new domain. newDomain = alibi.First; // Push the modified action to the edge object. edge.Action = alibi.Second; // Create a new problem object. newProblem = NewProblem(newDomain, problem, state, edge.Action); // Find a new plan. newPlan = PlannerInterface.Plan(planner, newDomain, newProblem); // Add the action to the system action list. systemActions = GetSystemActions(newPlan, new List <string> { problem.Player }, new List <IOperator>()); // Update the problem object with the system's next move. newProblem = NewProblem(newDomain, newProblem, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), systemActions); // Update the plan with the system's next move. newPlan = newPlan.GetPlanUpdate(newProblem, systemActions); } } } // Otherwise, if the action is a consistent step... else if (edge.ActionType == ActionType.Consistent) { // Count the consistent edge. Consistent++; // Create a new problem object. newProblem = NewProblem(newDomain, problem, state, edge.Action); // Add the action to the system action list. systemActions = GetSystemActions(plan, new List <string> { problem.Player }, new List <IOperator>()); // Create a new state. State newState = new State(newProblem.Initial, state.nextStep, (Operator)plan.Steps.First()); // Create a new problem object. newProblem = NewProblem(newDomain, newProblem, newState, systemActions); // Create a new plan. newPlan = plan.GetPlanUpdate(newProblem, systemActions); } // Otherwise, the action is a constituent step... else { // Count the constituent edge. Constituent++; // If there are effects of the constituent action... if (edge.Action.Effects.Count > 0) { // Create a new problem object. newProblem = NewProblem(newDomain, problem, state, edge.Action); // Create a new plan. newPlan = plan.GetPlanUpdate(newProblem, edge.Action as Operator); } // Otherwise, initialize to the old problem and plan... else { newProblem = problem; newPlan = plan.Clone() as Plan; } // If there are still plan actions... if (newPlan.Steps.Count > 0) { // Add the action to the system action list. systemActions = GetSystemActions(newPlan, new List <string> { problem.Player }, new List <IOperator>()); // Update the problem object with the system's next move. newProblem = NewProblem(newDomain, newProblem, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), systemActions); // Update the plan with the system's next move. newPlan = newPlan.GetPlanUpdate(newProblem, systemActions); } } // Add the system actions to the current edge. edge.SystemActions = systemActions; // Create an empty child node. StateSpaceNode child = null; // If there are remaining plan steps... if (newPlan.Steps.Count > 0) { // Build a new tree using the first step of the plan as the next step. child = StateSpaceSearchTools.CreateNode(planner, newDomain, newProblem, newPlan, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First())); } else { // Terminate the tree by adding a goal node. child = StateSpaceSearchTools.CreateNode(planner, newDomain, newProblem, newPlan, new State(newProblem.Initial, newPlan.InitialStep, newPlan.GoalStep)); } // Store the system actions. child.systemActions = systemActions; // Record the action that triggered the node's generation. child.incoming = edge; return(child); }
// Rewrites history to remove harmful conditional effects. public static StateSpaceNode RemoveConditionalEffects(Planner planner, Domain domain, Problem problem, Plan plan, State state, StateSpaceEdge edge, int depth) { // Store the incoming action. Operator incoming = edge.Action as Operator; // Create a new plan object. Plan newPlan = new Plan(); // Examine each exceptional effect. foreach (Predicate effect in incoming.ExceptionalEffects) { // Create a new domain object. Domain newDomain = new Domain(); // Save the domain's name. newDomain.Name = domain.Name; newDomain.staticStart = domain.staticStart; // If the current effect is conditional... if (incoming.IsConditional(effect)) { // If the conditional effect has not been observed by the player. // Remove the conditional effect from the domain. // Copy the current operator templates into a list. List <IOperator> templates = new List <IOperator>(); foreach (IOperator templ in 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; // Write new problem and domain files. Writer.ProblemToPDDL(Parser.GetTopDirectory() + @"Benchmarks/" + domain.Name.ToLower() + @"/probrob.pddl", newDomain, problem, state.Predicates); Writer.DomainToPDDL(Parser.GetTopDirectory() + @"Benchmarks/" + domain.Name.ToLower() + @"/domrob.pddl", newDomain); // Find a new plan. if (planner.Equals(Planner.FastDownward)) { newPlan = FastDownward.Plan(newDomain, problem); } else if (planner.Equals(Planner.Glaive)) { newPlan = Glaive.Plan(newDomain, problem); } // If the modified domain can accommodate the player's action... if (newPlan.Steps.Count > 0) { // 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; // Push the modified action to the edge object. edge.Action = newAction; // Expand the tree using the new domain. return(ExpandTree(planner, newDomain, problem, plan, state, edge, depth)); } } } return(null); }
// Rewrites history using alibi generation. public static StateSpaceNode GenerateAlibi(Planner planner, Domain domain, Problem problem, Plan plan, State state, StateSpaceEdge edge, int depth) { return(RemoveConditionalEffects(planner, domain, problem, plan, state, edge, depth)); }
// Expand an edge. public static StateSpaceNode ExpandTree(Planner planner, Domain domain, Problem problem, Plan plan, State state, StateSpaceEdge edge, int depth) { // Create a new problem object. Problem newProblem = new Problem(); // Create a new plan object. Plan newPlan = new Plan(); // Store actions the system takes. List <IOperator> systemActions = new List <IOperator>(); // If the action is an exceptional step... if (edge.ActionType == ActionType.Exceptional) { // Count the exceptional edge. Exceptional++; // Create a new problem object. newProblem = NewProblem(domain, problem, state, edge.Action); // Find a new plan. newPlan = PlannerInterface.Plan(planner, domain, newProblem); // If the action was accommodated and the first step of the new plan isn't taken by the player... if (newPlan.Steps.Count > 0) { // Add the action to the system action list. systemActions = GetSystemActions(newPlan, new List <string> { problem.Player }, new List <IOperator>()); // Update the problem object with the system's next move. newProblem = NewProblem(domain, newProblem, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), systemActions); // Update the plan with the system's next move. newPlan = newPlan.GetPlanUpdate(newProblem, systemActions); } else if (CEDeletion) { StateSpaceNode alibi = GenerateAlibi(planner, domain, problem, plan, state, edge, depth); if (alibi != null) { return(alibi); } } } // Otherwise, if the action is a consistent step... else if (edge.ActionType == ActionType.Consistent) { // Count the consistent edge. Consistent++; // Create a new problem object. newProblem = NewProblem(domain, problem, state, edge.Action); // Add the action to the system action list. systemActions = GetSystemActions(plan, new List <string> { problem.Player }, new List <IOperator>()); // Create a new state. State newState = new State(newProblem.Initial, state.nextStep, (Operator)plan.Steps.First()); // Create a new problem object. newProblem = NewProblem(domain, newProblem, newState, systemActions); // Create a new plan. newPlan = plan.GetPlanUpdate(newProblem, systemActions); } // Otherwise, the action is a constituent step... else { // Count the constituent edge. Constituent++; // If there are effects of the constituent action... if (edge.Action.Effects.Count > 0) { // Create a new problem object. newProblem = NewProblem(domain, problem, state, edge.Action); // Create a new plan. newPlan = plan.GetPlanUpdate(newProblem, edge.Action as Operator); } // Otherwise, initialize to the old problem and plan... else { newProblem = problem; newPlan = plan.Clone() as Plan; } // If there are still plan actions... if (newPlan.Steps.Count > 0) { // Add the action to the system action list. systemActions = GetSystemActions(newPlan, new List <string> { problem.Player }, new List <IOperator>()); // Update the problem object with the system's next move. newProblem = NewProblem(domain, newProblem, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), systemActions); // Update the plan with the system's next move. newPlan = newPlan.GetPlanUpdate(newProblem, systemActions); } } // Add the system actions to the current edge. edge.SystemActions = systemActions; // Create an empty child node. StateSpaceNode child = null; // If there are remaining plan steps... if (newPlan.Steps.Count > 0) { // Build a new tree using the first step of the plan as the next step. child = BuildTree(planner, domain, newProblem, newPlan, new State(newProblem.Initial, newPlan.InitialStep, (Operator)newPlan.Steps.First()), depth - 1); } else { // Terminate the tree by adding a goal node. child = BuildTree(planner, domain, newProblem, newPlan, new State(newProblem.Initial, newPlan.InitialStep, newPlan.GoalStep), depth - 1); } // Store the system actions. child.systemActions = systemActions; // Record the action that triggered the node's generation. child.incoming = edge; return(child); }