/// <summary> /// If this Variable is bound, then just call YP.unify to unify this with arg. /// (Note that if arg is an unbound Variable, then YP.unify will bind it to /// this Variable's value.) /// Otherwise, bind this Variable to YP.getValue(arg) and yield once. After the /// yield, return this Variable to the unbound state. /// For more details, see http://yieldprolog.sourceforge.net/tutorial1.html /// </summary> /// <param name="arg"></param> /// <returns></returns> public IEnumerable <bool> unify(object arg) { if (!_isBound) { _value = YP.getValue(arg); if (_value == this) { // We are unifying this unbound variable with itself, so leave it unbound. yield return(false); } else { _isBound = true; try { yield return(false); } finally { // Remove the binding. _isBound = false; } } } else { foreach (bool l1 in YP.unify(this, arg)) { yield return(false); } } }
/// <summary> /// Parse goalString and yield for each Goal, setting VariableList to a list of /// (variableAtom = Var). /// </summary> /// <param name="goalString"></param> /// <param name="Goal"></param> /// <param name="VariableList"></param> /// <returns></returns> static IEnumerable <bool> parseGoal(string goalString, object Goal, object VariableList) { // The parser requires a newline at the end. YP.see(new StringReader(goalString + "\n")); object TermList = new Variable(); // parseInput set TermList to a list of f(Goal, VariableList). foreach (bool l1 in Parser.parseInput(TermList)) { // Close the input now before yielding. YP.seen(); // Iterate through each member of TermList. for (TermList = YP.getValue(TermList); TermList is Functor2 && ((Functor2)TermList)._name == Atom.DOT; TermList = YP.getValue(((Functor2)TermList)._arg2)) { // Unify the head of the list with f(Goal, VariableList). foreach (bool l2 in YP.unify (((Functor2)TermList)._arg1, new Functor2(Atom.F, Goal, VariableList))) { yield return(false); } } yield break; } // Close the input in case parseInput failed. YP.seen(); }
/// If arg is another Functor2, then succeed (yield once) if this and arg have the /// same name and all functor args unify, otherwise fail (don't yield). /// If arg is a Variable, then call its unify to unify with this. /// Otherwise fail (don't yield). public IEnumerable <bool> unify(object arg) { arg = YP.getValue(arg); if (arg is Functor2) { Functor2 argFunctor = (Functor2)arg; if (_name.Equals(argFunctor._name)) { foreach (bool l1 in YP.unify(_arg1, argFunctor._arg1)) { foreach (bool l2 in YP.unify(_arg2, argFunctor._arg2)) { yield return(false); } } } } else if (arg is Variable) { foreach (bool l1 in ((Variable)arg).unify(this)) { yield return(false); } } }
public IEnumerable <bool> retract(object Head, object Body) { Head = YP.getValue(Head); if (Head is Variable) { throw new PrologException("instantiation_error", "Head is an unbound variable"); } object[] arguments = YP.getFunctorArgs(Head); // We always match Head from _allAnswers, and the Body is Atom.a("true"). #pragma warning disable 0168, 0219 foreach (bool l1 in YP.unify(Body, Atom.a("true"))) { // The caller can assert another answer into this same predicate during yield, so we have to // make a copy of the answers. foreach (object[] answer in _allAnswers.ToArray()) { foreach (bool l2 in YP.unifyArrays(arguments, answer)) { _allAnswers.Remove(answer); clearIndexes(); yield return(false); } } } #pragma warning restore 0168, 0219 }
static IEnumerable <bool> squaredRectangle(object Width, object Height) { foreach (bool l1 in YP.unify(Width, Height)) { yield return(false); } }
/// <summary> /// Unify Bag with the result. This frees the internal answers, so you can only call this once. /// </summary> /// <param name="Bag"></param> /// <returns></returns> public IEnumerable <bool> result(object Bag) { object result = ListPair.make(_bagArray); // Try to free the memory. _bagArray = null; return(YP.unify(Bag, result)); }
static IEnumerable <bool> makeList(object First, object Second, object List) { ListPair list1 = new ListPair(Second, Atom.NIL); ListPair result = new ListPair(First, list1); foreach (bool l1 in YP.unify(List, result)) { yield return(false); } }
/// <summary> /// For each result, unify the _freeVariables and unify Bag with the associated bag. /// </summary> /// <param name="Bag"></param> /// <returns></returns> public IEnumerable <bool> result(object Bag) { Variable bagArrayVariable = new Variable(); foreach (bool l1 in resultArray(bagArrayVariable)) { foreach (bool l2 in YP.unify(Bag, ListPair.make((List <object>)bagArrayVariable.getValue()))) { yield return(false); } } }
public static IEnumerable <bool> detected(object Obj) { { Variable Value = new Variable(); Variable Min = new Variable(); Variable Max = new Variable(); foreach (bool l2 in recognition(Obj, Value)) { foreach (bool l3 in confidence(Obj, Min, Max)) { if (YP.greaterThan(Value, Min)) { if (YP.lessThan(Value, Max)) { yield return(false); } } } } } { Variable Value = new Variable(); Variable Min = new Variable(); Variable Max = new Variable(); foreach (bool l2 in recognition(Obj, Value)) { foreach (bool l3 in confidence(Obj, Min, Max)) { foreach (bool l4 in YP.unify(Value, Min)) { yield return(false); } } } } { Variable Value = new Variable(); Variable Min = new Variable(); Variable Max = new Variable(); foreach (bool l2 in recognition(Obj, Value)) { foreach (bool l3 in confidence(Obj, Min, Max)) { foreach (bool l4 in YP.unify(Value, Max)) { yield return(false); } } } } }
/// <summary> /// For each result, unify the _freeVariables and unify Bag with the associated bag which is sorted /// with duplicates removed, as in setof. /// </summary> /// <param name="Bag"></param> /// <returns></returns> public IEnumerable <bool> resultSet(object Bag) { Variable bagArrayVariable = new Variable(); foreach (bool l1 in resultArray(bagArrayVariable)) { List <object> bagArray = (List <object>)bagArrayVariable.getValue(); YP.sortArray(bagArray); foreach (bool l2 in YP.unify(Bag, ListPair.makeWithoutRepeatedTerms(bagArray))) { yield return(false); } } }
/// <summary> /// If Obj is an Atom unify its _module with Module. If the Atom's _module is null, use Atom.NIL. /// </summary> /// <param name="Atom"></param> /// <param name="Module"></param> /// <returns></returns> public static IEnumerable <bool> module(object Obj, object Module) { Obj = YP.getValue(Obj); if (Obj is Atom) { if (((Atom)Obj)._module == null) { return(YP.unify(Module, Atom.NIL)); } else { return(YP.unify(Module, ((Atom)Obj)._module)); } } return(YP.fail()); }
static IEnumerable <bool> rangeList(object M, object N, object List) { if ((int)YP.getValue(M) >= (int)YP.getValue(N)) { foreach (bool l1 in YP.unify(List, new ListPair(N, Atom.NIL))) { yield return(false); } } else { Variable Tail = new Variable(); foreach (bool l1 in rangeList((int)YP.getValue(M) + 1, (int)YP.getValue(N), Tail)) { foreach (bool l2 in YP.unify(List, new ListPair(M, Tail))) { yield return(false); } } } }
static IEnumerable <bool> brother(object Person, object Brother) { foreach (bool l1 in YP.unify(Person, "Hillary")) { foreach (bool l2 in YP.unify(Brother, "Tony")) { yield return(false); } foreach (bool l2 in YP.unify(Brother, "Hugh")) { yield return(false); } } foreach (bool l1 in YP.unify(Person, "Bill")) { foreach (bool l2 in YP.unify(Brother, "Roger")) { yield return(false); } } }
public static IEnumerable <bool> parent (object Person, object Parent) { foreach (bool l1 in YP.unify (Person, Atom.a("Chelsea"))) { foreach (bool l2 in YP.unify (Parent, Atom.a("Hillary"))) { yield return(false); } } foreach (bool l1 in YP.unify (Person, Atom.a("Chelsea"))) { foreach (bool l2 in YP.unify (Parent, Atom.a("Bill"))) { yield return(false); } } }
public static IEnumerable <bool> uncle (object Person, object Uncle) { { Variable Goal = new Variable(); Variable Parent = new Variable(); foreach (bool l2 in YP.unify (Goal, new Functor2 (Atom.a("parent", Atom.a("")), Person, Parent))) { foreach (bool l3 in YP.getIterator (Goal, getDeclaringClass())) { foreach (bool l4 in YP.matchDynamic (Atom.a("brother"), new object[] { Parent, Uncle })) { yield return(false); } } } } }
public IEnumerable <bool> clause(object Head, object Body) { Head = YP.getValue(Head); if (Head is Variable) { throw new PrologException("instantiation_error", "Head is an unbound variable"); } object[] arguments = YP.getFunctorArgs(Head); // We always match Head from _allAnswers, and the Body is Atom.TRUE. foreach (bool l1 in YP.unify(Body, Atom.TRUE)) { // The caller can assert another answer into this same predicate during yield, so we have to // make a copy of the answers. foreach (object[] answer in _allAnswers.ToArray()) { foreach (bool l2 in YP.unifyArrays(arguments, answer)) { yield return(false); } } } }
static IEnumerable <bool> queens3(object UnplacedQs, object SafeQs, object Qs) { Variable UnplacedQs1 = new Variable(); Variable Q = new Variable(); foreach (bool l1 in selectq(Q, UnplacedQs, UnplacedQs1)) { foreach (bool l2 in notHasAttack(Q, SafeQs)) { foreach (bool l3 in queens3(UnplacedQs1, new ListPair(Q, SafeQs), Qs)) { yield return(false); } } } foreach (bool l1 in YP.unify(UnplacedQs, Atom.NIL)) { foreach (bool l2 in YP.unify(Qs, SafeQs)) { yield return(false); } } }
/// <summary> /// If this Variable is bound, then just call YP.unify to unify this with arg. /// (Note that if arg is an unbound Variable, then YP.unify will bind it to /// this Variable's value.) /// Otherwise, bind this Variable to YP.getValue(arg) and yield once. After the /// yield, return this Variable to the unbound state. /// For more details, see http://yieldprolog.sourceforge.net/tutorial1.html /// </summary> /// <param name="arg"></param> /// <returns></returns> public IEnumerable <bool> unify(object arg) { if (!_isBound) { _value = YP.getValue(arg); if (_value == this) { // We are unifying this unbound variable with itself, so leave it unbound. yield return(false); } else { _isBound = true; try { yield return(false); } finally { // Remove the binding. _isBound = false; } } } else { // disable warning on l1, don't see how we can // code this differently #pragma warning disable 0168, 0219 foreach (bool l1 in YP.unify(this, arg)) { yield return(false); } #pragma warning restore 0168, 0219 } }
public IEnumerable <bool> match(object[] arguments) { if (arguments.Length != _arity) { yield break; } // Set up indexArgs, up to arg position MAX_INDEX_ARGS. The signature has a 1 bit for // each non-null index arg. HashedList indexArgs = new HashedList(arguments.Length); bool gotAllIndexArgs = true; int signature = 0; for (int i = 0; i < arguments.Length; ++i) { object indexValue = null; if (i < MAX_INDEX_ARGS) { // We limit the number of args in a 32-bit signature. indexValue = getIndexValue(YP.getValue(arguments[i])); if (indexValue != null) { signature += (1 << i); } } if (indexValue == null) { gotAllIndexArgs = false; } indexArgs.Add(indexValue); } List <object[]> answers; if (signature == 0) { // No index args, so we have to match from _allAnswers. answers = _allAnswers; } else { if (!_gotAnswersForSignature.ContainsKey(signature)) { // We need to create the entry in _indexedAnswers. foreach (object[] answer in _allAnswers) { indexAnswerForSignature(answer, signature); } // Mark that we did this signature. _gotAnswersForSignature[signature] = null; } if (!_indexedAnswers.TryGetValue(indexArgs, out answers)) { yield break; } } if (gotAllIndexArgs) { // All the arguments were already bound, so we don't need to do bindings. yield return(false); yield break; } // Find matches in answers. IEnumerator <bool>[] iterators = new IEnumerator <bool> [arguments.Length]; // Debug: If the caller asserts another answer into this same predicate during yield, the iterator // over clauses will be corrupted. Should we take the time to copy answers? foreach (object[] answer in answers) { bool gotMatch = true; int nIterators = 0; // Try to bind all the arguments. for (int i = 0; i < arguments.Length; ++i) { if (indexArgs[i] != null) { // We already matched this argument by looking up _indexedAnswers. continue; } IEnumerator <bool> iterator = YP.unify(arguments[i], answer[i]).GetEnumerator(); iterators[nIterators++] = iterator; // MoveNext() is true if YP.unify succeeds. if (!iterator.MoveNext()) { gotMatch = false; break; } } int z = 0; try { if (gotMatch) { yield return(false); } } finally { // Manually finalize all the iterators. for (z = 0; z < nIterators; ++z) { iterators[z].Dispose(); } } } }