/*
* tuProlog - Copyright (C) 2001-2007 aliCE team at deis.unibo.it
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alice.tuprolog.lib;
import alice.tuprolog.Agent;
import alice.tuprolog.Functor;
import alice.tuprolog.Int;
import alice.tuprolog.InvalidTheoryException;
import alice.tuprolog.Library;
import alice.tuprolog.Number;
import alice.tuprolog.Operator;
import alice.tuprolog.Predicate;
import alice.tuprolog.Struct;
import alice.tuprolog.Term;
import alice.tuprolog.Theory;
import alice.tuprolog.Var;
/**
* This class defines a set of basic built-in
* predicates for the tuProlog engine
*
* Library/Theory dependency: none
*/
public class BasicLibrary extends Library {
public BasicLibrary() {
}
//
// meta-predicates
//
/**
* sets a new theory provided as a text
*/
@Predicate("set_theory/1")
public boolean setTheory(Term th) {
Struct theory = (Struct) th.getTerm();
try {
if (!theory.isAtom())
return false;
getEngine().setTheory(new Theory(theory.getName()));
return true;
} catch (InvalidTheoryException ex) {
System.err.println("Invalid theory at line " + ex.line);
return false;
}
}
/**
* adds a new theory provided as a text
*/
@Predicate("add_theory/1")
public boolean addTheory(Term th) {
Struct theory = (Struct) th.getTerm();
try {
if (!theory.isAtom())
return false;
getEngine().addTheory(new Theory(theory.getName()));
return true;
} catch (InvalidTheoryException ex) {
System.err.println("Invalid theory at line "+ex.line);
return false;
}
}
/** gets current theory text */
@Predicate("get_theory/1")
public boolean getTheory(Term arg) {
arg = arg.getTerm();
try {
Term theory = new Struct(getEngine().getTheory().toString());
return (unify(arg,theory));
} catch (Exception ex) {
return false;
}
}
@Predicate("load_library/2")
public boolean loadLibrary(Term className, Term libName) {
Struct clName = (Struct) className.getTerm();
libName = libName.getTerm();
try {
Library lib = getEngine().loadLibrary(clName.toStringWithoutApices());
return unify(libName,new Struct(lib.getName()));
} catch (Exception ex) {
return false;
}
}
/**
* Loads a library constructed from a theory.
*
* @param theory theory text
* @param libName name of the library
* @return true if the library has been successfully loaded.
*/
@Predicate("load_library_from_theory/2")
public boolean loadLibraryFromTheory(Term th, Term libName) {
Struct theory = (Struct) th.getTerm();
Struct libN = (Struct) libName.getTerm();
try {
if (!theory.isAtom())
return false;
if (!libN.isAtom())
return false;
Theory t = new Theory(theory.getName());
TheoryLibrary thlib = new TheoryLibrary(libN.getName(),t);
getEngine().loadLibrary(thlib);
return true;
} catch (Exception ex) {
return false;
}
}
@Predicate("get_operators_list/1")
public boolean getOperatorsList(Term argument) {
Term arg = argument.getTerm();
Struct list = new Struct();
for (Operator o : getEngine().getCurrentOperatorList())
list = new Struct(
new Struct("op", new alice.tuprolog.Int(o.prio),
new Struct(o.type),
new Struct(o.name)),
list);
return unify(arg, list);
}
/**
* spawns a separate prolog agent
* providing it a theory text
*/
@Predicate("agent/1")
public boolean agent(Term th) {
Struct theory = (Struct) th.getTerm();
try {
new Agent(theory.toStringWithoutApices()).spawn();
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
/**
* spawns a separate prolog agent
* providing it a theory text and a goal
*/
@Predicate("agent/2")
public boolean agentWithGoal(Term th, Term g) {
Struct theory = (Struct) th.getTerm();
Struct goal = (Struct) g.getTerm();
try {
new Agent(theory.toStringWithoutApices(),
goal.toString() + ".").spawn();
return true;
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
@Predicate("spy/0")
public boolean spy() {
getEngine().setSpy(true);
return true;
}
@Predicate("nospy/0")
public boolean noSpy() {
getEngine().setSpy(false);
return true;
}
@Predicate("warning/0")
public boolean warning() {
getEngine().setWarning(true);
return true;
}
@Predicate("nowarning/0")
public boolean noWarning() {
getEngine().setWarning(false);
return true;
}
//
// term type inspection
//
@Predicate("number/1")
public boolean isNumber(Term t) {
return (t.getTerm() instanceof Number);
}
@Predicate("integer/1")
public boolean isInteger(Term t) {
t = t.getTerm();
if (!(t instanceof Number))
return false;
return ((Number) t).isInteger();
}
@Predicate("float/1")
public boolean isFloat(Term t) {
t = t.getTerm();
if (!(t instanceof Number))
return false;
return ((Number) t).isReal();
}
@Predicate("atom/1")
public boolean isAtom(Term t) {
t = t.getTerm();
return (t.isAtom());
}
@Predicate("compound/1")
public boolean isCompound(Term t) {
t = t.getTerm();
return t.isCompound();
}
@Predicate("list/1")
public boolean isList(Term t) {
t = t.getTerm();
return (t.isList());
}
@Predicate("var/1")
public boolean isVar(Term t) {
t = t.getTerm();
return (t instanceof Var);
}
@Predicate("nonvar/1")
public boolean isNotVar(Term t) {
t = t.getTerm();
return !(t instanceof Var);
}
@Predicate("atomic/1")
public boolean isAtomic(Term t) {
t = t.getTerm();
return t.isAtomic();
}
@Predicate("ground/1")
public boolean isGround(Term t) {
t = t.getTerm();
return (t.isGround());
}
//
// term/expression comparison
//
@Predicate("=:=/2")
public boolean expressionEquality(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0==null || val1==null || !(val0 instanceof Number) || !(val1 instanceof Number)) {
return false;
}
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
if (val0n.isInteger() && val1n.isInteger()) {
return (val0n.intValue() == val1n.intValue()) ? true : false;
} else {
return (val0n.doubleValue() == val1n.doubleValue()) ? true : false;
}
}
@Predicate("=\\=/2")
public boolean expressionInequality(Term arg0, Term arg1) {
return !expressionEquality(arg0, arg1);
}
@Predicate(">/2")
public boolean expressionGreaterThan(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 == null || val1 == null || !(val0 instanceof Number) || !(val1 instanceof Number))
return false;
return expressionGreaterThan((alice.tuprolog.Number) val0, (alice.tuprolog.Number) val1);
}
@Predicate("=</2")
public boolean expressionLessOrEqualThan(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 == null || val1 == null || !(val0 instanceof Number) || !(val1 instanceof Number))
return false;
return !expressionGreaterThan((alice.tuprolog.Number) val0, (alice.tuprolog.Number) val1);
}
private boolean expressionGreaterThan(alice.tuprolog.Number num0, alice.tuprolog.Number num1) {
if (num0.isInteger() && num1.isInteger()) {
return num0.intValue() > num1.intValue();
} else {
return num0.doubleValue() > num1.doubleValue();
}
}
@Predicate("</2")
public boolean expressionLessThan(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 == null || val1 == null || !(val0 instanceof Number) || !(val1 instanceof Number))
return false;
return expressionLessThan((alice.tuprolog.Number) val0, (alice.tuprolog.Number) val1);
}
@Predicate(">=/2")
public boolean expressionGreaterOrEqualThan(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 == null || val1 == null || !(val0 instanceof Number) || !(val1 instanceof Number))
return false;
return !expressionLessThan((alice.tuprolog.Number) val0, (alice.tuprolog.Number) val1);
}
private boolean expressionLessThan(alice.tuprolog.Number num0, alice.tuprolog.Number num1) {
if (num0.isInteger() && num1.isInteger()) {
return num0.intValue() < num1.intValue();
} else {
return num0.doubleValue() < num1.doubleValue();
}
}
@Predicate("==/2")
public boolean termEquality(Term arg0, Term arg1) {
arg0 = arg0.getTerm();
arg1 = arg1.getTerm();
return arg0.isEqual(arg1);
}
@Predicate("\\==/2")
public boolean termInequality(Term arg0, Term arg1) {
return !termEquality(arg0, arg1);
}
@Predicate("@>/2")
public boolean termGreaterThan(Term arg0, Term arg1) {
arg0 = arg0.getTerm();
arg1 = arg1.getTerm();
return arg0.isGreater(arg1);
}
@Predicate("@=</2")
public boolean termLessOrEqualThan(Term arg0, Term arg1) {
return !termGreaterThan(arg0, arg1);
}
@Predicate("@</2")
public boolean termLessThan(Term arg0, Term arg1) {
arg0 = arg0.getTerm();
arg1 = arg1.getTerm();
return !(arg0.isGreater(arg1) || arg0.isEqual(arg1));
}
@Predicate("@>=/2")
public boolean termGreaterOrEqualThan(Term arg0, Term arg1) {
return !termLessThan(arg0, arg1);
}
@Functor("+/1")
public Term expressionPlus(Term arg0) {
Term val0 = evalExpression(arg0);
if (val0!=null && val0 instanceof Number)
return val0;
else
return null;
}
@Functor("-/1")
public Term expressionMinus(Term arg1) {
Term val0 = evalExpression(arg1);
if (val0!=null && val0 instanceof Number) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
if (val0n instanceof Int)
return new Int(val0n.intValue() * -1);
else if (val0n instanceof alice.tuprolog.Double)
return new alice.tuprolog.Double(val0n.doubleValue() * -1);
else if (val0n instanceof alice.tuprolog.Long)
return new alice.tuprolog.Long(val0n.longValue() * -1);
else if (val0n instanceof alice.tuprolog.Float)
return new alice.tuprolog.Float(val0n.floatValue() * -1);
else
return null;
} else
return null;
}
@Functor("\\/1")
public Term expressionBitwiseNot(Term arg0) {
Term val0 = evalExpression(arg0);
if (val0!=null && val0 instanceof Number)
return new Int(~((alice.tuprolog.Number) val0).intValue());
else
return null;
}
alice.tuprolog.Number getIntegerNumber(long num) {
if (num > Integer.MIN_VALUE && num < Integer.MAX_VALUE)
return new Int((int) num);
else
return new alice.tuprolog.Long(num);
}
@Functor("+/2")
public Term expressionPlus(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0!=null && val1!=null && val0 instanceof Number && (val1 instanceof Number)) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
if (val0n.isInteger() && (val1n.isInteger()))
return getIntegerNumber(val0n.longValue() + val1n.longValue());
else
return new alice.tuprolog.Double(val0n.doubleValue() + val1n.doubleValue());
} else
return null;
}
@Functor("-/2")
public Term expressionMinus(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0!=null && val1!=null && val0 instanceof Number && (val1 instanceof Number)) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
if (val0n.isInteger() && (val1n.isInteger()))
return getIntegerNumber(val0n.longValue() - val1n.longValue());
else
return new alice.tuprolog.Double(val0n.doubleValue() - val1n.doubleValue());
} else
return null;
}
@Functor("*/2")
public Term expressionMultiply(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0!=null && val1!=null && val0 instanceof Number && (val1 instanceof Number)) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
if (val0n.isInteger() && (val1n.isInteger()))
return getIntegerNumber(val0n.longValue() * val1n.longValue());
else
return new alice.tuprolog.Double(val0n.doubleValue() * val1n.doubleValue());
} else
return null;
}
@Functor("//2")
public Term expressionDiv(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 != null && val1 != null && val0 instanceof Number && val1 instanceof Number) {
Number val0n = (Number) val0;
Number val1n = (Number) val1;
alice.tuprolog.Double result = new alice.tuprolog.Double(val0n.doubleValue()/val1n.doubleValue());
if (val0n.isInteger() && val1n.isInteger())
return getIntegerNumber(result.longValue());
else
return result;
} else
return null;
}
@Functor("///2")
public Term expressionIntegerDiv(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 != null && val1 != null && val0 instanceof Number && (val1 instanceof Number)) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
return getIntegerNumber(val0n.longValue() / val1n.longValue());
} else
return null;
}
@Functor("**/2")
public Term expressionPow(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 != null && val1 != null && val0 instanceof Number && val1 instanceof Number) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
return new alice.tuprolog.Double(Math.pow(val0n.doubleValue(), val1n.doubleValue()));
} else
return null;
}
@Functor(">>/2")
public Term expressionBitwiseShiftRight(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 != null && val1 != null && val0 instanceof Number && val1 instanceof Number) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
return new Int(val0n.intValue() >> val1n.intValue());
} else
return null;
}
@Functor("<</2")
public Term expressionBitwiseShiftLeft(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 != null && val1 != null && val0 instanceof Number && val1 instanceof Number) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
return new Int(val0n.intValue() << val1n.intValue());
} else
return null;
}
@Functor("/\\/2")
public Term expressionBitwiseAnd(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 != null && val1 != null && val0 instanceof Number && val1 instanceof Number) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
return new Int(val0n.intValue() & val1n.intValue());
} else
return null;
}
@Functor("\\//2")
public Term expressionBitwiseOr(Term arg0, Term arg1) {
Term val0 = evalExpression(arg0);
Term val1 = evalExpression(arg1);
if (val0 != null && val1 != null && val0 instanceof Number && val1 instanceof Number) {
alice.tuprolog.Number val0n = (alice.tuprolog.Number) val0;
alice.tuprolog.Number val1n = (alice.tuprolog.Number) val1;
return new Int(val0n.intValue() | val1n.intValue());
} else
return null;
}
//
// text/atom manipulation predicates
//
/**
* bidirectional text/term conversion.
*/
@Predicate("text_term/2")
public boolean textTerm(Term arg0, Term arg1) {
arg0 = arg0.getTerm();
arg1 = arg1.getTerm();
if (!arg0.isGround()) {
return unify(arg0,new Struct(arg1.toString()));
} else {
try {
String text = arg0.toStringWithoutApices();
return unify(arg1,getEngine().toTerm(text));
} catch (Exception ex) {
return false;
}
}
}
@Predicate("text_concat/3")
public boolean textConcat(Term source1, Term source2, Term dest) {
source1 = source1.getTerm();
source2 = source2.getTerm();
dest = dest.getTerm();
if (source1.isAtom() && source2.isAtom())
return unify(dest,
new Struct( ((Struct)source1).getName()+ ((Struct)source2).getName()));
else
return false;
}
@Predicate("num_atom/2")
public boolean numAtom(Term arg0,Term arg1) {
arg0 = arg0.getTerm();
arg1 = arg1.getTerm();
if (arg1 instanceof Var) {
if (!(arg0 instanceof Number))
return false;
alice.tuprolog.Number n0 = (alice.tuprolog.Number) arg0;
String st = null;
if (n0.isInteger())
st = new java.lang.Integer(n0.intValue()).toString();
else
st = new java.lang.Double(n0.doubleValue()).toString();
return unify(arg1,new Struct(st));
} else {
if (!arg1.isAtom())
return false;
String st = ((Struct) arg1).getName();
try {
if (st.startsWith("'") && st.endsWith("'"))
st = st.substring(1, st.length() - 1);
} catch (Exception ex) {}
Term term = null;
try {
term = new alice.tuprolog.Int(java.lang.Integer.parseInt(st));
} catch (Exception ex) {}
if (term == null)
try {
term = new alice.tuprolog.Double(java.lang.Double.parseDouble(((Struct)arg1).getName()));
} catch (Exception ex){}
if (term == null)
return false;
return unify(arg0,term);
}
}
@Override
public String getTheory() {
return
//
// operators defined by the BasicLibrary theory
//
"':-'(op( 1200, fx, ':-')). \n"+
":- op( 1200, xfx, ':-'). \n"+
":- op( 1200, fx, '?-'). \n"+
":- op( 1100, xfy, ';'). \n"+
":- op( 1050, xfy, '->'). \n"+
":- op( 1000, xfy, ','). \n"+
":- op( 900, fy, '\\+'). \n"+
":- op( 900, fy, 'not'). \n"+
//
":- op( 700, xfx, '='). \n"+
":- op( 700, xfx, '\\='). \n"+
":- op( 700, xfx, '=='). \n"+
":- op( 700, xfx, '\\=='). \n"+
//
":- op( 700, xfx, '@>'). \n"+
":- op( 700, xfx, '@<'). \n"+
":- op( 700, xfx, '@=<'). \n"+
":- op( 700, xfx, '@>='). \n"+
":- op( 700, xfx, '=:='). \n"+
":- op( 700, xfx, '=\\='). \n"+
":- op( 700, xfx, '>'). \n"+
":- op( 700, xfx, '<'). \n"+
":- op( 700, xfx, '=<'). \n"+
":- op( 700, xfx, '>='). \n"+
//
":- op( 700, xfx, 'is'). \n"+
":- op( 700, xfx, '=..'). \n"+
":- op( 500, yfx, '+'). \n"+
":- op( 500, yfx, '-'). \n"+
":- op( 500, yfx, '/\\'). \n"+
":- op( 500, yfx, '\\/'). \n"+
":- op( 400, yfx, '*'). \n"+
":- op( 400, yfx, '/'). \n"+
":- op( 400, yfx, '//'). \n"+
":- op( 400, yfx, '>>'). \n"+
":- op( 400, yfx, '<<'). \n"+
":- op( 400, yfx, 'rem'). \n" +
":- op( 400, yfx, 'mod'). \n" +
":- op( 200, xfx, '**'). \n"+
":- op( 200, xfy, '^'). \n"+
":- op( 200, fy, '\\'). \n"+
":- op( 200, fy, '-'). \n"+
//
// flag management
//
"current_prolog_flag(Name,Value) :- get_prolog_flag(Name,Value),!.\n"+
"current_prolog_flag(Name,Value) :- flag_list(L), member(flag(Name,Value),L).\n"+
//
// meta-predicates
//
"'=..'(T, [T]) :- atomic(T), !. \n" +
"'=..'(T,L) :- compound(T),!,'$tolist'(T,L). \n " +
"'=..'(T,L) :- nonvar(L),'$fromlist'(T,L). \n " +
"functor(Term, Name, Arity) :- atomic(Term), !, Name = Term, Arity = 0. \n" +
"functor(Term, Name, Arity) :- compound(Term), !, Term =.. [Name | Args], length(Args, Arity). \n" +
"functor(Term, Name, Arity) :- var(Term), atomic(Name), Arity == 0, !, Term = Name. \n" +
"functor(Term, Name, Arity) :- var(Term), atom(Name), I is Arity, integer(I), I > 0, newlist([], I, L), Term =.. [Name | L]. \n" +
"arg(N,C,T):- nonvar(N), C =.. [_|Args], element(N,Args,T).\n"+
"clause(H, B) :- L = [], '$find'(H, L), copy_term(L, LC), member((':-'(H, B)), LC). \n" +
//
// call/1 is coded both in Prolog, to feature the desired opacity
// to cut, and in Java as a primitive built-in, to account for
// goal transformations that should be performed before execution
// as mandated by ISO Standard, see section 7.8.3.1
"call(G) :- '$call'(G). \n" +
"'\\+'(P):- P,!,fail.\n "+
"'\\+'(_).\n "+
"C -> T ; B :- !, or((call(C), !, call(T)), '$call'(B)). \n" +
"C -> T :- call(C), !, call(T). \n" +
"or(A, B) :- '$call'(A). \n" +
"or(A, B) :- '$call'(B). \n" +
"A ; B :- A =.. ['->', C, T], !, ('$call'(C), !, '$call'(T) ; '$call'(B)). \n" +
"A ; B :- '$call'(A). \n" +
"A ; B :- '$call'(B). \n "+
"unify_with_occurs_check(X,Y):-X=Y.\n "+
"current_op(Pri,Type,Name):-get_operators_list(L),member(op(Pri,Type,Name),L).\n "+
"once(X) :- myonce(X).\n "+
"myonce(X):-X,!.\n "+
"repeat. \n " +
"repeat :- repeat. \n " +
"not(G) :- G,!,fail. \n " +
"not(_). \n " +
//
// All solutions predicates
//
"findall(Template, Goal, Instances) :- \n" +
"L = [], \n" +
"'$findall0'(Template, Goal, L), \n" +
"Instances = L. \n" +
"'$findall0'(Template, Goal, L) :- \n" +
"call(Goal), \n" +
"copy_term(Template, CL), \n" +
"'$append'(CL, L), \n" +
"fail. \n" +
"'$findall0'(_, _, _). \n" +
"variable_set(T, []) :- atomic(T), !. \n" +
"variable_set(T, [T]) :- var(T), !. \n" +
"variable_set([H | T], [SH | ST]) :- \n" +
"variable_set(H, SH), variable_set(T, ST). \n" +
"variable_set(T, S) :- \n" +
"T =.. [_ | Args], variable_set(Args, L), flatten(L, FL), no_duplicates(FL, S), !. \n" +
"flatten(L, FL) :- '$flatten0'(L, FL), !. \n" +
"'$flatten0'(T, []) :- nonvar(T), T = []. \n" +
"'$flatten0'(T, [T]) :- var(T). \n" +
"'$flatten0'([H | T], [H | FT]) :- \n" +
"not(islist(H)), !, '$flatten0'(T, FT). \n" +
"'$flatten0'([H | T], FL) :- \n" +
"'$flatten0'(H, FH), '$flatten0'(T, FT), append(FH, FT, FL). \n" +
"islist([]). \n" +
"islist([_|L]):- islist(L). \n " +
"existential_variables_set(Term, Set) :- '$existential_variables_set0'(Term, Set), !. \n" +
"'$existential_variables_set0'(Term, []) :- var(Term), !. \n" +
"'$existential_variables_set0'(Term, []) :- atomic(Term), !. \n" +
"'$existential_variables_set0'(V ^ G, Set) :- \n" +
"variable_set(V, VS), '$existential_variables_set0'(G, EVS), append(VS, EVS, Set). \n" +
"'$existential_variables_set0'(Term, []) :- nonvar(Term), !. \n" +
"free_variables_set(Term, WithRespectTo, Set) :- \n" +
"variable_set(Term, VS), \n" +
"variable_set(WithRespectTo, VS1), existential_variables_set(Term, EVS1), append(VS1, EVS1, BV), \n" +
"list_difference(VS, BV, List), no_duplicates(List, Set), !. \n" +
"list_difference(List, Subtrahend, Difference) :- '$ld'(List, Subtrahend, Difference). \n" +
"'$ld'([], _, []). \n" +
"'$ld'([H | T], S, D) :- is_member(H, S), !, '$ld'(T, S, D). \n" +
"'$ld'([H | T], S, [H | TD]) :- '$ld'(T, S, TD). \n" +
"no_duplicates([], []). \n" +
"no_duplicates([H | T], L) :- is_member(H, T), !, no_duplicates(T, L). \n" +
"no_duplicates([H | T], [H | L]) :- no_duplicates(T, L). \n" +
"is_member(E, [H | _]) :- E == H, !. \n" +
"is_member(E, [_ | T]) :- is_member(E, T). \n" +
"'$wt_list'([], []). \n" +
"'$wt_list'([W + T | STail], [WW + T | WTTail]) :- copy_term(W, WW), '$wt_list'(STail, WTTail). \n" +
"'$s_next'(Witness, WT_List, S_Next) :- copy_term(Witness, W2), '$s_next0'(W2, WT_List, S_Next), !. \n" +
"bagof(Template, Goal, Instances) :- \n" +
"free_variables_set(Goal, Template, Set), \n" +
"Witness =.. [witness | Set], \n" +
"iterated_goal_term(Goal, G), \n" +
"findall(Witness + Template, G, S), \n" +
"'$bagof0'(Witness, S, Instances). \n" +
"'$bagof0'(_, [], _) :- !, fail. \n" +
"'$bagof0'(Witness, S, Instances) :- \n" +
"'$wt_list'(S, WT_List), \n" +
"'$wt_unify'(Witness, WT_List, T_List), \n" +
"Instances = T_List. \n" +
"'$bagof0'(Witness, S, Instances) :- \n" +
"'$wt_list'(S, WT_List), \n" +
"'$s_next'(Witness, WT_List, S_Next), \n" +
"'$bagof0'(Witness, S_Next, Instances). \n" +
"setof(Template, Goal, Instances) :- \n" +
"bagof(Template, Goal, List), \n" +
"quicksort(List, '@<', OrderedList), \n" +
"no_duplicates(OrderedList, Instances). \n" +
//
// theory management predicates
//
"assert(C) :- assertz(C). \n" +
"retract(Rule) :- Rule = ':-'(Head, Body), !, clause(Head, Body), '$retract'(Rule). \n" +
"retract(Fact) :- clause(Fact, true), '$retract'(Fact). \n" +
"retractall(Head) :- findall(':-'(Head, Body), clause(Head, Body), L), '$retract_clause_list'(L), !. \n" +
"'$retract_clause_list'([]). \n" +
"'$retract_clause_list'([E | T]) :- !, '$retract'(E), '$retract_clause_list'(T). \n" +
//
// auxiliary predicates
//
"member(E,[E|_]). \n " +
"member(E,[_|L]):- member(E,L). \n " +
"length(L, S) :- number(S), !, lengthN(L, S), !. \n" +
"length(L, S) :- var(S), lengthX(L, S). \n" +
"lengthN([],0). \n" +
"lengthN(_, N) :- N < 0, !, fail. \n" +
"lengthN([_|L], N) :- lengthN(L,M), N is M + 1. \n" +
"lengthX([],0). \n" +
"lengthX([_|L], N) :- lengthX(L,M), N is M + 1. \n" +
"append([],L2,L2). \n " +
"append([E|T1],L2,[E|T2]):- append(T1,L2,T2). \n " +
"reverse(L1,L2):- reverse0(L1,[],L2). \n " +
"reverse0([],Acc,Acc). \n " +
"reverse0([H|T],Acc,Y):- reverse0(T,[H|Acc],Y). \n " +
"delete(E,[],[]). \n " +
"delete(E,[E|T],L):- !,delete(E,T,L). \n " +
"delete(E,[H|T],[H|L]):- delete(E,T,L). \n " +
"element(1,[E|L],E):- !. \n " +
"element(N,[_|L],E):- M is N - 1,element(M,L,E). \n " +
"newlist(Ls,0,Ls):- !. \n " +
"newlist(Ls,N,Ld):- M is N - 1,newlist([_|Ls],M,Ld). \n " +
"quicksort([],Pred,[]). \n" +
"quicksort([X|Tail],Pred,Sorted):- \n"+
" split(X,Tail,Pred,Small,Big), \n"+
" quicksort(Small,Pred,SortedSmall), \n"+
" quicksort(Big,Pred,SortedBig), \n"+
" append(SortedSmall,[X|SortedBig],Sorted). \n"+
"split(_,[],_,[],[]). \n"+
"split(X,[Y|Tail],Pred,Small,[Y|Big]):- \n"+
" Predicate =..[Pred,X,Y], \n"+
" call(Predicate),!, \n"+
" split(X,Tail,Pred,Small,Big). \n"+
"split(X,[Y|Tail],Pred,[Y|Small],Big):- \n"+
" split(X,Tail,Pred,Small,Big). \n";
}
// Internal Java predicates which are part of the bagof/3 and setof/3 algorithm
@Predicate("$wt_unify/3")
public boolean wtUnify(Term witness, Term wtList, Term tList) {
Struct list = (Struct) wtList.getTerm();
Struct result = new Struct();
for (Term wt : list) {
Struct element = (Struct) wt;
Term w = element.getArg(0);
Term t = element.getArg(1);
if (unify(witness, w))
result.append(t);
}
return unify(tList, result);
}
@Predicate("$s_next0/3")
public boolean sNext(Term witness, Term wtList, Term sNext) {
Struct list = (Struct) wtList.getTerm();
Struct result = new Struct();
for (Term wt : list) {
Struct element = (Struct) wt;
Term w = element.getArg(0);
if (!unify(witness, w))
result.append(element);
}
return unify(sNext, result);
}
@Predicate("iterated_goal_term/2")
public boolean iteratedGoalTerm(Term term, Term goal) {
Term t = term.getTerm();
Term igt = t.iteratedGoalTerm();
return unify(igt, goal);
}
}