/* * Returns true if the KC_PrologExpression on the unit has already been evaluated, false otherwise. * Given a unit containing a KC_PrologExpression and a blackboard, returns true if there is a * L_SelectedUnitLink to a Unit with a KC_EvaluatablePrologExpression matching the KC_PrologExpression. */ protected static bool HasLinkToEvaluatedExpression(Unit unit, IBlackboard blackboard) { ISet <(IUnit, string, LinkDirection)> links = blackboard.LookupLinks(unit); foreach ((IUnit linkedIUnit, string type, LinkDirection dir) in links) { /* * There should only be up to 1 outgoing L_SelectedUnit link, but since I'm not enforcing this on the blackboard, * for now testing all L_SelectedUnit links until I find a matching KC_EvaluatablePrologExpression */ if (type.Equals(LinkTypes.L_SelectedUnit) && dir == LinkDirection.End) { Unit linkedUnit = linkedIUnit as Unit; // If the linkedUnit contains a matching, evaluated, KC_EvaluatablePrologExpression, return true. if (linkedUnit.HasComponent <KC_EvaluatablePrologExpression>()) { KC_EvaluatablePrologExpression evaledPrologExp = linkedUnit.GetComponent <KC_EvaluatablePrologExpression>(); if (evaledPrologExp.PrologExpName.Equals(unit.GetPrologExpName <KC_PrologExpression>()) && evaledPrologExp.Evaluated) { Debug.Assert(evaledPrologExp.PrologExp.Equals(unit.GetPrologExp())); return(true); } /* fixme * Consider making this recursively search links if the linked Unit has an EvaluatablePrologExpression with a matching name but it has * not been evaluated (though currently there's no KS in the system that does this) OR there's a PrologExpression with a matching name. * The latter is a likely use case. If we downselected in a pool with prolog expressions first, then evaluated those, that would result * in this case. */ } } } return(false); // No linked, matching KC_EvaluatablePrologExpression was found. }
/* * Copy all the units bound by the precondition into the OutputPool adding a KC_EvaluatablePrologExpression and evaluate the expression. */ protected override void Execute(object[] boundVars) { // Get the units and the prolog KB from the precondition bindings. var units = (IEnumerable <Unit>)boundVars[FilteredUnits]; Unit prologKB = (Unit)boundVars[PrologKB]; // Copy each of the units to the output pool, adding a KC_EvaluatablePrologExpression and evaluating it. foreach (var unit in units) { Unit unitCopy = CopyUnitToOutputPool(unit); // fixme: ignoring the name. When the Unit component infrastructure is updated to handle multiple named components, change the call here. KC_PrologExpression expToEvaluate = unitCopy.GetComponent <KC_PrologExpression>(); // Remove the KC_PrologExpression unitCopy.RemoveComponent(expToEvaluate); // Create a KC_EvaluatablePrologExpression based on expToEvaluate. KC_EvaluatablePrologExpression evaluatablePrologExp = new KC_EvaluatablePrologExpression(expToEvaluate); // Add the KC_EvaluatablePrologExpression to the Unit unitCopy.AddComponent(evaluatablePrologExp); /* * Evaluate the prolog expression. * The original unit now being linked (via CopyUnitToOutputPool) to a unit with a matching and evaled KC_EvaluatablePrologExpression * is what will keep this unit from repeatedly matching in the precondition. The precondition is testing !HasLinkToEvaluatedExpression * as a filter condition. */ evaluatablePrologExp.Evaluate(prologKB.GetComponent <KC_PrologKB>()); } }