001 package aima.logic.fol; 002 003 import java.util.ArrayList; 004 import java.util.HashMap; 005 import java.util.HashSet; 006 import java.util.List; 007 import java.util.Map; 008 import java.util.Set; 009 010 import aima.logic.fol.kb.data.Clause; 011 012 /** 013 * Note: From slide 17. 014 * http://logic.stanford.edu/classes/cs157/2008/lectures/lecture12.pdf 015 * 016 * Relational Subsumption 017 * 018 * A relational clause Phi subsumes Psi is and only if there 019 * is a substitution delta that, when applied to Phi, produces a 020 * clause Phidelta that is a subset of Psi. 021 */ 022 023 /** 024 * @author Ciaran O'Reilly 025 * 026 */ 027 public class SubsumptionElimination { 028 public static Set<Clause> findSubsumedClauses(Set<Clause> clauses) { 029 Set<Clause> subsumed = new HashSet<Clause>(); 030 031 // Group the clauses by their # of literals. 032 // Keep track of the min and max # of literals. 033 int min = Integer.MAX_VALUE; 034 int max = 0; 035 Map<Integer, Set<Clause>> clausesGroupedBySize = new HashMap<Integer, Set<Clause>>(); 036 for (Clause c : clauses) { 037 int size = c.getNumberLiterals(); 038 if (size < min) { 039 min = size; 040 } 041 if (size > max) { 042 max = size; 043 } 044 Set<Clause> cforsize = clausesGroupedBySize.get(size); 045 if (null == cforsize) { 046 cforsize = new HashSet<Clause>(); 047 clausesGroupedBySize.put(size, cforsize); 048 } 049 cforsize.add(c); 050 } 051 // Check if each smaller clause 052 // subsumes any of the larger clauses. 053 for (int i = min; i < max; i++) { 054 Set<Clause> scs = clausesGroupedBySize.get(i); 055 // Ensure there are clauses with this # of literals 056 if (null != scs) { 057 for (int j = i + 1; j <= max; j++) { 058 Set<Clause> lcs = clausesGroupedBySize.get(j); 059 // Ensure there are clauses with this # of literals 060 if (null != lcs) { 061 for (Clause sc : scs) { 062 // Don't bother checking clauses 063 // that are already subsumed. 064 if (!subsumed.contains(sc)) { 065 for (Clause lc : lcs) { 066 if (!subsumed.contains(lc)) { 067 if (sc.subsumes(lc)) { 068 subsumed.add(lc); 069 } 070 } 071 } 072 } 073 } 074 } 075 } 076 } 077 } 078 079 return subsumed; 080 } 081 }