public bool termEqual(object term) { term = YP.getValue(term); if (term is Functor) { Functor termFunctor = (Functor)term; if (_name.Equals(termFunctor._name) && _args.Length == termFunctor._args.Length) { for (int i = 0; i < _args.Length; ++i) { if (!YP.termEqual(_args[i], termFunctor._args[i])) { return(false); } } return(true); } } return(false); }
/// <summary> /// To get the free variables, split off any existential qualifiers from Goal such as the X in /// "X ^ f(Y)", get the set of unbound variables in Goal that are not qualifiers, then remove /// the unbound variables that are qualifiers as well as the unbound variables in Template. /// </summary> /// <param name="Template"></param> /// <param name="Goal"></param> public BagofAnswers(object Template, object Goal) { _template = Template; // First get the set of variables that are not free variables. List <Variable> variableSet = new List <Variable>(); YP.addUniqueVariables(Template, variableSet); object UnqualifiedGoal = YP.getValue(Goal); while (UnqualifiedGoal is Functor2 && ((Functor2)UnqualifiedGoal)._name == Atom.HAT) { YP.addUniqueVariables(((Functor2)UnqualifiedGoal)._arg1, variableSet); UnqualifiedGoal = YP.getValue(((Functor2)UnqualifiedGoal)._arg2); } // Remember how many non-free variables there are so we can find the unique free variables // that are added. int nNonFreeVariables = variableSet.Count; YP.addUniqueVariables(UnqualifiedGoal, variableSet); int nFreeVariables = variableSet.Count - nNonFreeVariables; if (nFreeVariables == 0) { // There were no free variables added, so we won't waste time with _bagForFreeVariables. _freeVariables = null; _findallBagArray = new List <object>(); } else { // Copy the free variables. _freeVariables = new Variable[nFreeVariables]; for (int i = 0; i < nFreeVariables; ++i) { _freeVariables[i] = variableSet[i + nNonFreeVariables]; } _bagForFreeVariables = new Dictionary <object[], List <object> >(_termArrayEqualityComparer); } }
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); } } } }
/// <summary> /// If arg is another Functor1, then succeed (yield once) if this and arg have the /// same name and the 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). /// </summary> /// <param name="arg"></param> /// <returns></returns> public IEnumerable <bool> unify(object arg) { arg = YP.getValue(arg); if (arg is Functor1) { Functor1 argFunctor = (Functor1)arg; if (_name.Equals(argFunctor._name)) { foreach (bool l1 in YP.unify(_arg1, argFunctor._arg1)) { yield return(false); } } } else if (arg is Variable) { foreach (bool l1 in ((Variable)arg).unify(this)) { 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); } } } }
/// <summary> /// Return an array of the elements in list or null if it is not /// a proper list. If list is Atom.NIL, return an array of zero elements. /// If the list or one of the tails of the list is Variable, raise an instantiation_error. /// This does not call YP.getValue on each element. /// </summary> /// <param name="list"></param> /// <returns></returns> public static object[] toArray(object list) { list = YP.getValue(list); if (list.Equals(Atom.NIL)) { return(new object[0]); } List <object> result = new List <object>(); object element = list; while (true) { if (element == Atom.NIL) { break; } if (element is Variable) { throw new PrologException(Atom.a("instantiation_error"), "List tail is an unbound variable"); } if (!(element is Functor2 && ((Functor2)element)._name == Atom.DOT)) { // Not a proper list. return(null); } result.Add(((Functor2)element)._arg1); element = YP.getValue(((Functor2)element)._arg2); } if (result.Count <= 0) { return(null); } return(result.ToArray()); }
/// <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 } }
static IEnumerable <bool> selectq(Variable X, ListPair Arg2, Variable Arg3) { foreach (bool l1 in X.unify(Arg2._arg1)) { foreach (bool l2 in Arg3.unify(Arg2._arg2)) { yield return(false); } } ListPair Arg2Tail = YP.getValue(Arg2._arg2) as ListPair; if (Arg2Tail != null) { Variable Zs = new Variable(); foreach (bool l1 in selectq(X, Arg2Tail, Zs)) { foreach (bool l2 in Arg3.unify(new ListPair(Arg2._arg1, Zs))) { yield return(false); } } } }
/// <summary> /// If arg is another Functor, 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). /// </summary> /// <param name="arg"></param> /// <returns></returns> public IEnumerable <bool> unify(object arg) { arg = YP.getValue(arg); if (arg is Functor) { Functor argFunctor = (Functor)arg; if (_name.Equals(argFunctor._name)) { return(YP.unifyArrays(_args, argFunctor._args)); } else { return(YP.fail()); } } else if (arg is Variable) { return(((Variable)arg).unify(this)); } else { return(YP.fail()); } }
/// <summary> /// Create a PrologException with the given Term. The printable exception message is the full Term. /// </summary> /// <param name="Term">the term of the exception</param> public PrologException(object Term) : base(YP.getValue(Term).ToString()) { _term = YP.makeCopy(Term, new Variable.CopyStore()); }
public bool termEqual(object term) { return(Equals(YP.getValue(term))); }
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(); } } } }
public override int GetHashCode() { // Note: The infrequent collision where changing the order of args gives the same hash value is OK. return(_name.GetHashCode() ^ YP.getValue(_arg1).GetHashCode() ^ YP.getValue(_arg2).GetHashCode()); }
public override int GetHashCode() { return(_name.GetHashCode() ^ YP.getValue(_arg1).GetHashCode()); }
public override string ToString() { return(_name + "(" + YP.getValue(_arg1) + ")"); }