/* * TermLink.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 implied 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.entity; import java.util.Arrays; import java.util.Objects; import nars.io.Symbols; import nars.language.Term; /** * A link between a compound term and a component term * <p> * A TermLink links the current Term to a target Term, which is * either a component of, or compound made from, the current term. * <p> * Neither of the two terms contain variable shared with other terms. * <p> * The index value(s) indicates the location of the component in the compound. * <p> * This class is mainly used in inference.RuleTable to dispatch premises to inference rules */ public class TermLink extends Item<TermLink> implements TLink<Term> { /** At C, point to C; TaskLink only */ public static final short SELF = 0; /** At (&&, A, C), point to C */ public static final short COMPONENT = 1; /** At C, point to (&&, A, C) */ public static final short COMPOUND = 2; /** At <C --> A>, point to C */ public static final short COMPONENT_STATEMENT = 3; /** At C, point to <C --> A> */ public static final short COMPOUND_STATEMENT = 4; /** At <(&&, C, B) ==> A>, point to C */ public static final short COMPONENT_CONDITION = 5; /** At C, point to <(&&, C, B) ==> A> */ public static final short COMPOUND_CONDITION = 6; /** At C, point to <(*, C, B) --> A>; TaskLink only */ public static final short TRANSFORM = 8; /** At C, point to B, potentially without common subterm term */ public static final short TEMPORAL = 9; /** The linked Term */ public final Term target; /** The type of link, one of the above */ public final short type; /** The index of the component in the component list of the compound, may have up to 4 levels */ public final short[] index; protected final int hash; /** * Constructor for TermLink template * <p> * called in CompoundTerm.prepareComponentLinks only * @param target Target Term * @param type Link type * @param indices Component indices in compound, may be 1 to 4 */ public TermLink(final Term target, final short type, final short... indices) { super(null); this.target = target; this.type = type; assert (type % 2 == 0); // template types all point to compound, though the target is component if (type == TermLink.COMPOUND_CONDITION) { // the first index is 0 by default index = new short[indices.length + 1]; //index[0] = 0; //first index is zero, but not necessary to set since index[] was just created System.arraycopy(indices, 0, index, 1, indices.length); /* for (int i = 0; i < indices.length; i++) index[i + 1] = (short) indices[i]; */ } else { index = indices; } hash = init(); } /** * Constructor to make actual TermLink from a template * <p> * called in Concept.buildTermLinks only * @param t Target Term * @param template TermLink template previously prepared * @param v Budget value of the link */ public TermLink(final Term t, final TermLink template, final BudgetValue v) { super(v); target = t; type = (template.target.equals(t)) ? (short)(template.type - 1) //// point to component : template.type; index = template.index; hash = init(); } @Override public TermLink name() { return this; } // @Override // public CharSequence name() { // if (key == null) // setKey(); // return key; // } @Override public int hashCode() { return hash; } @Override public boolean equals(final Object obj) { if (obj == this) return true; if (hashCode()!=obj.hashCode()) return false; if (obj instanceof TermLink) { TermLink t = (TermLink)obj; if (type != t.type) return false; if (!Arrays.equals(t.index, index)) return false; final Term tt = t.target; if (target == null) { if (tt!=null) return false; } else if (tt == null) { if (target!=null) return false; } else if (!target.equals(t.target)) return false; return true; } return false; } /** * @return hashcode */ protected int init() { //TODO lazy calculate this? int h = Objects.hash(target, type, Arrays.hashCode(index)); return h; } /*protected final void setKey() { setKey(null); }*/ /** * Set the key of the link * @param suffix optional suffix, may be null */ /*protected final void setKey(final CharSequence suffix) { this.key = Texts.yarn(Parameters.ROPE_TERMLINK_TERM_SIZE_THRESHOLD, newKeyPrefix(), target!=null ? target.name() : null, suffix); }*/ @Override public String toString() { return new StringBuilder().append(newKeyPrefix()).append(target!=null ? target.name() : "").toString(); } public CharSequence newKeyPrefix() { final String at1, at2; if ((type % 2) == 1) { // to component at1 = Symbols.TO_COMPONENT_1; at2 = Symbols.TO_COMPONENT_2; } else { // to compound at1 = Symbols.TO_COMPOUND_1; at2 = Symbols.TO_COMPOUND_2; } final int MAX_INDEX_DIGITS = 2; int estimatedLength = 2+2+1+MAX_INDEX_DIGITS*( (index!=null ? index.length : 0) + 1); final StringBuilder prefix = new StringBuilder(estimatedLength); prefix.append(at1).append('T').append(type); if (index != null) { for (int i : index) { prefix.append('-').append( Integer.toString(i + 1, 16 /** hexadecimal */) ); } } prefix.append(at2); return prefix; } /** * Get one index by level * @param i The index level * @return The index value */ public final short getIndex(final int i) { if ((index != null) && (i < index.length)) { return index[i]; } else { return -1; } } public TermLink(final short type, final Term target, final int i0) { this(target, type, (short)i0); } public TermLink(final short type, final Term target, final int i0, final int i1) { this(target, type, (short)i0, (short)i1); } public TermLink(final short type, final Term target, final int i0, final int i1, final int i2) { this(target, type, (short)i0, (short)i1, (short)i2); } public TermLink(final short type, final Term target, final int i0, final int i1, final int i2, final int i3) { this(target, type, (short)i0, (short)i1, (short)i2, (short)i3); } @Override public void end() { } @Override public Term getTarget() { return target; } public Term getTerm() { return getTarget(); } }