/*
* StructuralRules.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.storage.Memory;
import nars.control.DerivationContext;
import nars.entity.BudgetValue;
import nars.entity.Sentence;
import nars.entity.Task;
import nars.entity.TruthValue;
import nars.io.Symbols;
import nars.language.CompoundTerm;
import nars.language.Conjunction;
import nars.language.DifferenceExt;
import nars.language.DifferenceInt;
import nars.language.Disjunction;
import nars.language.Equivalence;
import nars.language.ImageExt;
import nars.language.ImageInt;
import nars.language.Implication;
import nars.language.Inheritance;
import nars.language.IntersectionExt;
import nars.language.IntersectionInt;
import nars.language.Negation;
import nars.language.Product;
import nars.language.SetExt;
import nars.language.SetInt;
import nars.language.Similarity;
import nars.language.Statement;
import nars.language.Term;
import nars.language.Terms;
/**
* Single-premise inference rules involving compound terms. Input are one
* sentence (the premise) and one TermLink (indicating a component)
*/
public final class StructuralRules {
/* -------------------- transform between compounds and term -------------------- */
/**
* {<S --> P>, S@(S&T)} |- <(S&T) --> (P&T)> {<S --> P>, S@(M-S)} |- <(M-P)
* --> (M-S)>
*
* @param compound The compound term
* @param index The location of the indicated term in the compound
* @param statement The premise
* @param side The location of the indicated term in the premise
* @param nal Reference to the memory
*/
static void structuralCompose2(CompoundTerm compound, short index, Statement statement, short side, DerivationContext nal) {
final Memory mem = nal.mem();
if (compound.equals(statement.term[side])) {
return;
}
/*if (!memory.getCurrentTask().sentence.isJudgment() || (compound.size() == 1)) {
return; // forward inference only
}*/
Term sub = statement.getSubject();
Term pred = statement.getPredicate();
List<Term> components = compound.asTermList();
if (((side == 0) && components.contains(pred)) || ((side == 1) && components.contains(sub))) {
return;
}
if (side == 0) {
if (components.contains(sub)) {
sub = compound;
components.set(index, pred);
pred = Terms.term(compound, components);
}
} else {
if (components.contains(pred)) {
components.set(index, sub);
sub = Terms.term(compound, components);
pred = compound;
}
}
if ((sub == null) || (pred == null))
return;
Statement content;
int order = statement.getTemporalOrder();
if (switchOrder(compound, index)) {
content = Statement.make(statement, pred, sub, TemporalRules.reverseOrder(order));
} else {
content = Statement.make(statement, sub, pred, order);
}
if (content == null)
return;
Sentence sentence = nal.getCurrentTask().sentence;
TruthValue truth = TruthFunctions.deduction(sentence.truth, Parameters.reliance);
BudgetValue budget = BudgetFunctions.compoundForward(truth, content, nal);
nal.singlePremiseTask(content, truth, budget);
}
/**
* {<(S*T) --> (P*T)>, S@(S*T)} |- <S --> P>
*
* @param statement The premise
* @param nal Reference to the memory
*/
static void structuralDecompose2(Statement statement, int index, DerivationContext nal) {
Term subj = statement.getSubject();
Term pred = statement.getPredicate();
if (subj.getClass() != pred.getClass()) {
return;
}
if (!(subj instanceof Product) && !(subj instanceof SetExt) && !(subj instanceof SetInt)) {
return; // no abduction on other compounds for now, but may change in the future
}
CompoundTerm sub = (CompoundTerm) subj;
CompoundTerm pre = (CompoundTerm) pred;
if (sub.size() != pre.size() || sub.size() <= index) {
return;
}
Term t1 = sub.term[index];
Term t2 = pre.term[index];
Statement content;
int order = statement.getTemporalOrder();
if (switchOrder(sub, (short) index)) {
content = Statement.make(statement, t2, t1, TemporalRules.reverseOrder(order));
} else {
content = Statement.make(statement, t1, t2, order);
}
if (content == null) {
return;
}
Task task = nal.getCurrentTask();
Sentence sentence = task.sentence;
TruthValue truth = sentence.truth;
BudgetValue budget;
if (sentence.isQuestion() || sentence.isQuest()) {
budget = BudgetFunctions.compoundBackward(content, nal);
} else {
budget = BudgetFunctions.compoundForward(truth, content, nal);
}
nal.singlePremiseTask(content, truth, budget);
}
/**
* List the cases where the direction of inheritance is revised in
* conclusion
*
* @param compound The compound term
* @param index The location of focus in the compound
* @return Whether the direction of inheritance should be revised
*/
private static boolean switchOrder(CompoundTerm compound, short index) {
return ((((compound instanceof DifferenceExt) || (compound instanceof DifferenceInt)) && (index == 1))
|| ((compound instanceof ImageExt) && (index != ((ImageExt) compound).relationIndex))
|| ((compound instanceof ImageInt) && (index != ((ImageInt) compound).relationIndex)));
}
/**
* {<S --> P>, P@(P|Q)} |- <S --> (P|Q)>
*
* @param compound The compound term
* @param index The location of the indicated term in the compound
* @param statement The premise
* @param nal Reference to the memory
*/
static void structuralCompose1(CompoundTerm compound, short index, Statement statement, DerivationContext nal) {
if (!nal.getCurrentTask().sentence.isJudgment()) {
return; // forward inference only
}
Term component = compound.term[index];
Task task = nal.getCurrentTask();
Sentence sentence = task.sentence;
int order = sentence.getTemporalOrder();
TruthValue truth = sentence.truth;
final float reliance = Parameters.reliance;
TruthValue truthDed = TruthFunctions.deduction(truth, reliance);
TruthValue truthNDed = TruthFunctions.negation(TruthFunctions.deduction(truth, reliance));
Term subj = statement.getSubject();
Term pred = statement.getPredicate();
if (component.equals(subj)) {
if (compound instanceof IntersectionExt) {
structuralStatement(compound, pred, order, truthDed, nal);
} else if (compound instanceof IntersectionInt) {
} else if ((compound instanceof DifferenceExt) && (index == 0)) {
structuralStatement(compound, pred, order, truthDed, nal);
} else if (compound instanceof DifferenceInt) {
if (index == 0) {
} else {
structuralStatement(compound, pred, order, truthNDed, nal);
}
}
} else if (component.equals(pred)) {
if (compound instanceof IntersectionExt) {
} else if (compound instanceof IntersectionInt) {
structuralStatement(subj, compound, order, truthDed, nal);
} else if (compound instanceof DifferenceExt) {
if (index == 0) {
} else {
structuralStatement(subj, compound, order, truthNDed, nal);
}
} else if ((compound instanceof DifferenceInt) && (index == 0)) {
structuralStatement(subj, compound, order, truthDed, nal);
}
}
}
/**
* {<(S|T) --> P>, S@(S|T)} |- <S --> P> {<S --> (P&T)>, P@(P&T)} |- <S --> P>
*
* @param compound The compound term
* @param index The location of the indicated term in the compound
* @param statement The premise
* @param nal Reference to the memory
*/
static void structuralDecompose1(CompoundTerm compound, short index, Statement statement, DerivationContext nal) {
// if (!memory.getCurrentTask().sentence.isJudgment()) {
// return;
// }
if(index >= compound.term.length) {
return;
}
Term component = compound.term[index];
Task task = nal.getCurrentTask();
Sentence sentence = task.sentence;
int order = sentence.getTemporalOrder();
TruthValue truth = sentence.truth;
if (truth == null) {
return;
}
final float reliance = Parameters.reliance;
TruthValue truthDed = TruthFunctions.deduction(truth, reliance);
TruthValue truthNDed = TruthFunctions.negation(TruthFunctions.deduction(truth, reliance));
Term subj = statement.getSubject();
Term pred = statement.getPredicate();
if (compound.equals(subj)) {
if (compound instanceof IntersectionInt) {
structuralStatement(component, pred, order, truthDed, nal);
} else if ((compound instanceof SetExt) && (compound.size() > 1)) {
Term[] t1 = new Term[]{component};
structuralStatement(new SetExt(t1), pred, order, truthDed, nal);
} else if (compound instanceof DifferenceInt) {
if (index == 0) {
structuralStatement(component, pred, order, truthDed, nal);
} else {
structuralStatement(component, pred, order, truthNDed, nal);
}
}
} else if (compound.equals(pred)) {
if (compound instanceof IntersectionExt) {
structuralStatement(subj, component, order, truthDed, nal);
} else if ((compound instanceof SetInt) && (compound.size() > 1)) {
structuralStatement(subj, new SetInt(component), order, truthDed, nal);
} else if (compound instanceof DifferenceExt) {
if (index == 0) {
structuralStatement(subj, component, order, truthDed, nal);
} else {
structuralStatement(subj, component, order, truthNDed, nal);
}
}
}
}
/**
* Common final operations of the above two methods
*
* @param subject The subject of the new task
* @param predicate The predicate of the new task
* @param truth The truth value of the new task
* @param nal Reference to the memory
*/
private static void structuralStatement(Term subject, Term predicate, int order, TruthValue truth, DerivationContext nal) {
Task task = nal.getCurrentTask();
Term oldContent = task.getTerm();
if (oldContent instanceof Statement) {
Statement content = Statement.make((Statement) oldContent, subject, predicate, order);
if (content != null) {
BudgetValue budget = BudgetFunctions.compoundForward(truth, content, nal);
nal.singlePremiseTask(content, truth, budget);
}
}
}
/* -------------------- set transform -------------------- */
/**
* {<S --> {P}>} |- <S <-> {P}>
*
* @param compound The set compound
* @param statement The premise
* @param side The location of the indicated term in the premise
* @param nal Reference to the memory
*/
static void transformSetRelation(CompoundTerm compound, Statement statement, short side, DerivationContext nal) {
if (compound.size() > 1) {
return;
}
if (statement instanceof Inheritance) {
if (((compound instanceof SetExt) && (side == 0)) || ((compound instanceof SetInt) && (side == 1))) {
return;
}
}
Term sub = statement.getSubject();
Term pre = statement.getPredicate();
Statement content;
if (statement instanceof Inheritance) {
content = Similarity.make(sub, pre);
} else {
if (((compound instanceof SetExt) && (side == 0)) || ((compound instanceof SetInt) && (side == 1))) {
content = Inheritance.make(pre, sub);
} else {
content = Inheritance.make(sub, pre);
}
}
if (content == null) {
return;
}
Task task = nal.getCurrentTask();
Sentence sentence = task.sentence;
TruthValue truth = sentence.truth;
BudgetValue budget;
if (sentence.isJudgment()) {
budget = BudgetFunctions.compoundForward(truth, content, nal);
} else {
budget = BudgetFunctions.compoundBackward(content, nal);
}
nal.singlePremiseTask(content, truth, budget);
}
/* -------------------- products and images transform -------------------- */
/**
* Equivalent transformation between products and images {<(*, S, M) --> P>,
* S@(*, S, M)} |- <S --> (/, P, _, M)> {<S --> (/, P, _, M)>, P@(/, P, _,
* M)} |- <(*, S, M) --> P> {<S --> (/, P, _, M)>, M@(/, P, _, M)} |- <M -->
* (/, P, S, _)>
*
* @param inh An Inheritance statement
* @param oldContent The whole content
* @param indices The indices of the TaskLink
* @param task The task
* @param memory Reference to the memory
*/
static void transformProductImage(Inheritance inh, CompoundTerm oldContent, short[] indices, DerivationContext nal) {
final Memory memory = nal.mem();
Term subject = inh.getSubject();
Term predicate = inh.getPredicate();
if (inh.equals(oldContent)) {
if (subject instanceof CompoundTerm) {
transformSubjectPI((CompoundTerm) subject, predicate, nal);
}
if (predicate instanceof CompoundTerm) {
transformPredicatePI(subject, (CompoundTerm) predicate, nal);
}
return;
}
short index = indices[indices.length - 1];
short side = indices[indices.length - 2];
Term compT = inh.term[side];
if (!(compT instanceof CompoundTerm))
return;
CompoundTerm comp = (CompoundTerm)compT;
if (comp instanceof Product) {
if (side == 0) {
subject = comp.term[index];
predicate = ImageExt.make((Product) comp, inh.getPredicate(), index);
} else {
subject = ImageInt.make((Product) comp, inh.getSubject(), index);
predicate = comp.term[index];
}
} else if ((comp instanceof ImageExt) && (side == 1)) {
if (index == ((ImageExt) comp).relationIndex) {
subject = Product.make(comp, inh.getSubject(), index);
predicate = comp.term[index];
} else {
subject = comp.term[index];
predicate = ImageExt.make((ImageExt) comp, inh.getSubject(), index);
}
} else if ((comp instanceof ImageInt) && (side == 0)) {
if (index == ((ImageInt) comp).relationIndex) {
subject = comp.term[index];
predicate = Product.make(comp, inh.getPredicate(), index);
} else {
subject = ImageInt.make((ImageInt) comp, inh.getPredicate(), index);
predicate = comp.term[index];
}
} else {
return;
}
Inheritance newInh = Inheritance.make(subject, predicate);
if (newInh == null)
return;
CompoundTerm content = null;
if (indices.length == 2) {
content = newInh;
} else if ((oldContent instanceof Statement) && (indices[0] == 1)) {
content = Statement.make((Statement) oldContent, oldContent.term[0], newInh, oldContent.getTemporalOrder());
} else {
Term[] componentList;
Term condition = oldContent.term[0];
if (((oldContent instanceof Implication) || (oldContent instanceof Equivalence)) && (condition instanceof Conjunction)) {
componentList = ((CompoundTerm) condition).cloneTerms();
componentList[indices[1]] = newInh;
Term newCond = Terms.term((CompoundTerm) condition, componentList);
content = Statement.make((Statement) oldContent, newCond, ((Statement) oldContent).getPredicate(), oldContent.getTemporalOrder());
} else {
componentList = oldContent.cloneTerms();
componentList[indices[0]] = newInh;
if (oldContent instanceof Conjunction) {
Term newContent = Terms.term(oldContent, componentList);
if (!(newContent instanceof CompoundTerm))
return;
content = (CompoundTerm)newContent;
} else if ((oldContent instanceof Implication) || (oldContent instanceof Equivalence)) {
content = Statement.make((Statement) oldContent, componentList[0], componentList[1], oldContent.getTemporalOrder());
}
}
}
if (content == null)
return;
Sentence sentence = nal.getCurrentTask().sentence;
TruthValue truth = sentence.truth;
BudgetValue budget;
if (sentence.isQuestion() || sentence.isQuest()) {
budget = BudgetFunctions.compoundBackward(content, nal);
} else {
budget = BudgetFunctions.compoundForward(truth, content, nal);
}
nal.singlePremiseTask(content, truth, budget);
}
/**
* Equivalent transformation between products and images when the subject is
* a compound {<(*, S, M) --> P>, S@(*, S, M)} |- <S --> (/, P, _, M)> {<S
* --> (/, P, _, M)>, P@(/, P, _, M)} |- <(*, S, M) --> P> {<S --> (/, P, _,
* M)>, M@(/, P, _, M)} |- <M --> (/, P, S, _)>
*
* @param subject The subject term
* @param predicate The predicate term
* @param nal Reference to the memory
*/
private static void transformSubjectPI(CompoundTerm subject, Term predicate, DerivationContext nal) {
TruthValue truth = nal.getCurrentTask().sentence.truth;
BudgetValue budget;
Inheritance inheritance;
Term newSubj, newPred;
if (subject instanceof Product) {
Product product = (Product) subject;
for (short i = 0; i < product.size(); i++) {
newSubj = product.term[i];
newPred = ImageExt.make(product, predicate, i);
inheritance = Inheritance.make(newSubj, newPred);
if (inheritance != null) {
if (truth == null) {
budget = BudgetFunctions.compoundBackward(inheritance, nal);
} else {
budget = BudgetFunctions.compoundForward(truth, inheritance, nal);
}
nal.singlePremiseTask(inheritance, truth, budget);
}
}
} else if (subject instanceof ImageInt) {
ImageInt image = (ImageInt) subject;
int relationIndex = image.relationIndex;
for (short i = 0; i < image.size(); i++) {
if (i == relationIndex) {
newSubj = image.term[relationIndex];
newPred = Product.make(image, predicate, relationIndex);
} else {
newSubj = ImageInt.make(image, predicate, i);
newPred = image.term[i];
}
inheritance = Inheritance.make(newSubj, newPred);
if (inheritance != null) {
if (truth == null) {
budget = BudgetFunctions.compoundBackward(inheritance, nal);
} else {
budget = BudgetFunctions.compoundForward(truth, inheritance, nal);
}
nal.singlePremiseTask(inheritance, truth, budget);
}
}
}
}
/**
* Equivalent transformation between products and images when the predicate
* is a compound {<(*, S, M) --> P>, S@(*, S, M)} |- <S --> (/, P, _, M)>
* {<S --> (/, P, _, M)>, P@(/, P, _, M)} |- <(*, S, M) --> P> {<S --> (/,
* P, _, M)>, M@(/, P, _, M)} |- <M --> (/, P, S, _)>
*
* @param subject The subject term
* @param predicate The predicate term
* @param nal Reference to the memory
*/
private static void transformPredicatePI(Term subject, CompoundTerm predicate, DerivationContext nal) {
TruthValue truth = nal.getCurrentTask().sentence.truth;
BudgetValue budget;
Inheritance inheritance;
Term newSubj, newPred;
if (predicate instanceof Product) {
Product product = (Product) predicate;
for (short i = 0; i < product.size(); i++) {
newSubj = ImageInt.make(product, subject, i);
newPred = product.term[i];
inheritance = Inheritance.make(newSubj, newPred);
if (inheritance != null) {
if (truth == null) {
budget = BudgetFunctions.compoundBackward(inheritance, nal);
} else {
budget = BudgetFunctions.compoundForward(truth, inheritance, nal);
}
nal.singlePremiseTask(inheritance, truth, budget);
}
}
} else if (predicate instanceof ImageExt) {
ImageExt image = (ImageExt) predicate;
int relationIndex = image.relationIndex;
for (short i = 0; i < image.size(); i++) {
if (i == relationIndex) {
newSubj = Product.make(image, subject, relationIndex);
newPred = image.term[relationIndex];
} else {
newSubj = image.term[i];
newPred = ImageExt.make(image, subject, i);
}
inheritance = Inheritance.make(newSubj, newPred);
if (inheritance != null) { // jmv <<<<<
if (truth == null) {
budget = BudgetFunctions.compoundBackward(inheritance, nal);
} else {
budget = BudgetFunctions.compoundForward(truth, inheritance, nal);
}
nal.singlePremiseTask(inheritance, truth, budget);
}
}
}
}
/* --------------- Disjunction and Conjunction transform --------------- */
/**
* {(&&, A, B), A@(&&, A, B)} |- A, or answer (&&, A, B)? using A {(||, A,
* B), A@(||, A, B)} |- A, or answer (||, A, B)? using A
*
* @param compound The premise
* @param component The recognized component in the premise
* @param compoundTask Whether the compound comes from the task
* @param nal Reference to the memory
*/
static boolean structuralCompound(CompoundTerm compound, Term component, boolean compoundTask, int index, DerivationContext nal) {
if (component.hasVarIndep()) {
return false;
}
if ((compound instanceof Conjunction) && (compound.getTemporalOrder() == TemporalRules.ORDER_FORWARD) && (index != 0)) {
return false;
}
final Term content = compoundTask ? component : compound;
Task task = nal.getCurrentTask();
Sentence sentence = task.sentence;
TruthValue truth = sentence.truth;
final float reliance = Parameters.reliance;
BudgetValue budget;
if (sentence.isQuestion() || sentence.isQuest()) {
budget = BudgetFunctions.compoundBackward(content, nal);
} else { // need to redefine the cases
//[03:24] <patham9> <a --> b>. (||,<a --> b>,<x --> y>)? => (||,<a --> b>,<x --> y>).
//[03:25] <patham9> <a --> b>. (||,<a --> b>,<x --> y>). => dont derive it "outputMustNotContain(<x --> y>)"
//[03:25] <patham9> <a --> b>. (&&,<a --> b>,<x --> y>)? => dont derive it "outputMustNotContain( (&&,<a --> b>,<x --> y>))"
//[03:25] <patham9> <a --> b>. (&&,<a --> b>,<x --> y>). => <x --> y>
if ((sentence.isJudgment() || sentence.isGoal()) && ((!compoundTask && compound instanceof Disjunction) ||
(compoundTask && compound instanceof Conjunction))) {
truth = TruthFunctions.deduction(truth, reliance);
}else {
TruthValue v1, v2;
v1 = TruthFunctions.negation(truth);
v2 = TruthFunctions.deduction(v1, reliance);
truth = TruthFunctions.negation(v2);
}
budget = BudgetFunctions.forward(truth, nal);
}
//if (content instanceof CompoundTerm)
return nal.singlePremiseTask(content, truth, budget);
// else
// return false;
}
/* --------------- Negation related rules --------------- */
/**
* {A, A@(--, A)} |- (--, A)
*
* @param content The premise
* @param nal Reference to the memory
*/
public static void transformNegation(CompoundTerm content, DerivationContext nal) {
Task task = nal.getCurrentTask();
Sentence sentence = task.sentence;
TruthValue truth = sentence.truth;
BudgetValue budget;
if (sentence.isJudgment() || sentence.isGoal()) {
truth = TruthFunctions.negation(truth);
budget = BudgetFunctions.compoundForward(truth, content, nal);
} else {
budget = BudgetFunctions.compoundBackward(content, nal);
}
nal.singlePremiseTask(content, truth, budget);
}
/**
* {<A ==> B>, A@(--, A)} |- <(--, B) ==> (--, A)>
*
* @param statement The premise
* @param memory Reference to the memory
*/
protected static boolean contraposition(final Statement statement, final Sentence sentence, final DerivationContext nal) {
Memory memory = nal.mem();
//memory.logic.CONTRAPOSITION.commit(statement.complexity);
Term subj = statement.getSubject();
Term pred = statement.getPredicate();
Statement content = Statement.make(statement,
Negation.make(pred),
Negation.make(subj),
TemporalRules.reverseOrder(statement.getTemporalOrder()));
if (content == null) return false;
TruthValue truth = sentence.truth;
BudgetValue budget;
if (sentence.isQuestion() || sentence.isQuest()) {
if (content instanceof Implication) {
budget = BudgetFunctions.compoundBackwardWeak(content, nal);
} else {
budget = BudgetFunctions.compoundBackward(content, nal);
}
return nal.singlePremiseTask(content, Symbols.QUESTION_MARK, truth, budget);
} else {
if (content instanceof Implication) {
truth = TruthFunctions.contraposition(truth);
}
budget = BudgetFunctions.compoundForward(truth, content, nal);
return nal.singlePremiseTask(content, Symbols.JUDGMENT_MARK, truth, budget);
}
}
}