public static void FromOperator(IOperator op) { var permList = new List <List <IObject> >(); foreach (Term variable in op.Terms) { permList.Add(typeDict[variable.Type] as List <IObject>); } foreach (var combination in EnumerableExtension.GenerateCombinations(permList)) { // Add bindings var opClone = op.Clone() as Operator; var termStringList = from term in opClone.Terms select term.Variable; var constantStringList = from objConst in combination select objConst.Name; opClone.AddBindings(termStringList.ToList(), constantStringList.ToList()); var legal = true; foreach (var precon in opClone.Preconditions) { if (!NonStaticPredicates.Contains(precon.Name)) { // this predicate is static if (!Init.Contains(precon)) { legal = false; break; } } } if (!legal) { continue; } // this ensures that this ground operator has a unique ID var groundOperator = new Operator(opClone.Name, opClone.Terms, opClone.Bindings, opClone.Preconditions, opClone.Effects); if (GroundLibrary.ContainsKey(groundOperator.ID)) { throw new System.Exception(); } GroundActions.Add(groundOperator as IOperator); GroundLibrary[groundOperator.ID] = groundOperator; } }
public static List <IOperator> FromOperatorWithReturn(IOperator op) { var listToReturn = new List <IOperator>(); var permList = new List <List <string> >(); foreach (Term variable in op.Terms) { permList.Add(TypeDict[variable.Type] as List <string>); } foreach (var combination in EnumerableExtension.GenerateCombinations(permList)) { // Add bindings var opClone = op.Clone() as Operator; var termStringList = from term in opClone.Terms select term.Variable; var constantStringList = combination; opClone.AddBindings(termStringList.ToList(), constantStringList.ToList()); if (!opClone.NonEqualTermsAreNonequal()) { continue; } //Debug.Log("operator: " + opClone.ToString()); // this ensures that this ground operator has a unique ID var groundOperator = new Operator(opClone.Name, opClone.Terms, opClone.Bindings, opClone.Preconditions, opClone.Effects); if (GroundActionFactory.GroundActions.Contains(groundOperator)) { continue; } if (GroundLibrary.ContainsKey(groundOperator.ID)) { throw new System.Exception(); } InsertOperator(groundOperator as IOperator); listToReturn.Add(groundOperator as IOperator); } return(listToReturn); }
/// <summary> /// The Decomposition is composed of a sub-plan with at least sub-step at height "height" /// </summary> /// <returns>A list of decompositions with ground terms and where each sub-step is ground. </returns> public List <Decomposition> Compose(int height) { /////////////////////////////////////// // START BY ADDING BINDINGS TO TERMS // /////////////////////////////////////// var permList = new List <List <string> >(); foreach (Term variable in Terms) { permList.Add(GroundActionFactory.TypeDict[variable.Type] as List <string>); } var decompList = new List <Decomposition>(); foreach (var combination in EnumerableExtension.GenerateCombinations(permList)) { // Add bindings var decompClone = Clone() as Decomposition; var termStringList = from term in decompClone.Terms select term.Variable; var constantStringList = combination; decompClone.AddBindings(termStringList.ToList(), constantStringList.ToList()); ///////////////////////////////////////////////////////// // PROPAGATE BINDINGS TO NONEQUALITY CONSTRAINTS ///////////////////////////////////////////////////////// var newNonEqualities = new List <List <ITerm> >(); foreach (var nonequals in NonEqualities) { var newNonEquals = new List <ITerm>(); newNonEquals.Add(decompClone.Terms.First(dterm => dterm.Variable.Equals(nonequals[0].Variable))); newNonEquals.Add(decompClone.Terms.First(dterm => dterm.Variable.Equals(nonequals[1].Variable))); newNonEqualities.Add(newNonEquals); } decompClone.NonEqualities = newNonEqualities; if (!decompClone.NonEqualTermsAreNonequal()) { continue; } // zip to dict var varDict = EnumerableExtension.Zip(termStringList, constantStringList).ToDictionary(x => x.Key, x => x.Value); ///////////////////////////////////////////////////////// // BINDINGS ARE ADDED. NEED TO APPLY BINDINGS TO SUBSTEPS ///////////////////////////////////////////////////////// // Need to propagate bindings to sub-steps foreach (var substep in decompClone.SubSteps) { var op = substep.Action as Operator; foreach (var term in substep.Terms) { op.AddBinding(term.Variable, varDict[term.Variable]); } foreach (var precon in substep.Preconditions) { foreach (var term in precon.Terms) { if (!term.Bound) { var decompTerm = decompClone.Terms.First(dterm => dterm.Variable.Equals(term.Variable)); op.Terms.Add(term); op.AddBinding(term.Variable, decompTerm.Constant); } } } foreach (var eff in substep.Effects) { foreach (var term in eff.Terms) { if (!term.Bound) { var decompTerm = decompClone.Terms.First(dterm => dterm.Variable.Equals(term.Variable)); op.Terms.Add(term); op.AddBinding(term.Variable, decompTerm.Constant); } } } } //////////////////////////////////////////////////////////////// // FILTER CANDIDATES FOR SUBSTEPS AND PASS BACK GROUNDED DECOMPS //////////////////////////////////////////////////////////////// var newGroundDecomps = FilterDecompCandidates(decompClone, height); foreach (var gdecomp in newGroundDecomps) { decompList.Add(gdecomp); } //Console.WriteLine("Check"); } return(decompList); }
/// <summary> /// Filters candidates for substeps, at least one with height "height" /// </summary> /// <param name="decomp"></param> /// <returns> List of decompositions with ground sub-steps. </returns> public static List <Decomposition> FilterDecompCandidates(Decomposition decomp, int height) { // find and replace sub-steps var comboList = new List <List <IOperator> >(); var ID_List = new List <int>(); foreach (var substep in decomp.SubSteps) { ID_List.Add(substep.ID); // each substep has ground terms that are already consistent. Composite IS-A Operator var cndts = ConsistentSteps(substep.Action as Operator); // If there's no cndts for this substep, then abandon this decomp. if (cndts.Count == 0) { return(new List <Decomposition>()); } comboList.Add(cndts); } List <Decomposition> decompList = new List <Decomposition>(); foreach (var combination in EnumerableExtension.GenerateCombinations(comboList)) { var decompClone = decomp.Clone() as Decomposition; var newSubsteps = new List <IPlanStep>(); var substepDict = new Dictionary <int, IPlanStep>(); var order = 0; var hasPrerequisiteHeight = false; foreach (var item in combination) { if (item.Height >= height) { // meets height requirement hasPrerequisiteHeight = true; } var originalID = ID_List[order++]; if (item.Height > 0) { var newPlanStep = new CompositePlanStep(item as Composite); substepDict[originalID] = newPlanStep; newSubsteps.Add(newPlanStep); } else { var newPlanStep = new PlanStep(item); substepDict[originalID] = newPlanStep; newSubsteps.Add(newPlanStep); } } // Did not meet requirements for height. if (!hasPrerequisiteHeight) { continue; } var newSuborderings = new List <Tuple <IPlanStep, IPlanStep> >(); foreach (var subordering in decomp.SubOrderings) { var first = substepDict[subordering.First.ID]; var second = substepDict[subordering.Second.ID]; newSuborderings.Add(new Tuple <IPlanStep, IPlanStep>(first, second)); } var linkWorlds = new List <List <CausalLink <IPlanStep> > >(); linkWorlds.Add(new List <CausalLink <IPlanStep> >()); var newSublinks = new List <CausalLink <IPlanStep> >(); foreach (var sublink in decomp.SubLinks) { var head = substepDict[sublink.Head.ID]; var tail = substepDict[sublink.Tail.ID]; var cndts = head.Effects.Where(eff => eff.IsConsistent(sublink.Predicate) && tail.Preconditions.Any(pre => pre.Equals(eff))); //// swap tall members //if (head.Height > 0) //{ // var Chead = head as CompositePlanStep; // head = Chead.GoalStep; //} //if (tail.Height > 0) //{ // var Ctail = tail as CompositePlanStep; // tail = Ctail.InitialStep; //} if (cndts.Count() == 0) { // forfeit this entire subplan linkWorlds = new List <List <CausalLink <IPlanStep> > >(); continue; } if (cndts.Count() == 1) { var cndt = cndts.First(); var dependency = cndt.Clone() as Predicate; var newLink = new CausalLink <IPlanStep>(dependency, head, tail); newLink.Tail.Fulfill(cndt); foreach (var linkworld in linkWorlds) { linkworld.Add(newLink); } } else { foreach (var cndt in cndts) { var dependency = cndt.Clone() as Predicate; var newLink = new CausalLink <IPlanStep>(dependency, head, tail); newLink.Tail.Fulfill(cndt); var clonedLinks = EnumerableExtension.CloneList(newSublinks); linkWorlds.Add(clonedLinks); foreach (var linkworld in linkWorlds) { linkworld.Add(newLink); } } } } foreach (var linkworld in linkWorlds) { var newDecomp = decomp.Clone() as Decomposition; newDecomp.SubSteps = newSubsteps; newDecomp.SubOrderings = newSuborderings; newDecomp.SubLinks = linkworld; decompList.Add(newDecomp); } } return(decompList); }
// difference between this and overrided method is that this packages list of decompositions with a substep dictionary int -> replaced plan step public static List <Tuple <TimelineDecomposition, Dictionary <int, IPlanStep> > > FilterDecompCandidates(TimelineDecomposition decomp) { // find and replace sub-steps var comboList = new List <List <IOperator> >(); var ID_List = new List <int>(); foreach (var substep in decomp.SubSteps) { ID_List.Add(substep.ID); // each substep has ground terms that are already consistent. Composite IS-A Operator var cndts = ConsistentSteps(substep.Action as Operator); // If there's no cndts for this substep, then abandon this decomp. if (cndts.Count == 0) { return(new List <Tuple <TimelineDecomposition, Dictionary <int, IPlanStep> > >()); } comboList.Add(cndts); } // update to this method is to track, for each decomposition, which number substep goes to which grounded plan step List <Tuple <TimelineDecomposition, Dictionary <int, IPlanStep> > > decompMap = new List <Tuple <TimelineDecomposition, Dictionary <int, IPlanStep> > >(); foreach (var combination in EnumerableExtension.GenerateCombinations(comboList)) { var decompClone = decomp.Clone() as TimelineDecomposition; var newSubsteps = new List <IPlanStep>(); var substepDict = new Dictionary <int, IPlanStep>(); var order = 0; foreach (var item in combination) { var originalID = ID_List[order++]; var newPlanStep = new PlanStep(item); substepDict[originalID] = newPlanStep; newSubsteps.Add(newPlanStep); } var newSuborderings = new List <Tuple <IPlanStep, IPlanStep> >(); foreach (var subordering in decomp.SubOrderings) { var first = substepDict[subordering.First.ID]; var second = substepDict[subordering.Second.ID]; newSuborderings.Add(new Tuple <IPlanStep, IPlanStep>(first, second)); } var linkWorlds = new List <List <CausalLink <IPlanStep> > >(); linkWorlds.Add(new List <CausalLink <IPlanStep> >()); var newSublinks = new List <CausalLink <IPlanStep> >(); foreach (var sublink in decomp.SubLinks) { var head = substepDict[sublink.Head.ID]; var tail = substepDict[sublink.Tail.ID]; List <IPredicate> cndts = new List <IPredicate>(); //var cndts = head.Effects.Where(eff => eff.IsConsistent(sublink.Predicate) && tail.Preconditions.Any(pre => pre.Equals(eff))); foreach (var eff in head.Effects) { foreach (var pre in tail.Preconditions) { if (eff.Equals(pre)) { cndts.Add(eff); //Debug.Log("here"); } } } if (cndts.Count() == 0) { // forfeit this entire subplan linkWorlds = new List <List <CausalLink <IPlanStep> > >(); continue; } if (cndts.Count() == 1) { var cndt = cndts.First(); var dependency = cndt.Clone() as Predicate; var newLink = new CausalLink <IPlanStep>(dependency, head, tail); newLink.Tail.Fulfill(cndt); foreach (var linkworld in linkWorlds) { linkworld.Add(newLink); } } else { foreach (var cndt in cndts) { var dependency = cndt.Clone() as Predicate; var newLink = new CausalLink <IPlanStep>(dependency, head, tail); newLink.Tail.Fulfill(cndt); var clonedLinks = EnumerableExtension.CloneList(newSublinks); linkWorlds.Add(clonedLinks); foreach (var linkworld in linkWorlds) { linkworld.Add(newLink); } } } } foreach (var linkworld in linkWorlds) { var newDecomp = decomp.Clone() as TimelineDecomposition; newDecomp.SubSteps = newSubsteps; newDecomp.SubOrderings = newSuborderings; newDecomp.SubLinks = linkworld; var outputTuple = new Tuple <TimelineDecomposition, Dictionary <int, IPlanStep> >(newDecomp, substepDict); decompMap.Add(outputTuple); } } return(decompMap); }
/// <summary> /// The Decomposition is composed of a sub-plan with at least sub-step at height "height" /// </summary> /// <returns>A list of decompositions with ground terms and where each sub-step is ground. </returns> public static List <TimelineDecomposition> Compose(int height, TimelineDecomposition TD, List <CamSchema> camOptions, Dictionary <string, Vector3> locationMap) { /////////////////////////////////////// // START BY ADDING BINDINGS TO TERMS // /////////////////////////////////////// var permList = new List <List <string> >(); foreach (Term variable in TD.Terms) { permList.Add(GroundActionFactory.TypeDict[variable.Type] as List <string>); } var decompList = new List <TimelineDecomposition>(); foreach (var combination in EnumerableExtension.GenerateCombinations(permList)) { // Add bindings var decompClone = TD.Clone() as TimelineDecomposition; var termStringList = from term in decompClone.Terms select term.Variable; var constantStringList = combination; decompClone.AddBindings(termStringList.ToList(), constantStringList.ToList()); ///////////////////////////////////////////////////////// // PROPAGATE BINDINGS TO NONEQUALITY CONSTRAINTS ///////////////////////////////////////////////////////// var newNonEqualities = new List <List <ITerm> >(); if (TD.NonEqualities == null) { TD.NonEqualities = new List <List <ITerm> >(); } else { foreach (var nonequals in TD.NonEqualities) { var newNonEquals = new List <ITerm>(); newNonEquals.Add(decompClone.Terms.First(dterm => dterm.Variable.Equals(nonequals[0].Variable))); newNonEquals.Add(decompClone.Terms.First(dterm => dterm.Variable.Equals(nonequals[1].Variable))); newNonEqualities.Add(newNonEquals); } decompClone.NonEqualities = newNonEqualities; if (!decompClone.NonEqualTermsAreNonequal()) { continue; } } // zip to dict var varDict = EnumerableExtension.Zip(termStringList, constantStringList).ToDictionary(x => x.Key, x => x.Value); ///////////////////////////////////////////////////////// // BINDINGS ARE ADDED. NEED TO APPLY BINDINGS TO SUBSTEPS ///////////////////////////////////////////////////////// // Need to propagate bindings to sub-steps foreach (var substep in decompClone.SubSteps) { var op = substep.Action as Operator; foreach (var term in substep.Terms) { op.AddBinding(term.Variable, varDict[term.Variable]); } foreach (var precon in substep.Preconditions) { foreach (var term in precon.Terms) { if (!term.Bound) { var decompTerm = decompClone.Terms.First(dterm => dterm.Variable.Equals(term.Variable)); op.Terms.Add(term); op.AddBinding(term.Variable, decompTerm.Constant); } } } foreach (var eff in substep.Effects) { foreach (var term in eff.Terms) { if (!term.Bound) { var decompTerm = decompClone.Terms.First(dterm => dterm.Variable.Equals(term.Variable)); op.Terms.Add(term); op.AddBinding(term.Variable, decompTerm.Constant); } } } } //////////////////////////////////////////////////////////////// // FILTER CANDIDATES FOR SUBSTEPS AND PASS BACK GROUNDED DECOMPS //////////////////////////////////////////////////////////////// // legacy for fabula subplan. returns a list of decomp packages, whose second member is a map from fabula substep IDs to substeps var fabulaGroundedDecompMap = TimelineDecomposition.FilterDecompCandidates(decompClone); // foreach decomposition including a mapping from fabula substep IDs to substeps foreach (Tuple <TimelineDecomposition, Dictionary <int, IPlanStep> > decompPackage in fabulaGroundedDecompMap) { // get candidates and ground for camera steps var newGroundDecomps = TimelineDecompositionHelper.FilterTimelineDecompCandidates(TD, decompPackage, height, camOptions, locationMap); foreach (var gdecomp in newGroundDecomps) { // This function updates the mapping from action variable names to step-variables, and repoints mapping to grounded fabula substep. These names used by camera shots. gdecomp.UpdateActionVarMap(decompPackage.Second); // Add new ground decomposition to map. decompList.Add(gdecomp); } } } return(decompList); }
/// <summary> /// Takes a fabula-valid decomposition and generates a list of discourse worlds (different camera shots to display the fabula) /// </summary> /// <param name="decompPackage"> Grounded fabula substeps and a mapping from step variables to those substeps </param> /// <param name="height"> Among CamOptions would include composite options... but may </param> /// <param name="camOptions"> From "Cameras" GameObject </param> /// <param name="locationMap"> Mapping location names to specific coordinates (used to determine orientation in space, and possibly for navigation estimates. </param> /// <returns> A list of TimelineDecomposition which all have fabula-valid and discourse-valid sub-plan</returns> public static List <TimelineDecomposition> FilterTimelineDecompCandidates(TimelineDecomposition TD, Tuple <TimelineDecomposition, Dictionary <int, IPlanStep> > decompPackage, int height, List <CamSchema> camOptions, Dictionary <string, Vector3> locationMap) { var timelineDecompList = new List <TimelineDecomposition>(); var decomp = decompPackage.First; var substepDict = decompPackage.Second; // mapping ID of substeps to orientations var orientLocationTuple = GetOrientsAndLocations(decomp, locationMap); var orientDict = orientLocationTuple.First; var locationDict = orientLocationTuple.Second; // Easier list to reference later //var discourseSubStepList = new List<CamPlanStep>(); // create permutation for each combination of legal subcams var permList = GetPermutationCameraShots(TD.discourseSubSteps, substepDict, TD.fabulaActionNameMap, orientDict, locationDict, camOptions); //ist<CamPlanStep> discourseSubSteps, Dictionary<int, IPlanStep> fabsubstepDict, Dictionary<string, IPlanStep> fabulaActionNameMap, //Dictionary<int, int> orientDict, Dictionary< int, string> locationDict, List<CamAttributesStruct> camOptions // foreach combination, check if step constraints are true foreach (var combination in EnumerableExtension.GenerateCombinations(permList)) { // clone decomp var decompClone = decomp.Clone() as TimelineDecomposition; var camSubStepDict = new Dictionary <int, CamPlanStep>(); var newDiscourseSubSteps = new List <CamPlanStep>(); for (int j = 0; j < combination.Count; j++) { // a reference to the camera object candidate //var camObj = combination[j].AttributesToSchema(); // a reference to the j'th discourse step var camStep = TD.discourseSubSteps[j].Clone() as CamPlanStep; camStep.CamDetails = combination[j].Clone() as CamSchema; //camStep.CamObject = camObj.gameObject; // a cloning of the cam plan step //var newPlanStep = camStep.Clone(); //newPlanStep.CamObject = camObj.gameObject; // storing a mapping from old cam plan step ID to new cam plan step camSubStepDict[camStep.ID] = camStep; newDiscourseSubSteps.Add(camStep); } var boolOutcome = ValidateConstraints(substepDict, camSubStepDict, TD.fabConstraints, TD.discConstraints, orientDict); // public static bool ValidateConstraints(Dictionary<int, IPlanStep> fabsubstepDict, Dictionary<int, CamPlanStep> discsubstepDict, //List<Tuple<string, Tuple<IPlanStep, IPlanStep>>> fabConstraints, List<Tuple<string, Tuple<IPlanStep, IPlanStep>>> discConstraints, //Dictionary<int, int> orientDict) if (!boolOutcome) { continue; } // these are done here, but they could/should have been performed during regular legacy decomposition filtering. var newFabCntgs = new List <Tuple <IPlanStep, IPlanStep> >(); foreach (var subCntg in TD.fabCntgs) { var newcntg = new Tuple <IPlanStep, IPlanStep>(substepDict[subCntg.First.ID], substepDict[subCntg.Second.ID]); newFabCntgs.Add(newcntg); } var newDOrderings = new List <Tuple <CamPlanStep, CamPlanStep> >(); foreach (var subOrdering in TD.discOrderings) { var newOrdering = new Tuple <CamPlanStep, CamPlanStep>(camSubStepDict[subOrdering.First.ID], camSubStepDict[subOrdering.Second.ID]); newDOrderings.Add(newOrdering); } var newDiscCntgs = new List <Tuple <CamPlanStep, CamPlanStep> >(); foreach (var subCntg in TD.discCntgs) { var newcntg = new Tuple <CamPlanStep, CamPlanStep>(camSubStepDict[subCntg.First.ID], camSubStepDict[subCntg.Second.ID]); newDiscCntgs.Add(newcntg); } var linkWorlds = new List <List <CausalLink <CamPlanStep> > >(); linkWorlds.Add(new List <CausalLink <CamPlanStep> >()); var newSublinks = new List <CausalLink <CamPlanStep> >(); foreach (var subLink in TD.discLinks) { var head = camSubStepDict[subLink.Head.ID]; var tail = camSubStepDict[subLink.Tail.ID]; var cndts = head.Effects.Where(eff => eff.IsConsistent(subLink.Predicate) && tail.Preconditions.Any(pre => pre.Equals(eff))); if (cndts.Count() == 0) { // forfeit this entire subplan linkWorlds = new List <List <CausalLink <CamPlanStep> > >(); break; } if (cndts.Count() == 1) { var cndt = cndts.First(); var dependency = cndt.Clone() as Predicate; var newLink = new CausalLink <CamPlanStep>(dependency, head, tail); newLink.Tail.Fulfill(cndt); foreach (var linkworld in linkWorlds) { linkworld.Add(newLink); } } else { foreach (var cndt in cndts) { var dependency = cndt.Clone() as Predicate; var newLink = new CausalLink <CamPlanStep>(dependency, head, tail); newLink.Tail.Fulfill(cndt); var clonedLinks = EnumerableExtension.CloneList(newSublinks); linkWorlds.Add(clonedLinks); foreach (var linkworld in linkWorlds) { linkworld.Add(newLink); } } } } foreach (var linkworld in linkWorlds) { var newDecomp = decomp.Clone() as TimelineDecomposition; newDecomp.discourseSubSteps = TD.discourseSubSteps; newDecomp.discOrderings = newDOrderings; newDecomp.fabCntgs = newFabCntgs; newDecomp.discCntgs = newDiscCntgs; newDecomp.discLinks = linkworld; timelineDecompList.Add(newDecomp); } } return(timelineDecompList); }