package org.ggp.base.util.gdl; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.ggp.base.util.gdl.grammar.Gdl; import org.ggp.base.util.gdl.grammar.GdlConstant; import org.ggp.base.util.gdl.grammar.GdlDistinct; import org.ggp.base.util.gdl.grammar.GdlFunction; import org.ggp.base.util.gdl.grammar.GdlLiteral; import org.ggp.base.util.gdl.grammar.GdlNot; import org.ggp.base.util.gdl.grammar.GdlOr; import org.ggp.base.util.gdl.grammar.GdlProposition; import org.ggp.base.util.gdl.grammar.GdlRule; import org.ggp.base.util.gdl.grammar.GdlSentence; import org.ggp.base.util.gdl.grammar.GdlTerm; import org.ggp.base.util.gdl.grammar.GdlVariable; public class GdlUtils { private GdlUtils() { } //TODO (AL): Check if we can switch over to just having this return a set. public static List<GdlVariable> getVariables(Gdl gdl) { final List<GdlVariable> variablesList = new ArrayList<GdlVariable>(); final Set<GdlVariable> variables = new HashSet<GdlVariable>(); GdlVisitors.visitAll(gdl, new GdlVisitor() { @Override public void visitVariable(GdlVariable variable) { if (!variables.contains(variable)) { variablesList.add(variable); variables.add(variable); } } }); return variablesList; } public static Set<GdlVariable> getVariablesSet(Gdl gdl) { final Set<GdlVariable> variables = new HashSet<GdlVariable>(); GdlVisitors.visitAll(gdl, new GdlVisitor() { @Override public void visitVariable(GdlVariable variable) { variables.add(variable); } }); return variables; } public static List<String> getVariableNames(Gdl gdl) { List<GdlVariable> variables = getVariables(gdl); List<String> variableNames = new ArrayList<String>(); for (GdlVariable variable : variables) { variableNames.add(variable.getName()); } return variableNames; } public static List<GdlSentence> getSentencesInRuleBody(GdlRule rule) { List<GdlSentence> result = new ArrayList<GdlSentence>(); for(GdlLiteral literal : rule.getBody()) { addSentencesInLiteral(literal, result); } return result; } private static void addSentencesInLiteral(GdlLiteral literal, Collection<GdlSentence> sentences) { if(literal instanceof GdlSentence) { sentences.add((GdlSentence) literal); } else if(literal instanceof GdlNot) { GdlNot not = (GdlNot) literal; addSentencesInLiteral(not.getBody(), sentences); } else if(literal instanceof GdlOr) { GdlOr or = (GdlOr) literal; for(int i = 0; i < or.arity(); i++) addSentencesInLiteral(or.get(i), sentences); } else if(!(literal instanceof GdlDistinct)) { throw new RuntimeException("Unexpected GdlLiteral type encountered: " + literal.getClass().getSimpleName()); } } public static List<GdlTerm> getTupleFromSentence( GdlSentence sentence) { if(sentence instanceof GdlProposition) return Collections.emptyList(); //A simple crawl through the sentence. List<GdlTerm> tuple = new ArrayList<GdlTerm>(); try { addBodyToTuple(sentence.getBody(), tuple); } catch(RuntimeException e) { throw new RuntimeException(e.getMessage() + "\nSentence was " + sentence); } return tuple; } private static void addBodyToTuple(List<GdlTerm> body, List<GdlTerm> tuple) { for(GdlTerm term : body) { if(term instanceof GdlConstant) { tuple.add(term); } else if(term instanceof GdlVariable) { tuple.add(term); } else if(term instanceof GdlFunction){ GdlFunction function = (GdlFunction) term; addBodyToTuple(function.getBody(), tuple); } else { throw new RuntimeException("Unforeseen Gdl tupe in SentenceModel.addBodyToTuple()"); } } } public static List<GdlConstant> getTupleFromGroundSentence( GdlSentence sentence) { if(sentence instanceof GdlProposition) return Collections.emptyList(); //A simple crawl through the sentence. List<GdlConstant> tuple = new ArrayList<GdlConstant>(); try { addBodyToGroundTuple(sentence.getBody(), tuple); } catch(RuntimeException e) { throw new RuntimeException(e.getMessage() + "\nSentence was " + sentence); } return tuple; } private static void addBodyToGroundTuple(List<GdlTerm> body, List<GdlConstant> tuple) { for(GdlTerm term : body) { if(term instanceof GdlConstant) { tuple.add((GdlConstant) term); } else if(term instanceof GdlVariable) { throw new RuntimeException("Asking for a ground tuple of a non-ground sentence"); } else if(term instanceof GdlFunction){ GdlFunction function = (GdlFunction) term; addBodyToGroundTuple(function.getBody(), tuple); } else { throw new RuntimeException("Unforeseen Gdl tupe in SentenceModel.addBodyToTuple()"); } } } public static Map<GdlVariable, GdlConstant> getAssignmentMakingLeftIntoRight( GdlSentence left, GdlSentence right) { Map<GdlVariable, GdlConstant> assignment = new HashMap<GdlVariable, GdlConstant>(); if(!left.getName().equals(right.getName())) return null; if(left.arity() != right.arity()) return null; if(left.arity() == 0) return Collections.emptyMap(); if(!fillAssignmentBody(assignment, left.getBody(), right.getBody())) return null; return assignment; } private static boolean fillAssignmentBody( Map<GdlVariable, GdlConstant> assignment, List<GdlTerm> leftBody, List<GdlTerm> rightBody) { //left body contains variables; right body shouldn't if(leftBody.size() != rightBody.size()) { return false; } for(int i = 0; i < leftBody.size(); i++) { GdlTerm leftTerm = leftBody.get(i); GdlTerm rightTerm = rightBody.get(i); if(leftTerm instanceof GdlConstant) { if(!leftTerm.equals(rightTerm)) { return false; } } else if(leftTerm instanceof GdlVariable) { if(assignment.containsKey(leftTerm)) { if(!assignment.get(leftTerm).equals(rightTerm)) { return false; } } else { if(!(rightTerm instanceof GdlConstant)) { return false; } assignment.put((GdlVariable)leftTerm, (GdlConstant)rightTerm); } } else if(leftTerm instanceof GdlFunction) { if(!(rightTerm instanceof GdlFunction)) return false; GdlFunction leftFunction = (GdlFunction) leftTerm; GdlFunction rightFunction = (GdlFunction) rightTerm; if(!leftFunction.getName().equals(rightFunction.getName())) return false; if(!fillAssignmentBody(assignment, leftFunction.getBody(), rightFunction.getBody())) return false; } } return true; } public static boolean containsTerm(GdlSentence sentence, GdlTerm term) { if(sentence instanceof GdlProposition) return false; return containsTerm(sentence.getBody(), term); } private static boolean containsTerm(List<GdlTerm> body, GdlTerm term) { for(GdlTerm curTerm : body) { if(curTerm.equals(term)) return true; if(curTerm instanceof GdlFunction) { if(containsTerm(((GdlFunction) curTerm).getBody(), term)) return true; } } return false; } }