All Downloads are FREE. Search and download functionalities are using the official Maven repository.

astra.reasoner.util.AbstractEvaluateVisitor Maven / Gradle / Ivy

There is a newer version: 1.4.2
Show newest version
package astra.reasoner.util;

import java.util.HashMap;
import java.util.Map;

import astra.formula.AND;
import astra.formula.Bind;
import astra.formula.BooleanTermFormula;
import astra.formula.BracketFormula;
import astra.formula.Comparison;
import astra.formula.Formula;
import astra.formula.FormulaVariable;
import astra.formula.Goal;
import astra.formula.ModuleFormula;
import astra.formula.NOT;
import astra.formula.OR;
import astra.formula.Predicate;
import astra.formula.TestGoal;
import astra.term.AtIndex;
import astra.term.Brackets;
import astra.term.Count;
import astra.term.FormulaTerm;
import astra.term.Funct;
import astra.term.Head;
import astra.term.ListSplitter;
import astra.term.ListTerm;
import astra.term.Not;
import astra.term.Operator;
import astra.term.Performative;
import astra.term.Primitive;
import astra.term.Tail;
import astra.term.Term;
import astra.term.Variable;
import astra.type.InvalidTypeException;
import astra.type.Type;

@SuppressWarnings("rawtypes")
public abstract class AbstractEvaluateVisitor implements LogicVisitor {
	public static interface Handler {
		public Class getType();
		public Object handle(LogicVisitor visitor, T object, boolean passByValue);
	}
	
	private static Map, Handler> formulaHandlers = new HashMap, Handler>();
	private static Map, Handler> termHandlers = new HashMap, Handler>();
	
	public static  void addFormulaHandler(Handler handler) {
		formulaHandlers.put(handler.getType(), handler);
	}
	
	public static  void addTermHandler(Handler handler) {
		termHandlers.put(handler.getType(), handler);
	}
	
	@SuppressWarnings("unchecked")
	private static  Handler getFormulaHandler(Class cls) {
		return (Handler) formulaHandlers.get(cls);
	}
	
	@SuppressWarnings("unchecked")
	private static  Handler getTermHandler(Class cls) {
//		System.out.println("cls: " + cls.getCanonicalName());
		return (Handler) termHandlers.get(cls);
	}
	
	protected boolean passByValue=true;

	public AbstractEvaluateVisitor(boolean passByValue) {
		this.passByValue = passByValue;
	}

	public Object visit(Formula formula) {
		Handler handler = getFormulaHandler(formula.getClass());
//		System.out.println("AEV Formula:" + formula + " / handler="+ handler);
		if (handler == null) return null;
		return handler.handle(this, formula, passByValue);
	}
	
	public Object visit(Term term) {
//		System.out.println("AEV: Term: " + term.getClass().getCanonicalName());
		Handler handler = getTermHandler(term.getClass());
//		System.out.println("AEV: Term: " + term + " / handler="+ handler);
		if (handler == null) return null;
		return handler.handle(this, term, passByValue);
	}
	
