public static DefaultRule representativeSubstitution( DefaultRule rule, List<Set<Constant>> interchangeable) { if (rule.antecedent().variables().isEmpty()) { return rule; } else { // a bit naive (but not too much), it can be improved later... List<Literal> auxLiteralsC = new ArrayList<Literal>(); for (Variable v : rule.antecedent().variables()) { auxLiteralsC.add(new Literal("v", v)); } List<Literal> auxLiteralsE = new ArrayList<Literal>(); int typeIndex = 0; for (Set<Constant> interch : interchangeable) { int counter = 0; for (Term t : interch) { auxLiteralsE.add(new Literal("v", t)); if (++counter >= rule.antecedent().variables().size()) { break; } } } Matching m = new Matching(); m.setSubsumptionMode(Matching.OI_SUBSUMPTION); Pair<Term[], List<Term[]>> substitutions = m.allSubstitutions(new Clause(auxLiteralsC), new Clause(auxLiteralsE), 1); return DefaultTransformationUtils.substitute(rule, substitutions.r, substitutions.s.get(0)); } }
public static MultiMap<DefaultRule, DefaultRule> representativeBodySpecializations( DefaultRule rule, List<Set<Constant>> interchangeableConstants) { Clause body = rule.antecedent(); Clause head = rule.consequent(); final MultiMap<Variable, Variable> different = surelyDifferent(rule); final List<Variable> variables = Sugar.<Variable>listFromCollections(body.variables()); List<Integer> indices = VectorUtils.toList(VectorUtils.sequence(0, variables.size() - 1)); List<Tuple<Integer>> unifications = Combinatorics.<Integer>cartesianPower( indices, indices.size(), new Sugar.Fun<Tuple<Integer>, Boolean>() { @Override public Boolean apply(Tuple<Integer> integerTuple) { for (int i = 0; i < integerTuple.size(); i++) { if (integerTuple.get(i) > i || !integerTuple.get(i).equals(integerTuple.get(integerTuple.get(i))) || different .get(variables.get(integerTuple.get(i))) .contains(variables.get(i)) || !sameType(variables.get(integerTuple.get(i)), variables.get(i))) { return Boolean.FALSE; } } return Boolean.TRUE; } }); Set<DefaultRule> nonIsomorphicUnifications = new HashSet<DefaultRule>(); for (Tuple<Integer> unification : unifications) { Map<Term, Term> substitution = new HashMap<Term, Term>(); for (int i = 0; i < unification.size(); i++) { substitution.put(variables.get(i), variables.get(unification.get(i))); } Clause newBody = LogicUtils.substitute(rule.antecedent(), substitution); Clause newHead = LogicUtils.substitute(rule.consequent(), substitution); nonIsomorphicUnifications.add( new DefaultRule( newBody.variables().size() > 1 ? new Clause(Sugar.union(newBody.literals(), allDiffLiteral(newBody))) : newBody, newHead)); } nonIsomorphicUnifications = DefaultTransformationUtils.selectNonisomorphicDefaultRules(nonIsomorphicUnifications); MultiMap<DefaultRule, DefaultRule> retVal = new MultiMap<DefaultRule, DefaultRule>(); // this needs to be improved... e.g. using typing information... MultiList<Integer, Constant> consts = new MultiList<Integer, Constant>(); int index = 0; for (Set<Constant> interch : interchangeableConstants) { consts.putAll(index++, interch); } for (DefaultRule unifiedRule : nonIsomorphicUnifications) { List<Variable> unifsVariables = Sugar.listFromCollections(unifiedRule.variables()); if (unifsVariables.isEmpty()) { retVal.put(unifiedRule, unifiedRule); } else { Set<DefaultRule> substituted = new HashSet<DefaultRule>(); middleLoop: for (Tuple<Integer> tuple : Combinatorics.cartesianPower( new NaturalNumbersList(0, interchangeableConstants.size()), unifsVariables.size())) { Counters<Integer> used = new Counters<Integer>(); Map<Term, Term> substitution = new HashMap<Term, Term>(); for (int i = 0; i < unifsVariables.size(); i++) { int j = used.incrementPost(tuple.get(i)); if (j >= consts.get(tuple.get(i)).size()) { continue middleLoop; } else { if (unifsVariables.get(i).type() == null) { substitution.put( unifsVariables.get(i), Variable.construct( unifsVariables.get(i).name(), consts.get(tuple.get(i)).get(j).type())); } else { if (unifsVariables.get(i).type().equals(consts.get(tuple.get(i)).get(j).type())) { substitution.put( unifsVariables.get(i), Variable.construct( unifsVariables.get(i).name(), consts.get(tuple.get(i)).get(j).type())); } else { continue middleLoop; } } } } substituted.add(DefaultTransformationUtils.substitute(unifiedRule, substitution)); } retVal.putAll( unifiedRule, DefaultTransformationUtils.selectNonisomorphicDefaultRules(substituted)); } } return retVal; }