/* * TruthFunctions.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 static java.lang.Math.abs; import nars.entity.TruthValue; /** * All truth-value (and desire-value) functions used in inference rules */ public final class TruthFunctions extends UtilityFunctions { /* ----- Single argument functions, called in MatchingRules ----- */ /** * {<A ==> B>} |- <B ==> A> * @param v1 Truth value of the premise * @return Truth value of the conclusion */ static final TruthValue conversion(final TruthValue v1) { final float f1 = v1.getFrequency(); final float c1 = v1.getConfidence(); final float w = and(f1, c1); final float c = w2c(w); return new TruthValue(1, c); } /* ----- Single argument functions, called in StructuralRules ----- */ /** * {A} |- (--A) * @param v1 Truth value of the premise * @return Truth value of the conclusion */ static final TruthValue negation(final TruthValue v1) { final float f = 1 - v1.getFrequency(); final float c = v1.getConfidence(); return new TruthValue(f, c); } /** * {<A ==> B>} |- <(--, B) ==> (--, A)> * @param v1 Truth value of the premise * @return Truth value of the conclusion */ static final TruthValue contraposition(final TruthValue v1) { final float f1 = v1.getFrequency(); final float c1 = v1.getConfidence(); final float w = and(1 - f1, c1); final float c = w2c(w); return new TruthValue(0, c); } /* ----- double argument functions, called in MatchingRules ----- */ /** * {<S ==> P>, <S ==> P>} |- <S ==> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue revision(final TruthValue v1, final TruthValue v2) { return revision(v1, v2, new TruthValue()); } static final TruthValue revision(final TruthValue v1, final TruthValue v2, final TruthValue result) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float w1 = c2w( v1.getConfidence() ); final float w2 = c2w( v2.getConfidence() ); final float w = w1 + w2; result.setFrequency( (w1 * f1 + w2 * f2) / w ); result.setConfidence( w2c(w) ); return result; } /* ----- double argument functions, called in SyllogisticRules ----- */ /** * {<S ==> M>, <M ==> P>} |- <S ==> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ public static final TruthValue deduction(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f = and(f1, f2); final float c = and(c1, c2, f); return new TruthValue(f, c); } /** * {M, <M ==> P>} |- P * @param v1 Truth value of the first premise * @param reliance Confidence of the second (analytical) premise * @return Truth value of the conclusion */ public static final TruthValue deduction(final TruthValue v1, final float reliance) { final float f1 = v1.getFrequency(); final float c1 = v1.getConfidence(); final float c = and(f1, c1, reliance); return new TruthValue(f1, c, true); } /** * {<S ==> M>, <M <=> P>} |- <S ==> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue analogy(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f = and(f1, f2); final float c = and(c1, c2, f2); return new TruthValue(f, c); } /** * {<S <=> M>, <M <=> P>} |- <S <=> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue resemblance(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f = and(f1, f2); final float c = and(c1, c2, or(f1, f2)); return new TruthValue(f, c); } /** * {<S ==> M>, <P ==> M>} |- <S ==> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ public static final TruthValue abduction(final TruthValue v1, final TruthValue v2) { if (v1.getAnalytic() || v2.getAnalytic()) { return new TruthValue(0.5f, 0f); } final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float w = and(f2, c1, c2); final float c = w2c(w); return new TruthValue(f1, c); } /** * {M, <P ==> M>} |- P * @param v1 Truth value of the first premise * @param reliance Confidence of the second (analytical) premise * @return Truth value of the conclusion */ static final TruthValue abduction(final TruthValue v1, final float reliance) { if (v1.getAnalytic()) { return new TruthValue(0.5f, 0f); } final float f1 = v1.getFrequency(); final float c1 = v1.getConfidence(); final float w = and(c1, reliance); final float c = w2c(w); return new TruthValue(f1, c, true); } /** * {<M ==> S>, <M ==> P>} |- <S ==> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ public static final TruthValue induction(final TruthValue v1, final TruthValue v2) { return abduction(v2, v1); } /** * {<M ==> S>, <P ==> M>} |- <S ==> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue exemplification(final TruthValue v1, final TruthValue v2) { if (v1.getAnalytic() || v2.getAnalytic()) { return new TruthValue(0.5f, 0f); } final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float w = and(f1, f2, c1, c2); final float c = w2c(w); return new TruthValue(1, c); } /** * {<M ==> S>, <M ==> P>} |- <S <=> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue comparison(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f0 = or(f1, f2); final float f = (f0 == 0) ? 0 : (and(f1, f2) / f0); final float w = and(f0, c1, c2); final float c = w2c(w); return new TruthValue(f, c); } /* ----- desire-value functions, called in SyllogisticRules ----- */ /** * A function specially designed for desire value [To be refined] * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ public static final TruthValue desireStrong(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f = and(f1, f2); final float c = and(c1, c2, f2); return new TruthValue(f, c); } /** * A function specially designed for desire value [To be refined] * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue desireWeak(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f = and(f1, f2); final float c = and(c1, c2, f2, w2c(1.0f)); return new TruthValue(f, c); } /** * A function specially designed for desire value [To be refined] * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ public static final TruthValue desireDed(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f = and(f1, f2); final float c = and(c1, c2); return new TruthValue(f, c); } /** * A function specially designed for desire value [To be refined] * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue desireInd(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float w = and(f2, c1, c2); final float c = w2c(w); return new TruthValue(f1, c); } /* ----- double argument functions, called in CompositionalRules ----- */ /** * {<M --> S>, <M <-> P>} |- <M --> (S|P)> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue union(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f = or(f1, f2); final float c = and(c1, c2); return new TruthValue(f, c); } /** * {<M --> S>, <M <-> P>} |- <M --> (S&P)> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue intersection(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float f2 = v2.getFrequency(); final float c1 = v1.getConfidence(); final float c2 = v2.getConfidence(); final float f = and(f1, f2); final float c = and(c1, c2); return new TruthValue(f, c); } /** * {(||, A, B), (--, B)} |- A * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue reduceDisjunction(final TruthValue v1, final TruthValue v2) { final TruthValue v0 = intersection(v1, negation(v2)); return deduction(v0, 1f); } /** * {(--, (&&, A, B)), B} |- (--, A) * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue reduceConjunction(final TruthValue v1, final TruthValue v2) { final TruthValue v0 = intersection(negation(v1), v2); return negation(deduction(v0, 1f)); } /** * {(--, (&&, A, (--, B))), (--, B)} |- (--, A) * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue reduceConjunctionNeg(final TruthValue v1, final TruthValue v2) { return reduceConjunction(v1, negation(v2)); } /** * {(&&, <#x() ==> M>, <#x() ==> P>), S ==> M} |- <S ==> P> * @param v1 Truth value of the first premise * @param v2 Truth value of the second premise * @return Truth value of the conclusion */ static final TruthValue anonymousAnalogy(final TruthValue v1, final TruthValue v2) { final float f1 = v1.getFrequency(); final float c1 = v1.getConfidence(); final TruthValue v0 = new TruthValue(f1, w2c(c1)); return analogy(v2, v0); } /** functions the same as TruthValue, but being a separate class, * indicates it was the result of eternalization */ public static final class EternalizedTruthValue extends TruthValue { public EternalizedTruthValue(final float f, final float c) { super(f, c); } } /** * From one moment to eternal * @param v1 Truth value of the premise * @return Truth value of the conclusion */ public static final EternalizedTruthValue eternalize(final TruthValue v1) { final float f1 = v1.getFrequency(); final float c1 = v1.getConfidence(); final float c = w2c(c1); return new EternalizedTruthValue(f1, c); } public static final float temporalProjection(final long sourceTime, final long targetTime, final long currentTime) { double a = 10000.0; //projection less strict as we changed in v2.0.0 10000.0 slower decay than 100000.0 return 1.0f - abs(sourceTime - targetTime) / (float) (abs(sourceTime - currentTime) + abs(targetTime - currentTime) + a); } }