	static {
		addFormulaHandler(new Handler() {
			public Class getType() { return Predicate.class; }
			public Object handle(LogicVisitor visitor, Predicate predicate,boolean passByValue) {
				Term[] terms = new Term[predicate.size()];
				
				for (int i=0; i < predicate.size(); i++) {
					terms[i] = (Term) predicate.getTerm(i).accept(visitor);
				}
				
				return new Predicate(predicate.predicate(), terms);
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return ModuleFormula.class; }
			public Object handle(LogicVisitor visitor, ModuleFormula formula,boolean passByValue) {
				return new ModuleFormula(formula.module(), (Predicate) formula.predicate().accept(visitor), formula.adaptor());
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return AND.class; }
			public Object handle(LogicVisitor visitor, AND and,boolean passByValue) {
				return new AND((Formula) and.left().accept(visitor), (Formula) and.right().accept(visitor));
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return OR.class; }
			public Object handle(LogicVisitor visitor, OR or,boolean passByValue) {
				// Formula left = (Formula) or.left().accept(visitor);
				// Formula right = (Formula) or.right().accept(visitor);
				// if (left == Predicate.TRUE || right == Predicate.TRUE) return Predicate.TRUE;
				// if (left == Predicate.FALSE && right == Predicate.FALSE) return Predicate.FALSE;
				return new OR((Formula) or.left().accept(visitor), (Formula) or.right().accept(visitor));
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return NOT.class; }
			public Object handle(LogicVisitor visitor, NOT not,boolean passByValue) {
				return new NOT((Formula) not.formula().accept(visitor));
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return Goal.class; }
			public Object handle(LogicVisitor visitor, Goal goal,boolean passByValue) {
				return new Goal((Predicate) goal.formula().accept(visitor));
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return TestGoal.class; }
			public Object handle(LogicVisitor visitor, TestGoal goal,boolean passByValue) {
				return new TestGoal((Predicate) goal.formula().accept(visitor));
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return FormulaVariable.class; }
			public Object handle(LogicVisitor visitor, FormulaVariable variable,boolean passByValue) {
				return variable.variable().accept(visitor);
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return BracketFormula.class; }
			public Object handle(LogicVisitor visitor, BracketFormula formula,boolean passByValue) {
				return new BracketFormula((Formula) formula.formula().accept(visitor));
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return Bind.class; }
			public Object handle(LogicVisitor visitor, Bind bind,boolean passByValue) {
				Bind b = new Bind(bind.variable(), (Term) bind.term().accept(visitor));
				return b;
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return Comparison.class; }
			@SuppressWarnings("unchecked")
			public Object handle(LogicVisitor visitor, Comparison comparison,boolean passByValue) {
				// Need to check if the bindings have been generated yet...
//				System.out.println("\tvisitor: " + visitor.getClass().getCanonicalName());
//				System.out.println("\tl: "+ comparison.left());
				Term il = (Term) comparison.left().accept(visitor);
//				System.out.println("\til: "+ il);
//				System.out.println("\tr: "+ comparison.right());
				Term ir = (Term) comparison.right().accept(visitor);
//				System.out.println("\tir: "+ ir);
				if (il instanceof Variable || ir instanceof Variable) return new Comparison(comparison.operator(), il,ir);
				
				if (Type.isNumeric(il) && Type.isNumeric(ir)) {
					Primitive l = (Primitive) il;
					Primitive r = (Primitive) ir;
					if (comparison.operator() == Comparison.LESS_THAN) {
						return Type.doubleValue(l) < Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
					} else if (comparison.operator() == Comparison.LESS_THAN_OR_EQUAL) {
						return Type.doubleValue(l) <= Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
					} else if (comparison.operator() == Comparison.GREATER_THAN) {
						return Type.doubleValue(l) > Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
					} else if (comparison.operator() == Comparison.GREATER_THAN_OR_EQUAL) {
						return Type.doubleValue(l) >= Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
					} else if (comparison.operator() == Comparison.EQUAL) {
						return Type.doubleValue(l) == Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
					} else if (comparison.operator() == Comparison.NOT_EQUAL || comparison.operator() == Comparison.OTHER_NOT_EQUAL) {
						return Type.doubleValue(l) != Type.doubleValue(r) ? Predicate.TRUE : Predicate.FALSE;
					}
	//			} else if (il.type() == Type.performativeType && ir.type() == Type.performativeType) {
	//				Performative l = (Performative) il;
	//				Performative r = (Performative) ir;
	//				if (comparison.operator() == Comparison.EQUAL) {
	//					return l.equals(r) ? Predicate.TRUE : Predicate.FALSE;
	//				} else if (comparison.operator() == Comparison.NOT_EQUAL) {
	//					return l.equals(r) ? Predicate.FALSE : Predicate.TRUE;
	//				}
				} else if (il.type() == Type.STRING && ir.type() == Type.STRING) {
					Primitive l = (Primitive) il;
					Primitive r = (Primitive) ir;
					if (comparison.operator() == Comparison.EQUAL) {
						return l.equals(r) ? Predicate.TRUE : Predicate.FALSE;
					} else if (comparison.operator() == Comparison.NOT_EQUAL) {
	//					System.out.println("Comparison: " + comparison);
	//					System.out.println("result: " + l.equals(r));
						return l.equals(r) ? Predicate.FALSE : Predicate.TRUE;
					} else {
						System.out.println("unknown opeator: " + comparison.operator());
					}
				} else if (il.type() == Type.BOOLEAN && ir.type() == Type.BOOLEAN) {
				
					Primitive l = (Primitive) il;
					Primitive r = (Primitive) ir;
					if (comparison.operator() == Comparison.EQUAL) {
						return l.equals(r) ? Predicate.TRUE : Predicate.FALSE;
					} else if (comparison.operator() == Comparison.NOT_EQUAL) {
						return l.equals(r) ? Predicate.FALSE : Predicate.TRUE;
					}
				} else if (il.type() == Type.LIST && ir.type() == Type.LIST) {
					ListTerm l = (ListTerm) il;
					ListTerm r = (ListTerm) ir;
					if (comparison.operator() == Comparison.EQUAL) {
						return l.equals(r) ? Predicate.TRUE : Predicate.FALSE;
					} else if (comparison.operator() == Comparison.NOT_EQUAL) {
						return l.equals(r) ? Predicate.FALSE : Predicate.TRUE;
					}
				} else {
					System.out.println("Comparison Not Supported: " + comparison);
					System.out.println("Left Type: " + il.type());
					System.out.println("Right Type: " + ir.type());
				}
				
				throw new RuntimeException("Problem comparing non-numeric terms in astra.plan.EvaluateVisitor: " + comparison);
			}
		});
		addFormulaHandler(new Handler() {
			public Class getType() { return BooleanTermFormula.class; }
			public Object handle(LogicVisitor visitor, BooleanTermFormula formula,boolean passByValue) {
				return new BooleanTermFormula((Term) formula.term().accept(visitor));
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return Primitive.class; }
			public Object handle(LogicVisitor visitor, Primitive term,boolean passByValue) {
				return term;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return Funct.class; }
			public Object handle(LogicVisitor visitor, Funct function,boolean passByValue) {
				Term[] terms = new Term[function.size()];
				
				for (int i=0; i < function.size(); i++) {
					terms[i] = (Term) function.getTerm(i).accept(visitor);
				}
				return new Funct(function.functor(), terms);
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return ListTerm.class; }
			public Object handle(LogicVisitor visitor, ListTerm list, boolean passByValue) {
				// Version 3:
				// The latest edition of the saga: copy if not grounded. The main
				// culprit here is the cartago.params([name, cls]) argument used in
				// cartago.makeArtifact(...).
				// System.out.println("List: " + list);
				// if (!isGrounded(list)) {
				
				// This was modified to ignore pass by value (not sure this is good)
				// Problem was due to dealing with ModuleTerm instances which cannot 
				// be replaced with the actual value...
				// NOTE: line below commented out to allow isGrounded() to be used
				if (passByValue) {
					ListTerm out = new ListTerm();
					for (int i=0; i < list.size(); i++) {
						out.add((Term) list.get(i).accept(visitor));
					}
					return out;
				}
				// Added the code below to make Prelude.remove(...) work
				// Wrote test case for list containing an element generated by a listTerm, but not
				// sure that previous issue has not been reintroduced...
				for (int i=0; i < list.size(); i++) {
					list.set(i, (Term) list.get(i).accept(visitor));
				}
				return list;				
			}

			// private boolean isGrounded(Term term) {
			// 	if (Variable.class.isInstance(term)) return false;
			// 	if (ModuleTerm.class.isInstance(term)) return false;
			// 	if (ListTerm.class.isInstance(term)) {
			// 		for (Term t : (ListTerm) term) {
			// 			if (!isGrounded(t)) return false;
			// 		}
			// 	}
			// 	if (Funct.class.isInstance(term)) {
			// 		for (Term t : ((Funct) term).terms()) {
			// 			if (!isGrounded(t)) return false;
			// 		}
			// 	}
			// 	return true;
			// }
		});
		addTermHandler(new Handler() {
			public Class getType() { return Operator.class; }
			public Object handle(LogicVisitor visitor, Operator operator, boolean passByValue) {
				// System.out.println("Operator: " + operator);
				((AbstractEvaluateVisitor) visitor).passByValue=true;
				Term l = (Term) operator.left().accept(visitor);
				Term r = (Term) operator.right().accept(visitor);
				((AbstractEvaluateVisitor) visitor).passByValue=passByValue;

//				System.out.println("l: " + l);
//				System.out.println("r: " + r + " / " + r.getClass().getCanonicalName());
//				System.out.println("term types: " + l.type() + " / " + r.type());
//				System.out.println("operator type: " + operator.type());

				if (l instanceof Variable || r instanceof Variable) return Operator.newOperator(operator.op(), l, r);
//				if (r instanceof Variable) {
//					System.out.println("Right hand operand is unbound: " + r);
//					System.exit(0);
//				}
				
				if (operator.type().equals(Type.STRING)) {
					try {
						if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.stringValue(l) + Type.stringValue(r));
					} catch (Throwable th) {
						System.out.println("Failed to evaluate: " + operator);
						System.out.println("Left: " + Type.stringValue(l));
						System.out.println("Right: " + Type.stringValue(r));
						th.printStackTrace();
						System.exit(0);
					}
				} else if (operator.type().equals(Type.LIST)) {
					if (operator.op() == Operator.PLUS) {
						return ((ListTerm) l).merge((ListTerm) r);
					}
				} else if (operator.type().equals(Type.INTEGER)) {
					if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.integerValue(l) + Type.integerValue(r)); 
					if (operator.op() == Operator.MINUS) return Primitive.newPrimitive(Type.integerValue(l) - Type.integerValue(r)); 
					if (operator.op() == Operator.MULTIPLY) return Primitive.newPrimitive(Type.integerValue(l) * Type.integerValue(r)); 
					if (operator.op() == Operator.DIVIDE) return Primitive.newPrimitive(Type.integerValue(l) / Type.integerValue(r)); 
					if (operator.op() == Operator.MODULO) return Primitive.newPrimitive(Type.integerValue(l) % Type.integerValue(r)); 
				} else if (operator.type().equals(Type.LONG)) {
//					System.out.println("l=" + l + " / r=" + r + " / p(l)=" + Type.longValue(l) + " / p(r)=" + Type.longValue(r));
					if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.longValue(l) + Type.longValue(r)); 
					if (operator.op() == Operator.MINUS) return Primitive.newPrimitive(Type.longValue(l) - Type.longValue(r)); 
					if (operator.op() == Operator.MULTIPLY) return Primitive.newPrimitive(Type.longValue(l) * Type.longValue(r)); 
					if (operator.op() == Operator.DIVIDE) return Primitive.newPrimitive(Type.longValue(l) / Type.longValue(r)); 
					if (operator.op() == Operator.MODULO) return Primitive.newPrimitive(Type.longValue(l) % Type.longValue(r)); 
				} else if (operator.type().equals(Type.FLOAT)) {
					if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.floatValue(l) + Type.floatValue(r)); 
					if (operator.op() == Operator.MINUS) return Primitive.newPrimitive(Type.floatValue(l) - Type.floatValue(r)); 
					if (operator.op() == Operator.MULTIPLY) return Primitive.newPrimitive(Type.floatValue(l) * Type.floatValue(r)); 
					if (operator.op() == Operator.DIVIDE) return Primitive.newPrimitive(Type.floatValue(l) / Type.floatValue(r)); 
				} else if (operator.type().equals(Type.DOUBLE)) {
					if (operator.op() == Operator.PLUS) return Primitive.newPrimitive(Type.doubleValue(l) + Type.doubleValue(r)); 
					if (operator.op() == Operator.MINUS) return Primitive.newPrimitive(Type.doubleValue(l) - Type.doubleValue(r)); 
					if (operator.op() == Operator.MULTIPLY) return Primitive.newPrimitive(Type.doubleValue(l) * Type.doubleValue(r)); 
					if (operator.op() == Operator.DIVIDE) return Primitive.newPrimitive(Type.doubleValue(l) / Type.doubleValue(r)); 
				}

