001 package aima.logic.fol.kb.data; 002 003 import java.util.ArrayList; 004 import java.util.Collections; 005 import java.util.List; 006 import java.util.Set; 007 008 import aima.logic.fol.inference.proof.ProofStep; 009 import aima.logic.fol.inference.proof.ProofStepChainContrapositive; 010 import aima.logic.fol.inference.proof.ProofStepPremise; 011 012 /** 013 * @see http://logic.stanford.edu/classes/cs157/2008/lectures/lecture13.pdf 014 * 015 * A Chain is a sequence of literals (while a clause is a set) - order is important for a chain. 016 */ 017 018 /** 019 * @author Ciaran O'Reilly 020 * 021 */ 022 public class Chain { 023 private static List<Literal> _emptyLiteralsList = Collections 024 .unmodifiableList(new ArrayList<Literal>()); 025 // 026 private List<Literal> literals = new ArrayList<Literal>(); 027 private ProofStep proofStep = null; 028 029 public Chain() { 030 // i.e. the empty chain 031 } 032 033 public Chain(List<Literal> literals) { 034 this.literals.addAll(literals); 035 } 036 037 public Chain(Set<Literal> literals) { 038 this.literals.addAll(literals); 039 } 040 041 public ProofStep getProofStep() { 042 if (null == proofStep) { 043 // Assume was a premise 044 proofStep = new ProofStepPremise(this); 045 } 046 return proofStep; 047 } 048 049 public void setProofStep(ProofStep proofStep) { 050 this.proofStep = proofStep; 051 } 052 053 public boolean isEmpty() { 054 return literals.size() == 0; 055 } 056 057 public void addLiteral(Literal literal) { 058 literals.add(literal); 059 } 060 061 public Literal getHead() { 062 if (0 == literals.size()) { 063 return null; 064 } 065 return literals.get(0); 066 } 067 068 public List<Literal> getTail() { 069 if (0 == literals.size()) { 070 return _emptyLiteralsList; 071 } 072 return Collections.unmodifiableList(literals 073 .subList(1, literals.size())); 074 } 075 076 public int getNumberLiterals() { 077 return literals.size(); 078 } 079 080 public List<Literal> getLiterals() { 081 return Collections.unmodifiableList(literals); 082 } 083 084 /** 085 * A contrapositive of a chain is a permutation in which a different literal 086 * is placed at the front. The contrapositives of a chain are logically 087 * equivalent to the original chain. 088 * 089 * @return a list of contrapositives for this chain. 090 */ 091 public List<Chain> getContrapositives() { 092 List<Chain> contrapositives = new ArrayList<Chain>(); 093 List<Literal> lits = new ArrayList<Literal>(); 094 095 for (int i = 1; i < literals.size(); i++) { 096 lits.clear(); 097 lits.add(literals.get(i)); 098 lits.addAll(literals.subList(0, i)); 099 lits.addAll(literals.subList(i + 1, literals.size())); 100 Chain cont = new Chain(lits); 101 cont.setProofStep(new ProofStepChainContrapositive(cont, this)); 102 contrapositives.add(cont); 103 } 104 105 return contrapositives; 106 } 107 108 public String toString() { 109 StringBuilder sb = new StringBuilder(); 110 sb.append("<"); 111 112 for (int i = 0; i < literals.size(); i++) { 113 if (i > 0) { 114 sb.append(","); 115 } 116 sb.append(literals.get(i).toString()); 117 } 118 119 sb.append(">"); 120 121 return sb.toString(); 122 } 123 }