/*
* SyllogisticRules.java
*
* Copyright (C) 2008 Pei Wang
*
* This file is part of Open-NARS.
*
* Open-NARS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Open-NARS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the abduction warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Open-NARS. If not, see <http://www.gnu.org/licenses/>.
*/
package nars.inference;
import java.util.List;
import nars.config.Parameters;
import nars.control.DerivationContext;
import nars.entity.BudgetValue;
import nars.entity.Concept;
import nars.entity.Sentence;
import nars.entity.Stamp;
import nars.entity.Task;
import nars.entity.TruthValue;
import static nars.inference.TemporalRules.ORDER_BACKWARD;
import static nars.inference.TemporalRules.ORDER_FORWARD;
import static nars.inference.TemporalRules.ORDER_INVALID;
import static nars.inference.TemporalRules.ORDER_NONE;
import static nars.inference.TemporalRules.abdIndComOrder;
import static nars.inference.TemporalRules.analogyOrder;
import static nars.inference.TemporalRules.dedExeOrder;
import static nars.inference.TemporalRules.resemblanceOrder;
import static nars.inference.TemporalRules.reverseOrder;
import nars.io.Output;
import nars.io.Symbols;
import nars.io.Symbols.NativeOperator;
import nars.language.CompoundTerm;
import nars.language.Conjunction;
import nars.language.Equivalence;
import nars.language.Implication;
import nars.language.Interval;
import nars.language.Statement;
import nars.language.Term;
import nars.language.Terms;
import static nars.language.Terms.reduceComponents;
import nars.language.Variables;
/**
* Syllogisms: Inference rules based on the transitivity of the relation.
*/
public final class SyllogisticRules {
/* --------------- rules used in both first-tense inference and higher-tense inference --------------- */
/**
* <pre>
* {<S ==> M>, <M ==> P>} |- {<S ==> P>, <P ==> S>}
* </pre>
*
* @param term1 Subject of the first new task
* @param term2 Predicate of the first new task
* @param sentence The first premise
* @param belief The second premise
* @param nal Reference to the memory
*/
static void dedExe(Term term1, Term term2, Sentence sentence, Sentence belief, DerivationContext nal) {
if (Statement.invalidStatement(term1, term2)) {
return;
}
int order1 = sentence.term.getTemporalOrder();
int order2 = belief.term.getTemporalOrder();
int order = dedExeOrder(order1, order2);
if (order == ORDER_INVALID) {
return;
}
TruthValue value1 = sentence.truth;
TruthValue value2 = belief.truth;
TruthValue truth1 = null;
TruthValue truth2 = null;
BudgetValue budget1, budget2;
if (sentence.isQuestion()) {
budget1 = BudgetFunctions.backwardWeak(value2, nal);
budget2 = BudgetFunctions.backwardWeak(value2, nal);
} else if (sentence.isQuest()) {
budget1 = BudgetFunctions.backward(value2, nal);
budget2 = BudgetFunctions.backward(value2, nal);
} else {
if (sentence.isGoal()) {
truth1 = TruthFunctions.desireWeak(value1, value2);
truth2 = TruthFunctions.desireWeak(value1, value2);
} else {
// isJudgment
truth1 = TruthFunctions.deduction(value1, value2);
truth2 = TruthFunctions.exemplification(value1, value2);
}
budget1 = BudgetFunctions.forward(truth1, nal);
budget2 = BudgetFunctions.forward(truth2, nal);
}
Statement content = (Statement) sentence.term;
Statement content1 = Statement.make(content, term1, term2, order);
Statement content2 = Statement.make(content, term2, term1, reverseOrder(order));
if ((content1 == null) || (content2 == null))
return;
nal.doublePremiseTask(content1, truth1, budget1,false, false); //(allow overlap) but not needed here, isn't detachment
nal.doublePremiseTask(content2, truth2, budget2,false, false);
}
/**
* {<M ==> S>, <M ==> P>} |- {<S ==> P>, <P ==> S>, <S <=> P>}
*
* @param term1 Subject of the first new task
* @param term2 Predicate of the first new task
* @param sentence1 The first premise
* @param sentence2 The second premise
* @param figure Locations of the shared term in premises --- can be
* removed?
* @param nal Reference to the memory
*/
static void abdIndCom(final Term term1, final Term term2, final Sentence sentence1, final Sentence sentence2, final int figure, final DerivationContext nal) {
if (Statement.invalidStatement(term1, term2) || Statement.invalidPair(term1, term2)) {
return;
}
int order1 = sentence1.term.getTemporalOrder();
int order2 = sentence2.term.getTemporalOrder();
int order = abdIndComOrder(order1, order2);
Statement taskContent = (Statement) sentence1.term;
TruthValue truth1 = null;
TruthValue truth2 = null;
TruthValue truth3 = null;
BudgetValue budget1, budget2, budget3;
TruthValue value1 = sentence1.truth;
TruthValue value2 = sentence2.truth;
if (sentence1.isQuestion()) {
budget1 = BudgetFunctions.backward(value2, nal);
budget2 = BudgetFunctions.backwardWeak(value2, nal);
budget3 = BudgetFunctions.backward(value2, nal);
} else if (sentence1.isQuest()) {
budget1 = BudgetFunctions.backwardWeak(value2, nal);
budget2 = BudgetFunctions.backward(value2, nal);
budget3 = BudgetFunctions.backwardWeak(value2, nal);
} else {
if (sentence1.isGoal()) {
truth1 = TruthFunctions.desireStrong(value1, value2); //P --> S
truth2 = TruthFunctions.desireWeak(value2, value1); //S --> P
truth3 = TruthFunctions.desireStrong(value1, value2); //S <-> P
} else {
// isJudgment
truth1 = TruthFunctions.abduction(value1, value2); //P --> S
truth2 = TruthFunctions.abduction(value2, value1); //S --> P
truth3 = TruthFunctions.comparison(value1, value2); //S <-> P
}
budget1 = BudgetFunctions.forward(truth1, nal);
budget2 = BudgetFunctions.forward(truth2, nal);
budget3 = BudgetFunctions.forward(truth3, nal);
}
if (order != ORDER_INVALID) {
nal.doublePremiseTask(
Statement.make(taskContent, term1, term2, order),
truth1, budget1,false, false);
nal.doublePremiseTask(
Statement.make(taskContent, term2, term1, reverseOrder(order)),
truth2, budget2,false, false);
nal.doublePremiseTask(
Statement.makeSym(taskContent, term1, term2, order),
truth3, budget3,false, false);
}
if(Parameters.BREAK_NAL_HOL_BOUNDARY && order1==order2 && taskContent.isHigherOrderStatement() && sentence2.term.isHigherOrderStatement()) { //
/* Bridge to higher order statements:
<a ==> c>.
<b ==> c>.
|-
<a <-> b>. %F_cmp%
<a --> b>. %F_abd%
<b --> a>. %F_abd%
*/
/* if(truth1!=null)
truth1=truth1.clone();
if(truth2!=null)
truth2=truth2.clone();*/
if(truth3!=null)
truth3=truth3.clone();
/* nal.doublePremiseTask(
Statement.make(NativeOperator.INHERITANCE, term1, term2),
truth1, budget1.clone(),false, false);
nal.doublePremiseTask(
Statement.make(NativeOperator.INHERITANCE, term2, term1),
truth2, budget2.clone(),false, false);*/
nal.doublePremiseTask(
Statement.make(NativeOperator.SIMILARITY, term1, term2, TemporalRules.ORDER_NONE),
truth3, budget3.clone(),false, false);
}
}
/**
* {<S ==> P>, <M <=> P>} |- <S ==> P>
*
* @param subj Subject of the new task
* @param pred Predicate of the new task
* @param asym The asymmetric premise
* @param sym The symmetric premise
* @param figure Locations of the shared term in premises
* @param nal Reference to the memory
*/
static void analogy(Term subj, Term pred, Sentence asym, Sentence sym, int figure, DerivationContext nal) {
if (Statement.invalidStatement(subj, pred)) {
return;
}
int order1 = asym.term.getTemporalOrder();
int order2 = sym.term.getTemporalOrder();
int order = analogyOrder(order1, order2, figure);
if (order == ORDER_INVALID) {
return;
}
Statement st = (Statement) asym.term;
TruthValue truth = null;
BudgetValue budget;
Sentence sentence = nal.getCurrentTask().sentence;
CompoundTerm taskTerm = (CompoundTerm) sentence.term;
if (sentence.isQuestion() || sentence.isQuest()) {
if (taskTerm.isCommutative()) {
if(asym.truth==null) { //a question for example
return;
}
budget = BudgetFunctions.backwardWeak(asym.truth, nal);
} else {
if(sym.truth==null) { //a question for example
return;
}
budget = BudgetFunctions.backward(sym.truth, nal);
}
} else {
if (sentence.isGoal()) {
if (taskTerm.isCommutative()) {
truth = TruthFunctions.desireWeak(asym.truth, sym.truth);
} else {
truth = TruthFunctions.desireStrong(asym.truth, sym.truth);
}
} else {
truth = TruthFunctions.analogy(asym.truth, sym.truth);
}
budget = BudgetFunctions.forward(truth, nal);
}
//nal.mem().logic.ANALOGY.commit();
nal.doublePremiseTask( Statement.make(st, subj, pred, order), truth, budget,false, false); //(allow overlap) but not needed here, isn't detachment
}
/**
* {<S <=> M>, <M <=> P>} |- <S <=> P>
*
* @param term1 Subject of the new task
* @param term2 Predicate of the new task
* @param belief The first premise
* @param sentence The second premise
* @param figure Locations of the shared term in premises
* @param nal Reference to the memory
*/
static void resemblance(Term term1, Term term2, Sentence belief, Sentence sentence, int figure, DerivationContext nal) {
if (Statement.invalidStatement(term1, term2)) {
return;
}
int order1 = belief.term.getTemporalOrder();
int order2 = sentence.term.getTemporalOrder();
int order = resemblanceOrder(order1, order2, figure);
if (order == ORDER_INVALID) {
return;
}
Statement st = (Statement) belief.term;
TruthValue truth = null;
BudgetValue budget;
if (sentence.isQuestion() || sentence.isQuest()) {
budget = BudgetFunctions.backward(belief.truth, nal);
} else {
if (sentence.isGoal()) {
truth = TruthFunctions.desireStrong(sentence.truth, belief.truth);
} else {
truth = TruthFunctions.resemblance(belief.truth, sentence.truth);
}
budget = BudgetFunctions.forward(truth, nal);
}
boolean higherOrder=(belief.term.isHigherOrderStatement() || sentence.term.isHigherOrderStatement());
boolean bothHigherOrder=(belief.term.isHigherOrderStatement() && sentence.term.isHigherOrderStatement());
if(!bothHigherOrder && higherOrder) {
if(belief.term.isHigherOrderStatement()) {
order=belief.term.getTemporalOrder();
}
else
if(sentence.term.isHigherOrderStatement()) {
order=sentence.term.getTemporalOrder();
}
}
Statement s=Statement.make(higherOrder ? NativeOperator.EQUIVALENCE : NativeOperator.SIMILARITY, term1, term2, order);
//if(!Terms.equalSubTermsInRespectToImageAndProduct(term2, term2))
nal.doublePremiseTask( s, truth, budget,false, false); //(allow overlap) but not needed here, isn't detachment
// nal.doublePremiseTask( Statement.make(st, term1, term2, order), truth, budget,false, true );
if(Parameters.BREAK_NAL_HOL_BOUNDARY && !sentence.term.hasVarIndep() && (st instanceof Equivalence) && order1==order2 && belief.term.isHigherOrderStatement() && sentence.term.isHigherOrderStatement()) {
BudgetValue budget1=null, budget2=null, budget3=null;
TruthValue truth1=null, truth2=null, truth3=null;
TruthValue value1 = sentence.truth;
TruthValue value2 = belief.truth;
if (sentence.isQuestion()) {
/* budget1 = BudgetFunctions.backward(value2, nal);
budget2 = BudgetFunctions.backwardWeak(value2, nal);*/
budget3 = BudgetFunctions.backward(value2, nal);
} else if (sentence.isQuest()) {
/* budget1 = BudgetFunctions.backwardWeak(value2, nal);
budget2 = BudgetFunctions.backward(value2, nal);*/
budget3 = BudgetFunctions.backwardWeak(value2, nal);
} else {
if (sentence.isGoal()) {
/* truth1 = TruthFunctions.desireStrong(value1, value2);
truth2 = TruthFunctions.desireWeak(value2, value1);*/
truth3 = TruthFunctions.desireStrong(value1, value2);
} else {
// isJudgment
/* truth1 = TruthFunctions.abduction(value1, value2);
truth2 = TruthFunctions.abduction(value2, value1);*/
truth3 = TruthFunctions.comparison(value1, value2);
}
/*budget1 = BudgetFunctions.forward(truth1, nal);
budget2 = BudgetFunctions.forward(truth2, nal);*/
budget3 = BudgetFunctions.forward(truth3, nal);
}
/* Bridge to higher order statements:
<b <=> k>.
<b <=> c>.
|-
<k <-> c>. %F_cmp%
*/
/* nal.doublePremiseTask(
Statement.make(NativeOperator.INHERITANCE, term1, term2),
truth1, budget1.clone(),false, false);
nal.doublePremiseTask(
Statement.make(NativeOperator.INHERITANCE, term2, term1),
truth2, budget2.clone(),false, false);*/
nal.doublePremiseTask(
Statement.make(NativeOperator.SIMILARITY, term1, term2, TemporalRules.ORDER_NONE),
truth3, budget3.clone(),false, false);
}
}
/* --------------- rules used only in conditional inference --------------- */
/**
* {<<M --> S> ==> <M --> P>>, <M --> S>} |- <M --> P> {<<M --> S> ==> <M
* --> P>>, <M --> P>} |- <M --> S> {<<M --> S> <=> <M --> P>>, <M --> S>}
* |- <M --> P> {<<M --> S> <=> <M --> P>>, <M --> P>} |- <M --> S>
*
* @param mainSentence The implication/equivalence premise
* @param subSentence The premise on part of s1
* @param side The location of s2 in s1
* @param nal Reference to the memory
*/
static void detachment(Sentence mainSentence, Sentence subSentence, int side, DerivationContext nal) {
Statement statement = (Statement) mainSentence.term;
if (!(statement instanceof Implication) && !(statement instanceof Equivalence)) {
return;
}
Term subject = statement.getSubject();
Term predicate = statement.getPredicate();
Term content;
Term term = subSentence.term;
if ((side == 0) && term.equals(subject)) {
content = predicate;
} else if ((side == 1) && term.equals(predicate)) {
content = subject;
} else {
return;
}
if ((content instanceof Statement) && ((Statement) content).invalid()) {
return;
}
Sentence taskSentence = nal.getCurrentTask().sentence;
Sentence beliefSentence = nal.getCurrentBelief();
if (beliefSentence == null)
return;
int order = statement.getTemporalOrder();
boolean shiftedTimeForward = false;
if ((order != ORDER_NONE) && (order!=ORDER_INVALID) && (!taskSentence.isGoal()) && (!taskSentence.isQuest())) {
long baseTime = subSentence.getOccurenceTime();
if (baseTime == Stamp.ETERNAL) {
baseTime = nal.getTime();
}
long inc = order * nal.mem().param.duration.get();
long time = (side == 0) ? baseTime+inc : baseTime-inc;
shiftedTimeForward = (side == 0);
nal.getTheNewStamp().setOccurrenceTime(time);
}
TruthValue beliefTruth = beliefSentence.truth;
TruthValue truth1 = mainSentence.truth;
TruthValue truth2 = subSentence.truth;
TruthValue truth = null;
boolean strong = false;
BudgetValue budget;
if (taskSentence.isQuestion()) {
if (statement instanceof Equivalence) {
budget = BudgetFunctions.backward(beliefTruth, nal);
} else if (side == 0) {
budget = BudgetFunctions.backwardWeak(beliefTruth, nal);
} else {
budget = BudgetFunctions.backward(beliefTruth, nal);
}
} else if (taskSentence.isQuest()) {
if (statement instanceof Equivalence) {
budget = BudgetFunctions.backwardWeak(beliefTruth, nal);
} else if (side == 0) {
budget = BudgetFunctions.backward(beliefTruth, nal);
} else {
budget = BudgetFunctions.backwardWeak(beliefTruth, nal);
}
} else {
if (taskSentence.isGoal()) {
if (statement instanceof Equivalence) {
truth = TruthFunctions.desireStrong(truth1, truth2);
strong = true; //not for goals anymore
} else if (side == 0) {
truth = TruthFunctions.desireInd(truth1, truth2);
} else {
truth = TruthFunctions.desireDed(truth1, truth2);
strong = true; //not for goals anymore
}
} else { // isJudgment
if (statement instanceof Equivalence) {
truth = TruthFunctions.analogy(truth2, truth1);
strong = true;
} else if (side == 0) {
truth = TruthFunctions.deduction(truth1, truth2);
strong = true;
} else {
truth = TruthFunctions.abduction(truth2, truth1);
}
}
budget = BudgetFunctions.forward(truth, nal);
}
if(!Variables.indepVarUsedInvalid(content)) {
boolean allowOverlap = taskSentence.isJudgment() && strong;
List<Task> ret = nal.doublePremiseTask(content, truth, budget, false, allowOverlap); //(strong) when strong on judgement
if(shiftedTimeForward && ret != null && ret.size() > 0 && mainSentence.isEternal() && taskSentence.isJudgment() && mainSentence.isJudgment() && shiftedTimeForward) {
//discountPredictiveHypothesis(nal, mainSentence, budget);
// SyllogisticRules.generatePotentialNegConfirmation(nal, mainSentence, budget, mintime, maxtime, 1);
}
}
}
public static void generatePotentialNegConfirmation(DerivationContext nal, Sentence mainSentence, BudgetValue budget, long mintime, long maxtime, float priority) {
//derivation was successful and it was a judgment event
try { //that was predicted by an eternal belief that shifted time
float immediateDisappointmentConfidence = 0.1f;
Stamp stamp = new Stamp(nal.memory);
stamp.setOccurrenceTime(Stamp.ETERNAL);
//long serial = stamp.evidentialBase[0];
Sentence s = new Sentence(mainSentence.term, mainSentence.punctuation, new TruthValue(0.0f, immediateDisappointmentConfidence), stamp);
//s.producedByTemporalInduction = true; //also here to not go into sequence buffer
Task t = new Task(s, new BudgetValue(0.99f,0.1f,0.1f)); //Budget for one-time processing
Concept c = nal.memory.concept(((Statement) mainSentence.term).getPredicate()); //put into consequence concept
if(c != null /*&& mintime > nal.memory.time()*/ && c.observable && mainSentence.getTerm() instanceof Statement && ((Statement)mainSentence.getTerm()).getTemporalOrder() == TemporalRules.ORDER_FORWARD) {
if(c.negConfirmation == null || priority > c.negConfirmationPriority /*|| t.getPriority() > c.negConfirmation.getPriority() */) {
c.negConfirmation = t;
c.negConfirmationPriority = priority;
c.negConfirm_abort_maxtime = maxtime;
c.negConfirm_abort_mintime = mintime;
nal.memory.emit(Output.ANTICIPATE.class,((Statement) c.negConfirmation.sentence.term).getPredicate()); //disappoint/confirm printed anyway
}
}
}catch(Exception ex) {
System.out.println("problem in anticipation handling");
}
}
/**
* {<(&&, S1, S2, S3) ==> P>, S1} |- <(&&, S2, S3) ==> P> {<(&&, S2, S3) ==>
* P>, <S1 ==> S2>} |- <(&&, S1, S3) ==> P> {<(&&, S1, S3) ==> P>, <S1 ==>
* S2>} |- <(&&, S2, S3) ==> P>
*
* @param premise1 The conditional premise
* @param index The location of the shared term in the condition of premise1
* @param premise2 The premise which, or part of which, appears in the
* condition of premise1
* @param side The location of the shared term in premise2: 0 for subject, 1
* for predicate, -1 for the whole term
* @param nal Reference to the memory
*/
static void conditionalDedInd(Sentence premise1Sentence, Implication premise1, short index, Term premise2, int side, DerivationContext nal) {
Task task = nal.getCurrentTask();
Sentence taskSentence = task.sentence;
Sentence belief = nal.getCurrentBelief();
boolean deduction = (side != 0);
boolean conditionalTask = Variables.hasSubstitute(Symbols.VAR_INDEPENDENT, premise2, belief.term);
Term commonComponent;
Term newComponent = null;
if (side == 0) {
commonComponent = ((Statement) premise2).getSubject();
newComponent = ((Statement) premise2).getPredicate();
} else if (side == 1) {
commonComponent = ((Statement) premise2).getPredicate();
newComponent = ((Statement) premise2).getSubject();
} else {
commonComponent = premise2;
}
Term subj = premise1.getSubject();
if (!(subj instanceof Conjunction)) {
return;
}
Conjunction oldCondition = (Conjunction) subj;
int index2 = Terms.indexOf(oldCondition.term,commonComponent);
if (index2 >= 0) {
index = (short) index2;
} else {
Term[] u = new Term[] { premise1, premise2 };
boolean match = Variables.unify(Symbols.VAR_INDEPENDENT, oldCondition.term[index], commonComponent, u);
premise1 = (Implication) u[0]; premise2 = u[1];
if (!match && (commonComponent.getClass() == oldCondition.getClass())) {
CompoundTerm compoundCommonComponent = ((CompoundTerm) commonComponent);
if ((oldCondition.term.length > index) && (compoundCommonComponent.term.length > index)) { // assumption: { was missing
u = new Term[] { premise1, premise2 };
match = Variables.unify(Symbols.VAR_INDEPENDENT,
oldCondition.term[index],
compoundCommonComponent.term[index],
u);
premise1 = (Implication) u[0]; premise2 = u[1];
}
}
if (!match) {
return;
}
}
int conjunctionOrder = subj.getTemporalOrder();
if (conjunctionOrder == ORDER_FORWARD) {
if (index > 0) {
return;
}
if ((side == 0) && (premise2.getTemporalOrder() == ORDER_FORWARD)) {
return;
}
if ((side == 1) && (premise2.getTemporalOrder() == ORDER_BACKWARD)) {
return;
}
}
Term newCondition;
if (oldCondition.equals(commonComponent)) {
newCondition = null;
} else {
newCondition = oldCondition.setComponent(index, newComponent, nal.mem());
}
Term content;
long delta = 0;
long mintime = 0;
long maxtime = 0;
boolean predictedEvent = false;
final Interval.AtomicDuration duration = nal.mem().param.duration;
if (newCondition != null) {
if (newCondition instanceof Interval) {
content = premise1.getPredicate();
delta = ((Interval) newCondition).getTime(duration);
if(taskSentence.getOccurenceTime() != Stamp.ETERNAL) {
mintime = taskSentence.getOccurenceTime() + Interval.magnitudeToTime(((Interval) newCondition).magnitude - 1, duration);
maxtime = taskSentence.getOccurenceTime() + Interval.magnitudeToTime(((Interval) newCondition).magnitude + 2, duration);
predictedEvent = true;
}
} else if ((newCondition instanceof Conjunction) && (((CompoundTerm) newCondition).term[0] instanceof Interval)) {
Interval interval = (Interval) ((CompoundTerm) newCondition).term[0];
delta = interval.getTime(duration);
newCondition = ((CompoundTerm)newCondition).setComponent(0, null, nal.mem());
content = Statement.make(premise1, newCondition, premise1.getPredicate(), premise1.getTemporalOrder());
} else {
content = Statement.make(premise1, newCondition, premise1.getPredicate(), premise1.getTemporalOrder());
}
} else {
content = premise1.getPredicate();
}
if (content == null)
return;
if(!predictedEvent && ((Conjunction) subj).getTemporalOrder() == TemporalRules.ORDER_FORWARD) { //do not allow sequences
boolean last_ival = false; //which have two intervals as result of this, makes sure we only detach (&/ from left side
for(Term t: ((Conjunction) subj).term) {
boolean ival = t instanceof Interval;
if(last_ival && ival) {
return;
}
last_ival = ival;
}
}
if (delta != 0) {
long baseTime = (belief.term instanceof Implication) ?
taskSentence.getOccurenceTime() : belief.getOccurenceTime();
if (baseTime == Stamp.ETERNAL) {
baseTime = nal.getTime();
}
if(premise1.getTemporalOrder()==TemporalRules.ORDER_CONCURRENT)
return; //https://groups.google.com/forum/#!topic/open-nars/ZfCM416Dx1M - Interval Simplification
baseTime += delta;
nal.getTheNewStamp().setOccurrenceTime(baseTime);
}
TruthValue truth1 = taskSentence.truth;
TruthValue truth2 = belief.truth;
TruthValue truth = null;
BudgetValue budget;
if (taskSentence.isQuestion() || taskSentence.isQuest()) {
budget = BudgetFunctions.backwardWeak(truth2, nal);
} else {
if (taskSentence.isGoal()) {
if (conditionalTask) {
truth = TruthFunctions.desireWeak(truth1, truth2);
} else if (deduction) {
truth = TruthFunctions.desireInd(truth1, truth2);
} else {
truth = TruthFunctions.desireDed(truth1, truth2);
}
} else {
if (deduction) {
truth = TruthFunctions.deduction(truth1, truth2);
} else if (conditionalTask) {
truth = TruthFunctions.induction(truth2, truth1);
} else {
truth = TruthFunctions.induction(truth1, truth2);
}
}
budget = BudgetFunctions.forward(truth, nal);
}
List<Task> ret = nal.doublePremiseTask(content, truth, budget,false, taskSentence.isJudgment() && deduction); //(allow overlap) when deduction on judgment
if(!nal.evidentalOverlap && ret != null && ret.size() > 0) {
if(predictedEvent && taskSentence.isJudgment() && truth != null && truth.getExpectation() > Parameters.DEFAULT_CONFIRMATION_EXPECTATION &&
!premise1Sentence.stamp.alreadyAnticipatedNegConfirmation) {
premise1Sentence.stamp.alreadyAnticipatedNegConfirmation = true;
SyllogisticRules.generatePotentialNegConfirmation(nal, premise1Sentence, budget, mintime, maxtime, 1);
}
}
}
/**
* {<(&&, S1, S2, S3) <=> P>, S1} |- <(&&, S2, S3) <=> P> {<(&&, S2, S3) <=> P>,
* <S1 ==> S2>} |- <(&&, S1, S3) <=> P> {<(&&, S1, S3) <=> P>, <S1 ==>
*
* @param premise1 The equivalence premise
* @param index The location of the shared term in the condition of premise1
* @param premise2 The premise which, or part of which, appears in the
* condition of premise1
* @param side The location of the shared term in premise2: 0 for subject, 1
* for predicate, -1 for the whole term
* @param nal Reference to the memory
*/
static void conditionalAna(Equivalence premise1, short index, Term premise2, int side, DerivationContext nal) {
Task task = nal.getCurrentTask();
Sentence taskSentence = task.sentence;
Sentence belief = nal.getCurrentBelief();
boolean conditionalTask = Variables.hasSubstitute(Symbols.VAR_INDEPENDENT, premise2, belief.term);
Term commonComponent;
Term newComponent = null;
if (side == 0) {
commonComponent = ((Statement) premise2).getSubject();
newComponent = ((Statement) premise2).getPredicate();
} else if (side == 1) {
commonComponent = ((Statement) premise2).getPredicate();
newComponent = ((Statement) premise2).getSubject();
} else {
commonComponent = premise2;
}
Term tm = premise1.getSubject();
if (!(tm instanceof Conjunction)) {
return;
}
Conjunction oldCondition = (Conjunction) tm;
Term[] u = new Term[] { premise1, premise2 };
boolean match = Variables.unify(Symbols.VAR_DEPENDENT, oldCondition.term[index], commonComponent, u);
premise1 = (Equivalence) u[0]; premise2 = u[1];
if (!match && (commonComponent.getClass() == oldCondition.getClass())) {
u = new Term[] { premise1, premise2 };
match = Variables.unify(Symbols.VAR_DEPENDENT, oldCondition.term[index], ((CompoundTerm) commonComponent).term[index], u);
premise1 = (Equivalence) u[0]; premise2 = u[1];
}
if (!match) {
return;
}
int conjunctionOrder = oldCondition.getTemporalOrder();
if (conjunctionOrder == ORDER_FORWARD) {
if (index > 0) {
return;
}
if ((side == 0) && (premise2.getTemporalOrder() == ORDER_FORWARD)) {
return;
}
if ((side == 1) && (premise2.getTemporalOrder() == ORDER_BACKWARD)) {
return;
}
}
Term newCondition;
if (oldCondition.equals(commonComponent)) {
newCondition = null;
} else {
newCondition = oldCondition.setComponent(index, newComponent, nal.mem());
}
Term content;
if (newCondition != null) {
content = Statement.make(premise1, newCondition, premise1.getPredicate(), premise1.getTemporalOrder());
} else {
content = premise1.getPredicate();
}
if (content == null)
return;
TruthValue truth1 = taskSentence.truth;
TruthValue truth2 = belief.truth;
TruthValue truth = null;
BudgetValue budget;
if (taskSentence.isQuestion() || taskSentence.isQuest()) {
budget = BudgetFunctions.backwardWeak(truth2, nal);
} else {
if (taskSentence.isGoal()) {
if (conditionalTask) {
truth = TruthFunctions.desireWeak(truth1, truth2);
} else {
truth = TruthFunctions.desireDed(truth1, truth2);
}
} else {
if (conditionalTask) {
truth = TruthFunctions.comparison(truth1, truth2);
} else {
truth = TruthFunctions.analogy(truth1, truth2);
}
}
budget = BudgetFunctions.forward(truth, nal);
}
nal.doublePremiseTask(content, truth, budget, false, taskSentence.isJudgment() && !conditionalTask); //(allow overlap) when !conditionalTask on judgment
}
/**
* {<(&&, S2, S3) ==> P>, <(&&, S1, S3) ==> P>} |- <S1 ==> S2>
*
* @param cond1 The condition of the first premise
* @param cond2 The condition of the second premise
* @param taskContent The first premise
* @param st2 The second premise
* @param nal Reference to the memory
* @return Whether there are derived tasks
*/
static boolean conditionalAbd(Term cond1, Term cond2, Statement st1, Statement st2, DerivationContext nal) {
if (!(st1 instanceof Implication) || !(st2 instanceof Implication)) {
return false;
}
if (!(cond1 instanceof Conjunction) && !(cond2 instanceof Conjunction)) {
return false;
}
int order1 = st1.getTemporalOrder();
int order2 = st2.getTemporalOrder();
if (order1 != reverseOrder(order2)) {
return false;
}
Term term1 = null;
Term term2 = null;
// if ((cond1 instanceof Conjunction) && !Variable.containVarDep(cond1.getName())) {
if (cond1 instanceof Conjunction) {
term1 = reduceComponents((CompoundTerm) cond1, cond2, nal.mem());
}
// if ((cond2 instanceof Conjunction) && !Variable.containVarDep(cond2.getName())) {
if (cond2 instanceof Conjunction) {
term2 = reduceComponents((CompoundTerm) cond2, cond1, nal.mem());
}
if ((term1 == null) && (term2 == null)) {
return false;
}
Task task = nal.getCurrentTask();
Sentence sentence = task.sentence;
Sentence belief = nal.getCurrentBelief();
TruthValue value1 = sentence.truth;
TruthValue value2 = belief.truth;
Term content;
boolean keepOrder = Variables.hasSubstitute(Symbols.VAR_INDEPENDENT, st1, task.getTerm());
TruthValue truth = null;
BudgetValue budget;
//is this correct because the second term2!=null condition may overwrite the first
//should the inner if be: if (term2 == null) then it makes sense.
if (term1 != null) {
if (term2 != null) {
content = Statement.make(st2, term2, term1, st2.getTemporalOrder());
} else {
content = term1;
if(content.hasVarIndep()) {
return false;
}
}
if (sentence.isQuestion() || sentence.isQuest()) {
budget = BudgetFunctions.backwardWeak(value2, nal);
} else {
if (sentence.isGoal()) {
if (keepOrder) {
truth = TruthFunctions.desireDed(value1, value2);
} else {
truth = TruthFunctions.desireInd(value1, value2);
}
} else { // isJudgment
truth = TruthFunctions.abduction(value2, value1);
}
budget = BudgetFunctions.forward(truth, nal);
}
nal.doublePremiseTask(content, truth, budget,false, false);
}
if (term2 != null) {
if (term1 != null) {
content = Statement.make(st1, term1, term2, st1.getTemporalOrder());
} else {
content = term2;
if(content.hasVarIndep()) {
return false;
}
}
if (sentence.isQuestion() || sentence.isQuest()) {
budget = BudgetFunctions.backwardWeak(value2, nal);
} else {
if (sentence.isGoal()) {
if (keepOrder) {
truth = TruthFunctions.desireDed(value1, value2);
} else {
truth = TruthFunctions.desireInd(value1, value2);
}
} else { // isJudgment
truth = TruthFunctions.abduction(value1, value2);
}
budget = BudgetFunctions.forward(truth, nal);
}
nal.doublePremiseTask(content, truth, budget,false, false);
}
return true;
}
/**
* {(&&, <#x() --> S>, <#x() --> P>>, <M --> P>} |- <M --> S>
*
* @param compound The compound term to be decomposed
* @param component The part of the compound to be removed
* @param compoundTask Whether the compound comes from the task
* @param nal Reference to the memory
*/
static void elimiVarDep(CompoundTerm compound, Term component, boolean compoundTask, DerivationContext nal) {
Term comp = null;
for(Term t : compound) {
Term[] unify = new Term[] { t, component };
if(Variables.unify(Symbols.VAR_DEPENDENT, unify)) {
comp = t;
break;
}
}
if(comp == null) {
return;
}
Term content = reduceComponents(compound, comp, nal.mem());
if ((content == null) || ((content instanceof Statement) && ((Statement) content).invalid())) {
return;
}
Task task = nal.getCurrentTask();
Sentence sentence = task.sentence;
Sentence belief = nal.getCurrentBelief();
TruthValue v1 = sentence.truth;
TruthValue v2 = belief.truth;
TruthValue truth = null;
BudgetValue budget;
if (sentence.isQuestion() || sentence.isQuest()) {
budget = (compoundTask ? BudgetFunctions.backward(v2, nal) : BudgetFunctions.backwardWeak(v2, nal));
} else {
if (sentence.isGoal()) {
truth = (compoundTask ? TruthFunctions.desireDed(v1, v2) : TruthFunctions.desireInd(v1, v2)); // to check
} else {
truth = (compoundTask ? TruthFunctions.anonymousAnalogy(v1, v2) : TruthFunctions.anonymousAnalogy(v2, v1));
}
budget = BudgetFunctions.compoundForward(truth, content, nal);
}
nal.doublePremiseTask(content, truth, budget,false, false);
}
}