				return null;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return Performative.class; }
			public Object handle(LogicVisitor visitor, Performative performative, boolean passByValue) {
				return performative;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return FormulaTerm.class; }
			public Object handle(LogicVisitor visitor, FormulaTerm formula, boolean passByValue) {
				if (formula.value() != null) formula.value().accept(visitor);
				return null;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return Brackets.class; }
			public Object handle(LogicVisitor visitor, Brackets term, boolean passByValue) {
				// System.out.println("term: " + term);
				// System.out.println("term.term: " + term.term());
				return term.term().accept(visitor);
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return ListSplitter.class; }
			public Object handle(LogicVisitor visitor, ListSplitter term, boolean passByValue) {
				return term;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return Count.class; }
			public Object handle(LogicVisitor visitor, Count count, boolean passByValue) {
//				System.out.println("(AEV) Handling count: " + count);
				Term c = (Term) count.term().accept(visitor);
				if (c instanceof ListTerm) {
					return Primitive.newPrimitive(((ListTerm) c).size());
				}
				return count;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return Head.class; }
			public Object handle(LogicVisitor visitor, Head head, boolean passByValue) {
//				System.out.println("(AEV) Handling head: " + head);
				Term c = (Term) head.term().accept(visitor);
//				System.out.println("(AEV) processed: " + c);
				if (c instanceof ListTerm) {
					return ((ListTerm) c).get(0);
				}
				return head;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return Tail.class; }
			public Object handle(LogicVisitor visitor, Tail tail, boolean passByValue) {
//				System.out.println("(AEV) Handling tail: " + tail);
				Term c = (Term) tail.term().accept(visitor);
				
//				System.out.println("(AEV) processed: " + c);
				if (c instanceof ListTerm) {
					ListTerm tailList = new ListTerm();
					for (int i=1;i<((ListTerm)c).size(); i++) {
						tailList.add(((ListTerm) c).get(i));
					}
					return tailList;
				}
				return tail;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return AtIndex.class; }
			@SuppressWarnings("unchecked")
			public Object handle(LogicVisitor visitor, AtIndex atIndex, boolean passByValue) {
//				System.out.println("(AEV) Handling at_index: " + atIndex);
				Term t = (Term) atIndex.term().accept(visitor);
				Term i = (Term) atIndex.index().accept(visitor);
				if (t instanceof ListTerm && i instanceof Primitive) {
					return ((ListTerm) t).get(((Primitive) i).value());
				}
				return atIndex;
			}
		});
		addTermHandler(new Handler() {
			public Class getType() { return Not.class; }
			public Object handle(LogicVisitor visitor, Not term, boolean passByValue) {
				Term innerTerm = (Term) term.term().accept(visitor);
				if (innerTerm instanceof Primitive) {
					Primitive primitive = (Primitive) innerTerm;
					if (primitive.type().equals(Type.BOOLEAN)) {
						return Primitive.newPrimitive(!(Boolean) primitive.value());
					}
				}

				System.out.println("Term: " +term.term().accept(visitor));
				System.out.println("Class: " +term.term().accept(visitor).getClass());
				throw new InvalidTypeException("Expected boolean term but got: " + innerTerm.type());
			}
		});
	}
	
//	@Override
//	public Object visit(AcreHistory history) {
//		history.getConversationId().accept(this);
//		history.getIndex().accept(this);
//		history.getType().accept(this);
//		history.getContent().accept(this);
//		return null;
//	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy