package aima.core.logic.fol.kb.data;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import aima.core.logic.fol.inference.proof.ProofStep;
import aima.core.logic.fol.inference.proof.ProofStepChainContrapositive;
import aima.core.logic.fol.inference.proof.ProofStepPremise;
/**
*
* A Chain is a sequence of literals (while a clause is a set) - order is
* important for a chain.
*
* @see <a
* href="http://logic.stanford.edu/classes/cs157/2008/lectures/lecture13.pdf"
* >Chain</a>
*
* @author Ciaran O'Reilly
*
*/
public class Chain {
private static List<Literal> _emptyLiteralsList = Collections
.unmodifiableList(new ArrayList<Literal>());
//
private List<Literal> literals = new ArrayList<Literal>();
private ProofStep proofStep = null;
public Chain() {
// i.e. the empty chain
}
public Chain(List<Literal> literals) {
this.literals.addAll(literals);
}
public Chain(Set<Literal> literals) {
this.literals.addAll(literals);
}
public ProofStep getProofStep() {
if (null == proofStep) {
// Assume was a premise
proofStep = new ProofStepPremise(this);
}
return proofStep;
}
public void setProofStep(ProofStep proofStep) {
this.proofStep = proofStep;
}
public boolean isEmpty() {
return literals.size() == 0;
}
public void addLiteral(Literal literal) {
literals.add(literal);
}
public Literal getHead() {
if (0 == literals.size()) {
return null;
}
return literals.get(0);
}
public List<Literal> getTail() {
if (0 == literals.size()) {
return _emptyLiteralsList;
}
return Collections
.unmodifiableList(literals.subList(1, literals.size()));
}
public int getNumberLiterals() {
return literals.size();
}
public List<Literal> getLiterals() {
return Collections.unmodifiableList(literals);
}
/**
* A contrapositive of a chain is a permutation in which a different literal
* is placed at the front. The contrapositives of a chain are logically
* equivalent to the original chain.
*
* @return a list of contrapositives for this chain.
*/
public List<Chain> getContrapositives() {
List<Chain> contrapositives = new ArrayList<Chain>();
List<Literal> lits = new ArrayList<Literal>();
for (int i = 1; i < literals.size(); i++) {
lits.clear();
lits.add(literals.get(i));
lits.addAll(literals.subList(0, i));
lits.addAll(literals.subList(i + 1, literals.size()));
Chain cont = new Chain(lits);
cont.setProofStep(new ProofStepChainContrapositive(cont, this));
contrapositives.add(cont);
}
return contrapositives;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("<");
for (int i = 0; i < literals.size(); i++) {
if (i > 0) {
sb.append(",");
}
sb.append(literals.get(i).toString());
}
sb.append(">");
return sb.toString();
}
}