///////////////////////////////////////////////////////////////////////
// STANFORD LOGIC GROUP //
// General Game Playing Project //
// //
// Sample Player Implementation //
// //
// (c) 2007. See LICENSE and CONTRIBUTORS. //
///////////////////////////////////////////////////////////////////////
/**
*
*/
package stanfordlogic.prover;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import stanfordlogic.prover.Implication;
import stanfordlogic.prover.Conjunction;
import stanfordlogic.prover.Substitution;
import stanfordlogic.gdl.Parser;
import stanfordlogic.knowledge.KnowledgeBase;
import stanfordlogic.game.GameManager;
/**
*
*/
public class BasicReasoner extends AbstractReasoner
{
private static final Logger logger_ = Logger.getLogger("stanfordlogic.prover");
public BasicReasoner(KnowledgeBase kb, Map<Integer, List<Implication>> rules, Parser p)
{
super(kb, rules, p);
}
public BasicReasoner(KnowledgeBase kb, List<Implication> rules, Parser p)
{
super(kb, rules, p);
}
@Override
public List<GroundFact> getAllAnswers(Fact f, ProofContext context)
{
long startTime = System.nanoTime();
List<GroundFact> answers = new ArrayList<GroundFact>();
logger_.fine(" ---------- Beginning new proof request (multi) ----------");
List<Substitution> subs = proveFact(f, context, true);
if(subs != null)
{
for(Substitution sub : subs)
{
GroundFact res = (GroundFact) f.applySubstitution(sub);
if(!answers.contains(res))
answers.add(res);
}
}
GameManager.addTime(GameManager.TIME_GET_ALL_ANSWERS, System.nanoTime() - startTime);
return answers;
}
@Override
public Iterable<GroundFact> getAllAnswersIterable( Fact question, ProofContext context )
{
return getAllAnswers(question, context);
}
@Override
public GroundFact getAnAnswer(Fact f, ProofContext context)
{
long startTime = System.nanoTime();
logger_.fine(" ---------- Beginning new proof request (single) ----------");
Substitution s = proveOne(f, context);
GameManager.addTime(GameManager.TIME_GET_AN_ANSWER, System.nanoTime() - startTime);
// No proof?
if (s == null)
return null;
// Proof: apply and return.
return (GroundFact) f.applySubstitution(s);
}
/////////////////////////////////////
// IMPLEMENTATION OF PROOF SYSTEM: //
/////////////////////////////////////
private List<Substitution> prove(Expression exp, ProofContext context, boolean proveAll)
{
if (exp instanceof Fact) {
return proveFact((Fact) exp, context, proveAll);
}
else if (exp instanceof Conjunction) {
return proveConjunction((Conjunction) exp, context, proveAll);
}
else if (exp instanceof Negation) {
return proveNegation((Negation) exp, context, proveAll);
}
else if (exp instanceof Disjunction) {
return proveDisjunction((Disjunction) exp, context, proveAll);
}
else {
logger_.severe("Cannot prove expression of type " + exp.getClass().getName());
return null;
}
}
private Substitution proveOne(Expression exp, ProofContext context)
{
List<Substitution> proofs = prove(exp, context, false);
if (proofs == null) {
return null;
}
else
{
if (proofs.size() > 1) {
logger_.warning("proveAll with getAll==false returned >1 results");
}
return proofs.get(0);
}
}
private List<Substitution> proveFact(Fact f, ProofContext context, boolean proveAll)
{
context.enterProof(f, proveAll);
// Special case for distinct.
if (isDistinctFact(f))
{
if (checkDistinct((GroundFact) f))
{
// Success
context.exitProof(f, true, EMPTY_SUB);
return EMPTY_SUB_LIST;
}
else
{
// Failure
context.exitProof(f, false, EMPTY_SUB);
return null;
}
}
List<Substitution> results = new ArrayList<Substitution>();
// If this is a ground fact, just check if it's in our KB
if (f instanceof GroundFact)
{
if (findGround((GroundFact) f, context))
{
context.exitProof(f, true, EMPTY_SUB);
return EMPTY_SUB_LIST;
}
}
// Otherwise, try to find all things unifiable with it
else
{
Iterable<Substitution> similar = getUnifiableGrounds((VariableFact) f, context);
for ( Substitution u: similar )
{
// Success!
results.add(u);
// Should we stop here?
if (!proveAll) {
context.exitProof(f, true, u);
return results;
}
}
}
// OK, we also need to check for rules that can be applied.
Iterable<Implication> rules = getRules(f);
for ( Implication rule : rules )
{
rule = rule.uniquefy();
Substitution unification = f.unify(rule.getConsequent());
// Stop if unification fails.
if ( unification == null )
continue;
context.reportRuleHead(rule.getConsequent(), unification);
Conjunction conjuncts =
(Conjunction) rule.getAntecedents().applySubstitution(unification);
List<Substitution> ruleResults = proveConjunction(conjuncts, context, proveAll);
if ( ruleResults != null )
{
for (Substitution sub: ruleResults)
{
Substitution s = unification.copy(sub);
results.add(s);
if (!proveAll) {
// we can just stop here.
context.exitProof(f, true, s);
return results;
}
}
}
}
if ( results.size() == 0 )
{
// Failure.
context.exitProof(f, false, results);
return null;
}
else
{
// Success.
context.exitProof(f, true, results);
return results;
}
}
private List<Substitution> proveConjunction(Conjunction conjuncts, ProofContext context, boolean getAll)
{
context.enterProof(conjuncts, true);
List<Substitution> overallSubs = new ArrayList<Substitution>();
overallSubs.add(EMPTY_SUB);
List<Substitution> levelSubs = new ArrayList<Substitution>();
List<Substitution> tempSubs;
Expression [] sentences = conjuncts.getConjuncts();
for ( int i = 0; i < sentences.length; i++ )
{
for(Substitution currentSub : overallSubs)
{
tempSubs = prove(sentences[i].applySubstitution(currentSub), context, true);
if(tempSubs != null)
{
for ( Substitution sub : tempSubs )
levelSubs.add( currentSub.copy(sub) );
}
}
if(levelSubs.size() == 0)
{
overallSubs.clear();
context.exitProof(conjuncts, false, overallSubs);
return null;
}
overallSubs.clear();
overallSubs.addAll(levelSubs);
levelSubs.clear();
}
context.exitProof(conjuncts, true, overallSubs);
return overallSubs;
}
private List<Substitution> proveNegation(Negation s, ProofContext context, boolean proveAll)
{
context.enterProof(s, proveAll);
Substitution result = proveOne(s.getNegated(), context);
// Make sure we *failed* the proof.
if ( result == null ) {
List<Substitution> res = new ArrayList<Substitution>(1);
res.add(EMPTY_SUB);
context.exitProof(s, false, EMPTY_SUB);
return res;
}
else {
return null;
}
}
private List<Substitution> proveDisjunction(Disjunction s, ProofContext context, boolean proveAll)
{
context.enterProof(s, proveAll);
List<Substitution> results;
results = new ArrayList<Substitution>();
Expression [] disjuncts = s.getDisjuncts();
for ( Expression disjunct : disjuncts )
{
List<Substitution> result = prove(disjunct, context, proveAll);
if ( result != null )
{
results.addAll(result);
// should we stop here?
if (!proveAll) {
context.exitProof(s, true, result);
return results;
}
}
}
if ( results.size() == 0 )
{
context.exitProof(s, false, results);
return null;
}
else
{
context.exitProof(s, true, results);
return results;
}
}
}