// 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> /// 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); }
/// <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); }