/* * Conjunction.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.language; import static java.lang.System.arraycopy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.TreeSet; import nars.config.Parameters; import nars.inference.TemporalRules; import nars.io.Symbols.NativeOperator; /** * Conjunction of statements */ public class Conjunction extends CompoundTerm { public final int temporalOrder; public static Term[] removeFirstInterval(Term[] arg) { if(arg[0] instanceof Interval) { Term[] argNew = new Term[arg.length - 1]; for(int i=1;i<arg.length;i++) { argNew[i - 1] = arg[i]; } return argNew; } return arg; } /** * Constructor with partial values, called by make * * @param arg The component list of the term * @param order * @param normalized */ protected Conjunction(Term[] arg, final int order, boolean normalized) { super(arg); temporalOrder = order; init(this.term); /*if (normalized) setNormalized(true);*/ } @Override final public int getMinimumRequiredComponents() { return 1; } @Override public Term clone(Term[] t) { return make(t, temporalOrder); } /** * Clone an object * * @return A new object */ @Override public Conjunction clone() { return new Conjunction(term, temporalOrder, isNormalized()); } /** * Get the operator of the term. * * @return the operator of the term */ @Override public NativeOperator operator() { switch (temporalOrder) { case TemporalRules.ORDER_FORWARD: return NativeOperator.SEQUENCE; case TemporalRules.ORDER_CONCURRENT: return NativeOperator.PARALLEL; default: return NativeOperator.CONJUNCTION; } } /** * Check if the compound is commutative. * * @return true for commutative */ @Override public boolean isCommutative() { return temporalOrder != TemporalRules.ORDER_FORWARD; } /** * Try to make a new compound from a list of term. Called by StringParser. * * @return the Term generated from the arguments * @param argList the list of arguments * @param memory Reference to the memory */ final public static Term make(final Term[] argList) { return make(argList, TemporalRules.ORDER_NONE); } public static boolean isConjunctionAndHasSameOrder(Term t, int order) { if(t instanceof Conjunction) { Conjunction c=(Conjunction) t; if(c.getTemporalOrder()==order) { return true; } } return false; } public static Term[] flatten(Term[] args, int order) { //flatten only same order! //determine how many there are with same order int sz=0; for(int i=0;i<args.length;i++) { Term a=args[i]; if(isConjunctionAndHasSameOrder(a, order)) { sz+=((Conjunction)a).term.length; } else { sz+=1; } } Term[] ret=new Term[sz]; int k=0; for(int i=0;i<args.length;i++) { Term a=args[i]; if(isConjunctionAndHasSameOrder(a, order)) { Conjunction c=((Conjunction)a); for(Term t: c.term) { ret[k]=t; k++; } } else { ret[k]=a; k++; } } return ret; } /** * Try to make a new compound from a list of term. Called by StringParser. * * @param temporalOrder The temporal order among term * @param argList the list of arguments * @param memory Reference to the memory * @return the Term generated from the arguments, or null if not possible */ final public static Term make(final Term[] argList, final int temporalOrder) { if (Parameters.DEBUG) { Terms.verifyNonNull(argList);} if (argList.length == 0) { return null; } // special case: single component if (argList.length == 1) { return argList[0]; } // special case: single component if (temporalOrder == TemporalRules.ORDER_FORWARD) { Term[] newArgList = removeFirstInterval(flatten(argList, temporalOrder)); if(newArgList.length == 1) { return newArgList[0]; } return new Conjunction(newArgList, temporalOrder, false); } else { // sort/merge arguments final TreeSet<Term> set = new TreeSet<>(); for (Term t : argList) { if(!(t instanceof Interval)) { //intervals only for seqs set.add(t); } } if (set.size() == 1) { return set.first(); } return new Conjunction(set.toArray(new Term[set.size()] ), temporalOrder, false); } } final public static Term make(final Term prefix, final List<Interval> suffix, final int temporalOrder) { Term[] t = new Term[suffix.size()+1]; int i = 0; t[i++] = prefix; for (Term x : suffix) t[i++] = x; return make(t, temporalOrder); } final public static Term make(final Term prefix, final List<Interval> ival, final Term suffix, final int temporalOrder) { Term[] t = new Term[ival.size()+2]; int i = 0; t[i++] = prefix; for (Term x : ival) t[i++] = x; t[i++] = suffix; return make(t, temporalOrder); } /** * * @param set a set of Term as term * @param memory Reference to the memory * @return the Term generated from the arguments */ final private static Term make(final Collection<Term> set, int temporalOrder) { Term[] argument = set.toArray(new Term[set.size()]); return make(argument, temporalOrder); } @Override protected CharSequence makeName() { return makeCompoundName( operator(), term); } // overload this method by term type? /** * Try to make a new compound from two term. Called by the inference rules. * * @param term1 The first component * @param term2 The second component * @param memory Reference to the memory * @return A compound generated or a term it reduced to */ final public static Term make(final Term term1, final Term term2) { return make(term1, term2, TemporalRules.ORDER_NONE); } final public static Term make(final Term term1, final Term term2, int temporalOrder) { if (temporalOrder == TemporalRules.ORDER_FORWARD) { final Term[] components; if ((term1 instanceof Conjunction) && (term1.getTemporalOrder() == TemporalRules.ORDER_FORWARD)) { CompoundTerm cterm1 = (CompoundTerm) term1; ArrayList<Term> list = new ArrayList<>(cterm1.size()); cterm1.addTermsTo(list); if ((term2 instanceof Conjunction) && (term2.getTemporalOrder() == TemporalRules.ORDER_FORWARD)) { // (&/,(&/,P,Q),(&/,R,S)) = (&/,P,Q,R,S) ((CompoundTerm) term2).addTermsTo(list); } else { // (&,(&,P,Q),R) = (&,P,Q,R) list.add(term2); } components = list.toArray(new Term[list.size()]); } else if ((term2 instanceof Conjunction) && (term2.getTemporalOrder() == TemporalRules.ORDER_FORWARD)) { CompoundTerm cterm2 = (CompoundTerm) term2; components = new Term[((CompoundTerm) term2).size() + 1]; components[0] = term1; arraycopy(cterm2.term, 0, components, 1, cterm2.size()); } else { components = new Term[] { term1, term2 }; } return make(components, temporalOrder); } else { final List<Term> set = new ArrayList(); if (term1 instanceof Conjunction) { ((CompoundTerm) term1).addTermsTo(set); if (term2 instanceof Conjunction) { // (&,(&,P,Q),(&,R,S)) = (&,P,Q,R,S) ((CompoundTerm) term2).addTermsTo(set); } else { // (&,(&,P,Q),R) = (&,P,Q,R) set.add(term2); } } else if (term2 instanceof Conjunction) { ((CompoundTerm) term2).addTermsTo(set); set.add(term1); // (&,R,(&,P,Q)) = (&,P,Q,R) } else { set.add(term1); set.add(term2); } return make(set, temporalOrder); } } @Override public int getTemporalOrder() { return temporalOrder; } }