Package org.mindswap.pellet.utils

Source Code of org.mindswap.pellet.utils.ATermUtils

// Portions Copyright (c) 2006 - 2008, Clark & Parsia, LLC. <http://www.clarkparsia.com>
// Clark & Parsia, LLC parts of this source code are available under the terms of the Affero General Public License v3.
//
// Please see LICENSE.txt for full license terms, including the availability of proprietary exceptions.
// Questions, comments, or requests for clarification: licensing@clarkparsia.com
//
// ---
// Portions Copyright (c) 2003 Ron Alford, Mike Grove, Bijan Parsia, Evren Sirin
// Alford, Grove, Parsia, Sirin parts of this source code are available under the terms of the MIT License.
//
// The MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

package org.mindswap.pellet.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.mindswap.pellet.Role;
import org.mindswap.pellet.exceptions.InternalReasonerException;
import org.mindswap.pellet.output.ATermManchesterSyntaxRenderer;
import org.mindswap.pellet.utils.iterator.MultiListIterator;
import org.mindswap.pellet.utils.iterator.PairIterator;

import aterm.AFun;
import aterm.ATerm;
import aterm.ATermAppl;
import aterm.ATermFactory;
import aterm.ATermInt;
import aterm.ATermList;
import aterm.pure.PureFactory;

/**
* This class provides the functions ATerm related functions. Creating terms for
* URI's and complex class descriptions is done here. There are also functions
* for normalization, simplification and conversion to NNF (Normal Negation
* Form).
*
* @author Evren Sirin
*/
public class ATermUtils {
  private static final ATermFactory  factory        = new PureFactory();

  public static final AFun      LITFUN        = factory
                                  .makeAFun( "literal", 3, false );
  public static final int        LIT_VAL_INDEX    = 0;
  public static final int        LIT_LANG_INDEX    = 1;
  public static final int        LIT_URI_INDEX    = 2;

  public static final AFun      ANDFUN        = factory.makeAFun( "and", 1, false );
  public static final AFun      ORFUN        = factory.makeAFun( "or", 1, false );
  public static final AFun      SOMEFUN        = factory.makeAFun( "some", 2, false );
  public static final AFun      ALLFUN        = factory.makeAFun( "all", 2, false );
  public static final AFun      NOTFUN        = factory.makeAFun( "not", 1, false );
  public static final AFun      MAXFUN        = factory.makeAFun( "max", 3, false );
  public static final AFun      MINFUN        = factory.makeAFun( "min", 3, false );
  public static final AFun      VALUEFUN      = factory.makeAFun( "value", 1, false );
  public static final AFun      SELFFUN        = factory.makeAFun( "self", 1, false );
  /**
   * This is not used in the reasoner but kept here to be used for display
   */
  public static final AFun      CARDFUN        = factory.makeAFun( "card", 3, false );

  public static Set<AFun>        CLASS_FUN      = SetUtils.create( new AFun[] {
      ALLFUN, SOMEFUN, MAXFUN, MINFUN, CARDFUN, ANDFUN, ORFUN, NOTFUN, VALUEFUN, SELFFUN } );
 
  public static final AFun      INVFUN        = factory.makeAFun( "inv", 1, false );

  public static final AFun      SUBFUN        = factory.makeAFun( "subClassOf", 2,
                                  false );
  public static final AFun      EQCLASSFUN      = factory.makeAFun(
                                  "equivalentClasses", 2, false );

  public static final AFun      SAMEASFUN      = factory.makeAFun( "sameAs", 2, false );

  public static final AFun      DISJOINTFUN      = factory.makeAFun( "disjointWith", 2,
                                  false );
  public static final AFun      DISJOINTSFUN    = factory.makeAFun( "disjointClasses",
                                  1, false );

  public static final AFun      DISJOINTPROPFUN    = factory.makeAFun( "disjointPropertyWith", 2,
                                  false );
  public static final AFun      DISJOINTPROPSFUN  = factory.makeAFun( "disjointProperties",
                                  1, false );
 
  public static final AFun      COMPLEMENTFUN    = factory.makeAFun( "complementOf", 2,
                                  false );

  /**
   * This is used to represent variables in queries
   */
  public static final AFun      VARFUN        = factory.makeAFun( "var", 1, false );

  public static final AFun      TYPEFUN        = factory.makeAFun( "type", 2, false );

  public static final AFun      PROPFUN        = factory.makeAFun( "prop", 3, false );

  /**
   * Added for explanations
   */
  public static final AFun      DIFFERENTFUN    = factory.makeAFun( "different", 2,
                                  false );
  public static final AFun      ALLDIFFERENTFUN    = factory.makeAFun( "allDifferent", 1,
                                  false );
  public static final AFun      ASYMMETRICFUN    = factory.makeAFun( "asymmetric", 1,
                                  false );
  /**
   * @deprecated Use {@link #ASYMMETRICFUN}
   */
  @Deprecated
    public static final AFun      ANTISYMMETRICFUN  = ASYMMETRICFUN;
  public static final AFun      FUNCTIONALFUN    = factory.makeAFun( "functional", 1,
                                  false );
  public static final AFun      INVFUNCTIONALFUN  = factory.makeAFun(
                                  "inverseFunctional", 1, false );
  public static final AFun      IRREFLEXIVEFUN    = factory.makeAFun( "irreflexive", 1,
                                  false );
  public static final AFun      REFLEXIVEFUN    = factory.makeAFun( "reflexive", 1,
                                  false );
  public static final AFun      SYMMETRICFUN    = factory.makeAFun( "symmetric", 1,
                                  false );
  public static final AFun      TRANSITIVEFUN    = factory.makeAFun( "transitive", 1,
                                  false );
  public static final AFun      SUBPROPFUN      = factory.makeAFun( "subProperty", 2,
                                  false );
  public static final AFun      EQPROPFUN      = factory.makeAFun(
                                  "equivalentProperty", 2, false );
  public static final AFun      INVPROPFUN      = factory.makeAFun( "inverseProperty",
                                  2, false );
  public static final AFun      DOMAINFUN      = factory.makeAFun( "domain", 2, false );

  public static final AFun      RANGEFUN      = factory.makeAFun( "range", 2, false );
 
  public static final AFun      RULEFUN        = factory.makeAFun( "rule", 3, false );
 
  public static final AFun      BUILTINFUN      = factory.makeAFun( "builtin", 1, false );
 
  public static final AFun      DATATYPEDEFFUN    = factory.makeAFun( "datatypeDefinition", 2, false );
 
  public static final AFun      RESTRDATATYPEFUN  = factory.makeAFun( "restrictedDatatype", 2, false );
 
  public static final AFun      FACET        = factory.makeAFun( "facet", 2, false );

  public static final ATermAppl    EMPTY        = makeTermAppl( "" );

  public static final ATermList    EMPTY_LIST      = factory.makeList();
 

  /**
   * Set of all axiom functors used in explanations
   */
  public static Set<AFun>        AXIOM_FUN      = SetUtils.create( new AFun[] {
      TYPEFUN, PROPFUN, SAMEASFUN, DIFFERENTFUN, ALLDIFFERENTFUN,
      SUBFUN, EQCLASSFUN, DISJOINTFUN, DISJOINTSFUN, COMPLEMENTFUN,
      SUBPROPFUN, EQPROPFUN, INVPROPFUN, DOMAINFUN, RANGEFUN,
      FUNCTIONALFUN, INVFUNCTIONALFUN, TRANSITIVEFUN, SYMMETRICFUN, REFLEXIVEFUN,
      IRREFLEXIVEFUN, ANTISYMMETRICFUN, } );



  // TOP and BOTTOM concepts. TOP is not defined as T or not(T) any
  // more but added to each node manually. Defining TOP as a primitive
  // concept reduces number of GCIs and makes other reasoning tasks
  // faster
  public static final ATermAppl    TOP          = ATermUtils.makeTermAppl( "_TOP_" );
  public static final ATermAppl    BOTTOM        = ATermUtils.makeNot( TOP );

  public static final ATermAppl    TOP_OBJECT_PROPERTY = ATermUtils.makeTermAppl( "_TOP_OBJECT_PROPERTY_" );
  public static final ATermAppl    TOP_DATA_PROPERTY  = ATermUtils.makeTermAppl( "_TOP_DATA_PROPERTY_" );
  public static final ATermAppl    BOTTOM_OBJECT_PROPERTY   = ATermUtils.makeTermAppl( "_BOTTOM_OBJECT_PROPERTY_" );
  public static final ATermAppl    BOTTOM_DATA_PROPERTY  = ATermUtils.makeTermAppl( "_BOTTOM_DATA_PROPERTY_" );
 
  public static final ATermAppl    TOP_LIT        = ATermUtils
                                  .makeTermAppl( Namespaces.RDFS
                                      + "Literal" );
  public static final ATermAppl    BOTTOM_LIT      = ATermUtils.makeNot( TOP_LIT );

  public static final ATermAppl    CONCEPT_SAT_IND    = ATermUtils.makeTermAppl( "_C_" );

  public static final ATermInt    ONE          = factory.makeInt( 1 );

  public static final ATermAppl    PLAIN_LITERAL_DATATYPE  = ATermUtils
                                    .makeTermAppl( Namespaces.RDF
                                        + "PlainLiteral" );

  public static QNameProvider      qnames        = new QNameProvider();

  static public ATermFactory getFactory() {
    return factory;
  }

  final static public ATermAppl makeTypeAtom(ATermAppl ind, ATermAppl c) {
    return factory.makeAppl( TYPEFUN, ind, c );
  }

  final static public ATermAppl makePropAtom(ATermAppl p, ATermAppl s, ATermAppl o) {
    return factory.makeAppl( PROPFUN, p, s, o );
  }

  static public ATermAppl makePlainLiteral(String value) {
    return factory.makeAppl( ATermUtils.LITFUN, makeTermAppl( value ), EMPTY,
        PLAIN_LITERAL_DATATYPE );
  }

  static public ATermAppl makePlainLiteral(String value, String lang) {
    return factory.makeAppl( ATermUtils.LITFUN, makeTermAppl( value ), makeTermAppl( lang ),
        PLAIN_LITERAL_DATATYPE );
  }

  static public ATermAppl makeTypedLiteral(String value, ATermAppl dt) {
    return factory
        .makeAppl( ATermUtils.LITFUN, makeTermAppl( value ), EMPTY, dt );
  }

  static public ATermAppl makeTypedLiteral(String value, String dt) {
    return factory
        .makeAppl( ATermUtils.LITFUN, makeTermAppl( value ), EMPTY, makeTermAppl( dt ) );
  }

  static public ATermAppl  NO_DATATYPE  = makeTermAppl( "NO_DATATYPE" );

  static public ATermAppl makeLiteral(ATermAppl name) {
    return factory.makeAppl( ATermUtils.LITFUN, name, EMPTY, NO_DATATYPE );
  }

  static public String getLiteralValue(ATermAppl literal) {
    return ((ATermAppl) literal.getArgument( LIT_VAL_INDEX )).getName();
  }

  static public String getLiteralLang(ATermAppl literal) {
    return ((ATermAppl) literal.getArgument( LIT_LANG_INDEX )).getName();
  }

  static public String getLiteralDatatype(ATermAppl literal) {
    return ((ATermAppl) literal.getArgument( LIT_URI_INDEX )).getName();
  }

  static public ATermAppl makeTermAppl(String name) {
    return factory.makeAppl( factory.makeAFun( name, 0, false ) );
  }

  static public ATermAppl makeTermAppl(AFun fun, ATerm[] args) {
    return factory.makeAppl( fun, args );
  }

  static public ATermAppl makeNot(ATerm c) {
    return factory.makeAppl( NOTFUN, c );
  }

  static public ATerm term(String str) {
    return factory.parse( str );
  }

  // negate all the elements in the list and return the new list
  static public ATermList negate(ATermList list) {
    if( list.isEmpty() ) {
          return list;
        }

    ATermAppl a = (ATermAppl) list.getFirst();
    a = isNot( a )
      ? (ATermAppl) a.getArgument( 0 )
      : makeNot( a );
    ATermList result = makeList( a, negate( list.getNext() ) );

    return result;
  }

  final static public ATermAppl negate(ATermAppl a) {
    return isNot( a )
      ? (ATermAppl) a.getArgument( 0 )
      : makeNot( a );
  }

  public static final AFun  BNODE_FUN      = factory.makeAFun( "bnode", 1, false );
  public static final AFun  ANON_FUN      = factory.makeAFun( "anon", 1, false );
  public static final AFun  ANON_NOMINAL_FUN  = factory.makeAFun( "anon_nominal", 1, false );

  private static final ATermAppl[] anonCache = new ATermAppl[1000];
  static {
    for( int i = 0; i < anonCache.length; i++ ) {
      anonCache[i] = factory.makeAppl( ANON_FUN, factory.makeInt( i ) );
    }
  }
 
  final static public boolean isAnonNominal(ATermAppl term) {
    return term.getAFun().equals( ANON_NOMINAL_FUN );
  }

  final static public ATermAppl makeAnonNominal(int id) {
    return factory.makeAppl( ANON_NOMINAL_FUN, factory.makeInt( id ) );
  }
 
  final static public ATermAppl makeAnon(int id) {
    if( id < anonCache.length ) {
          return anonCache[id];
        }
    return factory.makeAppl( ANON_FUN, factory.makeInt( id ) );
  }

  final static public ATermAppl makeBnode(String id) {
    return factory.makeAppl( BNODE_FUN, makeTermAppl( id ) );
  }
 
  final static public ATermAppl makeVar(String name) {
    return factory.makeAppl( VARFUN, makeTermAppl( name ) );
  }

  final static public ATermAppl makeVar(ATermAppl name) {
    return factory.makeAppl( VARFUN, name );
  }

  final static public ATermAppl makeValue(ATerm c) {
    return factory.makeAppl( VALUEFUN, c );
  }

  final static public ATermAppl makeInv(ATermAppl r) {
    if( isInv( r ) ) {
          return (ATermAppl) r.getArgument( 0 );
        }

    return factory.makeAppl( INVFUN, r );
  }

  final static public ATermAppl makeInvProp(ATerm r, ATerm s) {
    return factory.makeAppl( INVPROPFUN, r, s );
  }

  final static public ATermAppl makeSub(ATerm a, ATerm b) {
    return factory.makeAppl( SUBFUN, a, b );
  }

  final static public ATermAppl makeEqClasses(ATerm a, ATerm b) {
    return factory.makeAppl( EQCLASSFUN, a, b );
  }

  final static public ATermAppl makeSameAs(ATerm a, ATerm b) {
    return factory.makeAppl( SAMEASFUN, a, b );
  }

  final static public ATermAppl makeSubProp(ATerm r, ATerm s) {
    return factory.makeAppl( SUBPROPFUN, r, s );
  }

  final static public ATermAppl makeEqProp(ATerm r, ATerm s) {
    return factory.makeAppl( EQPROPFUN, r, s );
  }

  final static public ATermAppl makeDomain(ATerm r, ATerm c) {
    return factory.makeAppl( DOMAINFUN, r, c );
  }

  final static public ATermAppl makeRange(ATerm r, ATerm c) {
    return factory.makeAppl( RANGEFUN, r, c );
  }

  final static public ATermAppl makeComplement(ATerm a, ATerm b) {
    return factory.makeAppl( COMPLEMENTFUN, a, b );
  }

  final static public ATermAppl makeDisjoint(ATerm a, ATerm b) {
    return factory.makeAppl( DISJOINTFUN, a, b );
  }

  final static public ATermAppl makeDisjoints(ATermList list) {
    return factory.makeAppl( DISJOINTSFUN, list );
  }

  final static public ATermAppl makeDisjointProperty(ATerm a, ATerm b) {
    return factory.makeAppl( DISJOINTPROPFUN, a, b );
  }

  final static public ATermAppl makeDisjointProperties(ATermList list) {
    return factory.makeAppl( DISJOINTPROPSFUN, list );
  }
 
  final static public ATermAppl makeDifferent(ATerm a, ATerm b) {
    return factory.makeAppl( DIFFERENTFUN, a, b );
  }

  final static public ATermAppl makeAllDifferent(ATermList list) {
    return factory.makeAppl( ALLDIFFERENTFUN, list );
  }

  final static public ATermAppl makeAsymmetric(ATerm r) {
    return factory.makeAppl( ASYMMETRICFUN, r );
  }

    /**
     * @deprecated Use {@link #makeAsymmetric(ATerm)}
     */
  @Deprecated
    final static public ATermAppl makeAntisymmetric(ATerm r) {
    return makeAsymmetric( r );
  }

  final static public ATermAppl makeFunctional(ATerm a) {
    return factory.makeAppl( FUNCTIONALFUN, a );
  }

  final static public ATermAppl makeInverseFunctional(ATerm a) {
    return factory.makeAppl( INVFUNCTIONALFUN, a );
  }

  final static public ATermAppl makeIrreflexive(ATerm r) {
    return factory.makeAppl( IRREFLEXIVEFUN, r );
  }

  final static public ATermAppl makeReflexive(ATerm r) {
    return factory.makeAppl( REFLEXIVEFUN, r );
  }

  final static public ATermAppl makeSymmetric(ATerm r) {
    return factory.makeAppl( SYMMETRICFUN, r );
  }

  final static public ATermAppl makeTransitive(ATerm r) {
    return factory.makeAppl( TRANSITIVEFUN, r );
  }

  final static public ATermAppl makeAnd(ATerm c1, ATerm c2) {
    return makeAnd( makeList( c2 ).insert( c1 ) );
  }

  static public ATermAppl makeAnd(ATermList list) {
    if( list == null ) {
          throw new NullPointerException();
        }
        else if( list.isEmpty() ) {
          return TOP;
        }
        else if( list.getNext().isEmpty() ) {
          return (ATermAppl) list.getFirst();
        }

    return factory.makeAppl( ANDFUN, list );
  }

  final static public ATermAppl makeOr(ATermAppl c1, ATermAppl c2) {
    return makeOr( makeList( c2 ).insert( c1 ) );
  }

  static public ATermAppl makeOr(ATermList list) {
    if( list == null ) {
          throw new NullPointerException();
        }
        else if( list.isEmpty() ) {
          return BOTTOM;
        }
        else if( list.getNext().isEmpty() ) {
          return (ATermAppl) list.getFirst();
        }

    return factory.makeAppl( ORFUN, list );
  }

  final static public ATermAppl makeAllValues(ATerm r, ATerm c) {
    if( r.getType() == ATerm.LIST ) {
      ATermList list = (ATermList) r;
      if( list.getLength() == 1 ) {
              r = list.getFirst();
            }
    }
    return factory.makeAppl( ALLFUN, r, c );
  }

  final static public ATermAppl makeSomeValues(ATerm r, ATerm c) {
    assertTrue( c instanceof ATermAppl );

    return factory.makeAppl( SOMEFUN, r, c );
  }

  final static public ATermAppl makeSelf(ATermAppl r) {
    return factory.makeAppl( SELFFUN, r );
  }

  final static public ATermAppl makeHasValue(ATerm r, ATerm ind) {
    ATermAppl c = makeValue( ind );
    return factory.makeAppl( SOMEFUN, r, c );
  }

  final static public ATermAppl makeNormalizedMax(ATermAppl r, int n, ATermAppl c) {
    assertTrue( n >= 0 );

    return makeNot( makeMin( r, n + 1, c ) );
  }

  final static public ATermAppl makeMax(ATerm r, int n, ATerm c) {
    // assertTrue( n >= 0 );

    // This was causing nnf to come out wrong
    // return makeNot(makeMin(r, n + 1));

    return makeMax( r, factory.makeInt( n ), c );
  }

  final static public ATermAppl makeMax(ATerm r, ATermInt n, ATerm c) {
    assertTrue( n.getInt() >= 0 );

    return factory.makeAppl( MAXFUN, r, n, c );
  }

  final static public ATermAppl makeMin(ATerm r, int n, ATerm c) {
    // comment out built-in simplification so that explanation
    // axioms will come out right
    // if( n == 0 )
    // return ATermUtils.TOP;

    return makeMin( r, factory.makeInt( n ), c );
  }

  final static public ATermAppl makeMin(ATerm r, ATermInt n, ATerm c) {
    assertTrue( n.getInt() >= 0 );

    return factory.makeAppl( MINFUN, r, n, c );
  }

  final static public ATermAppl makeDisplayCard(ATerm r, int n, ATerm c) {
    assertTrue( n >= 0 );

    return factory.makeAppl( CARDFUN, r, factory.makeInt( n ), c );
  }

  final static public ATermAppl makeDisplayMax(ATerm r, int n, ATerm c) {
    assertTrue( n >= 0 );

    return factory.makeAppl( MAXFUN, r, factory.makeInt( n ), c );
  }

  final static public ATermAppl makeDisplayMin(ATerm r, int n, ATerm c) {
    assertTrue( n >= 0 );

    return factory.makeAppl( MINFUN, r, factory.makeInt( n ), c );
  }

  final static public ATermAppl makeCard(ATerm r, int n, ATerm c) {
    return makeDisplayCard( r, n, c );
    // ATermAppl max = makeMax( r, n, c );
    // if( n == 0 )
    // return max;
    //
    // ATermAppl min = makeMin( r, n, c );
    // return makeAnd( min, max );
  }

  final static public ATermAppl makeExactCard(ATerm r, int n, ATerm c) {
    return makeExactCard( r, factory.makeInt( n ), c );
  }

  final static public ATermAppl makeExactCard(ATerm r, ATermInt n, ATerm c) {
    ATermAppl max = makeMax( r, n, c );

    if( n.getInt() == 0 ) {
          return max;
        }

    ATermAppl min = makeMin( r, n, c );
    return makeAnd( min, max );
  }

  final static public ATermAppl makeFacetRestriction(ATermAppl facetName, ATermAppl facetValue) {
    return factory.makeAppl( FACET, facetName, facetValue );
  }
 
  final static public ATermAppl makeRestrictedDatatype(ATermAppl baseDatatype, ATermAppl[] restrictions) {
    return factory.makeAppl( RESTRDATATYPEFUN, baseDatatype, makeList( restrictions ) );
  }
 
  final static public ATermAppl makeDatatypeDefinition(ATermAppl datatype, ATermAppl definition) {
    return factory.makeAppl( DATATYPEDEFFUN, datatype, definition );
  }
   
  final static public boolean isRestrictedDatatype(ATermAppl term) {
    return term.getAFun().equals( RESTRDATATYPEFUN );
  }
 
  final static public ATermList makeList(ATerm singleton) {
    return factory.makeList( singleton, EMPTY_LIST );
  }

  final static public ATermList makeList(ATerm first, ATermList rest) {
    return factory.makeList( first, rest );
  }

  public static ATermList makeList(Collection<ATermAppl> set) {
    ATermList list = EMPTY_LIST;

    for( ATerm term : set ) {
      list = list.insert( term );
    }
    return list;
  }

  final static public ATermList makeList(ATerm[] aTerms) {
    return makeList( aTerms, 0 );
  }

  static private ATermList makeList(ATerm[] aTerms, int index) {
    if( index >= aTerms.length ) {
          return EMPTY_LIST;
        }
        else if( index == aTerms.length - 1 ) {
          return makeList( aTerms[index] );
        }

    return makeList( aTerms[index], makeList( aTerms, index + 1 ) );
  }

  final static public boolean member(ATerm a, ATermList list) {
    return (list.indexOf( a, 0 ) != -1);
  }

  static public boolean isSet(ATermList list) {
    if( list.isEmpty() ) {
          return true;
        }

    ATerm curr = list.getFirst();
    list = list.getNext();
    while( !list.isEmpty() ) {
      ATerm next = list.getFirst();
      if( Comparators.termComparator.compare( curr, next ) >= 0 ) {
              return false;
            }
      curr = next;
      list = list.getNext();
    }

    return true;
  }

  static public ATermList toSet(ATermList list) {
    if( isSet( list ) ) {
          return list;
        }

    int size = list.getLength();

    ATerm[] a = toArray( list );
    if( a == null || a.length < size ) {
          a = new ATerm[Math.max( 100, size )];
        }

    Arrays.sort( a, 0, size, Comparators.termComparator );

    ATermList set = makeList( a[size - 1] );
    for( int i = size - 2; i >= 0; i-- ) {
      ATerm s = set.getFirst();
      if( !s.equals( a[i] ) ) {
              set = set.insert( a[i] );
            }
    }

    return set;
  }

  static public ATermList toSet(ATerm[] a, int size) {
    Arrays.sort( a, 0, size, Comparators.termComparator );

    ATermList set = makeList( a[size - 1] );
    for( int i = size - 2; i >= 0; i-- ) {
      ATerm s = set.getFirst();
      if( !s.equals( a[i] ) ) {
              set = set.insert( a[i] );
            }
    }

    return set;
  }

  static public ATermList toSet(Collection<ATermAppl> terms) {
    int size = terms.size();

    ATermAppl[] a = new ATermAppl[size];
    terms.toArray( a );

    return toSet( a, size );
  }
 
  /**
   * Return the string representations of the terms in a collection. For each element of the collection
   * {@link #toString(ATermAppl)} function will be called to create the string representation.
   *
   * @param terms
   *            a collection of terms
   * @return string representation of the terms
   */
  public static String toString(Collection<ATermAppl> terms) {
    if (terms.isEmpty()) {
          return "[]";
        }
   
    StringBuilder sb = new StringBuilder();
    sb.append("[");
   
    Iterator<ATermAppl> i = terms.iterator();
    sb.append(ATermUtils.toString(i.next()));
    while (i.hasNext()) {
      sb.append(", ");
      sb.append(ATermUtils.toString(i.next()));
    }

    sb.append("]");

    return sb.toString();
  }

  /**
   * Return a string representation of the term which might be representing a named
   * term, literal, variable or a complex concept expression. The URIs used in the
   * term will be shortened into local names. The concept expressions are printed
   * in NNF format.
   *
   * @param term term whose string representation we are creating
   * @return string representation of the term
   */
  public static String toString(ATermAppl term) {
    return toString( term, true , true);
  }
 
  /**
   * Return a string representation of the term which might be representing a named
   * term, literal, variable or a complex concept expression. The URIs used in the
   * term can be shortened into local names. The concept expressions can be printed
   * in NNF format.
   *
   * @param term term whose string representation we are creating
   * @return string representation of the term
   */
  public static String toString(ATermAppl term, boolean printLocalName, boolean printNNF) {
    if (term == null) {
      return "<null>";
    }
    else {
      StringBuilder sb = new StringBuilder();
      toString( term, sb, printNNF ? Bool.FALSE : Bool.UNKNOWN, printLocalName );
      return sb.toString();
    }
  }
 
  /**
   * Helper for toString function.
   *
   * @param term term
   * @param sb the builder we are
   * @param negated
   * @param useLocalName
   */
  private static void toString(ATermAppl term, StringBuilder sb, Bool negated, boolean printLocalName) {
    if( term.equals( ATermUtils.TOP ) ) {
          sb.append(negated.isTrue() ? "owl:Nothing" : "owl:Thing");
        }
        else if( term.equals( ATermUtils.BOTTOM ) ) {
          sb.append(negated.isTrue() ? "owl:Thing" : "owl:Nothing");
        }
        else if( ATermUtils.isVar( term ) ) {
      String name = ((ATermAppl) term.getArgument( 0 )).getName();
      if( printLocalName ) {
              name = URIUtils.getLocalName( name );
            }
      sb.append( "?" ).append( name );
    }
    else if( ATermUtils.isLiteral( term ) ) {
      String value = ((ATermAppl) term.getArgument( 0 )).toString();
      String lang = ((ATermAppl) term.getArgument( 1 )).getName();
      ATermAppl datatypeURI = (ATermAppl) term.getArgument( 2 );

      sb.append( '"' ).append( value ).append( '"' );
      if( !lang.equals( "" ) ) {
        sb.append( '@' ).append( lang );
      }
      else if( !datatypeURI.equals( NO_DATATYPE ) &&
           !datatypeURI.equals( PLAIN_LITERAL_DATATYPE ) ) {
        sb.append( "^^" );
        toString( datatypeURI, sb, Bool.FALSE, printLocalName );       
      }
    }
    else if( ATermUtils.isPrimitive( term ) ) {
      if( negated.isTrue() ) {
        sb.append( "not(" );
      }
      String name = term.getName();
      sb.append( URIUtils.getLocalName( name ) );
      if( negated.isTrue() ) {
        sb.append( ")" );
      }
    }
    else if( ATermUtils.isRestrictedDatatype( term ) ) {
      if( negated.isTrue() ) {
        sb.append( "not(" );
      }
          toString((ATermAppl) term.getArgument(0), sb, Bool.FALSE, printLocalName );
          sb.append("[");
          ATermList list = (ATermList) term.getArgument( 1 );
      while (!list.isEmpty()) {
        ATermAppl facet = (ATermAppl) list.getFirst();
        sb.append( ATermManchesterSyntaxRenderer.FACETS.get( facet.getArgument( 0 ) ));
        sb.append(" ");
        toString((ATermAppl) facet.getArgument( 1 ), sb, Bool.FALSE, printLocalName );
        list = list.getNext();
        if(!list.isEmpty()) {
                  sb.append(", ");
                }
      }
      sb.append("]");
      if( negated.isTrue() ) {
        sb.append( ")" );
      }
    }
    else if( negated.isKnown() && ATermUtils.isNot( term ) ) {
      toString( (ATermAppl) term.getArgument( 0 ), sb, negated.not(), printLocalName );
    }
    else {   
      AFun fun = term.getAFun();
      if( negated.isTrue() ) {
        if( fun.equals( ATermUtils.ANDFUN ) ) {
                  sb.append( ATermUtils.ORFUN.getName() );
                }
                else if( fun.equals( ATermUtils.ORFUN ) ) {
                  sb.append( ATermUtils.ANDFUN.getName() );
                }
                else if( fun.equals( ATermUtils.SOMEFUN ) ) {
                  sb.append( ATermUtils.ALLFUN.getName() );
                }
                else if( fun.equals( ATermUtils.ALLFUN ) ) {
                  sb.append( ATermUtils.SOMEFUN.getName() );
                }
                else if( fun.equals( ATermUtils.MINFUN ) ) {
                  sb.append( ATermUtils.MAXFUN.getName() );
                }
                else if( fun.equals( ATermUtils.MAXFUN ) ) {
                  sb.append( ATermUtils.MINFUN.getName() );
                }
                else if( !fun.equals( ATermUtils.NOTFUN ) ) {
          if( fun.equals( ATermUtils.VALUEFUN )
            || fun.equals( ATermUtils.RESTRDATATYPEFUN )) {
                      sb.append( "not(" );
                    }
          sb.append( fun.getName() );
        }
      }
      else {
        sb.append( fun.getName() );
      }
     
      Bool negatedRecurse = negated;
      if( negated.isKnown() && fun.equals( ATermUtils.MINFUN ) || fun.equals( ATermUtils.MAXFUN ) ) {
        negatedRecurse = Bool.FALSE;
      }
      else if( fun.equals( ATermUtils.NOTFUN ) ) {
        negatedRecurse = negated.not();
      }

      sb.append( "(" );
      for( int i = 0, n = term.getArity(); i < n; i++ ) {
        if( i > 0 ) {
          sb.append ( ", " );       
        }
        ATerm arg = term.getArgument( i );
        if( arg instanceof ATermAppl ) {
          toString( (ATermAppl) arg, sb, i > 0 ? negatedRecurse : Bool.FALSE, printLocalName );         
        }
        else if( arg instanceof ATermList ) {
          sb.append( "[" );
          ATermList list = (ATermList) arg;
          while( !list.isEmpty() ) {
            toString( (ATermAppl) list.getFirst(), sb, negatedRecurse, printLocalName );
            list = list.getNext();
            if( !list.isEmpty() ) {
                          sb.append ( ", " );
                        }
          }
          sb.append( "]" );
        }
        else {
          int value = ((ATermInt) arg).getInt();
          if( negated.isTrue() ) {
            if( fun.equals( ATermUtils.MINFUN ) ) {
                          value--;
                        }
                        else if( fun.equals( ATermUtils.MAXFUN ) ) {
                          value++;
                        }
          }
          sb.append( value );
        }
      }
      sb.append( ")" );
      if( (fun.equals( ATermUtils.VALUEFUN )
        || fun.equals( ATermUtils.RESTRDATATYPEFUN )) && negated.isTrue() ) {
              sb.append( ")" );
            }
    }
  }

  static public ATermAppl[] toArray(ATermList list) {
    ATermAppl[] a = new ATermAppl[list.getLength()];

    for( int i = 0; !list.isEmpty(); list = list.getNext() ) {
          a[i++] = (ATermAppl) list.getFirst();
        }

    return a;
  }

  public final static void assertTrue(boolean condition) {
    if( !condition ) {
      throw new RuntimeException( "assertion failed." );
    }
  }

  public static final boolean isPrimitive(ATermAppl c) {
    return c.getArity() == 0;
  }

  public static final boolean isNegatedPrimitive(ATermAppl c) {
    return isNot( c ) && isPrimitive( (ATermAppl) c.getArgument( 0 ) );
  }

  public static final boolean isPrimitiveOrNegated(ATermAppl c) {
    return isPrimitive( c ) || isNegatedPrimitive( c );
  }

  public static final boolean isBnode(ATermAppl name) {
    return name.getAFun().equals( BNODE_FUN );
  }

  public static final boolean isAnon(ATermAppl term) {
    return term.getAFun().equals( ANON_FUN );
  }
 
  public static final boolean isBuiltinProperty(ATermAppl name) {
    if ( TOP_OBJECT_PROPERTY.equals( name ) ||
        BOTTOM_OBJECT_PROPERTY.equals( name ) ||
        makeInv( TOP_OBJECT_PROPERTY).equals( name ) ||
        makeInv( BOTTOM_OBJECT_PROPERTY ).equals( name ) ||
        TOP_DATA_PROPERTY.equals( name ) ||
        BOTTOM_DATA_PROPERTY.equals( name ) ) {
          return true;
        }
    return false;
  }

  public static Set<ATermAppl> listToSet(ATermList list) {
    Set<ATermAppl> set = new HashSet<ATermAppl>();
    while( !list.isEmpty() ) {
      set.add( (ATermAppl) list.getFirst() );
      list = list.getNext();
    }
    return set;
  }

  public static Set<ATermAppl> getPrimitives(ATermList list) {
    Set<ATermAppl> set = new HashSet<ATermAppl>();
    while( !list.isEmpty() ) {
      ATermAppl term = (ATermAppl) list.getFirst();
      if( isPrimitive( term ) ) {
              set.add( term );
            }
      list = list.getNext();
    }
    return set;
  }

  public final static ATermAppl getTop(Role r) {
    return r.isDatatypeRole()
      ? TOP_LIT
      : TOP;
  }
 
  public final static boolean isTop(ATermAppl a) {
    return a.equals( TOP ) || a.equals( TOP_LIT );
  }

  public final static boolean isBottom(ATermAppl a) {
    return a.equals( BOTTOM ) || a.equals( BOTTOM_LIT );
  }

  final static public boolean isInv(ATermAppl r) {
    return r.getAFun().equals( INVFUN );
  }

  public final static boolean isAnd(ATermAppl a) {
    return a.getAFun().equals( ANDFUN );
  }

  public final static boolean isOr(ATermAppl a) {
    return a.getAFun().equals( ORFUN );
  }

  public final static boolean isAllValues(ATermAppl a) {
    return a.getAFun().equals( ALLFUN );
  }

  public final static boolean isSomeValues(ATermAppl a) {
    return a.getAFun().equals( SOMEFUN );
  }

  public final static boolean isSelf(ATermAppl a) {
    return a.getAFun().equals( SELFFUN );
  }

  public final static boolean isHasValue(ATermAppl a) {
    return a.getAFun().equals( SOMEFUN )
        && ((ATermAppl) a.getArgument( 1 )).getAFun().equals( VALUEFUN );
  }

  public final static boolean isNominal(ATermAppl a) {
    return a.getAFun().equals( VALUEFUN );
  }

  public final static boolean isOneOf(ATermAppl a) {
    if( !a.getAFun().equals( ORFUN ) ) {
          return false;
        }

    ATermList list = (ATermList) a.getArgument( 0 );
    while( !list.isEmpty() ) {
      if( !isNominal( (ATermAppl) list.getFirst() ) ) {
              return false;
            }
      list = list.getNext();
    }
    return true;
  }

  public final static boolean isDataRange(ATermAppl a) {
    if( !a.getAFun().equals( ORFUN ) ) {
          return false;
        }

    ATermList list = (ATermList) a.getArgument( 0 );
    while( !list.isEmpty() ) {
      ATermAppl term = (ATermAppl) list.getFirst();
      if( !isNominal( term ) || !isLiteral( (ATermAppl) term.getArgument( 0 ) ) ) {
              return false;
            }
      list = list.getNext();
    }
    return true;
  }

  public final static boolean isNot(ATermAppl a) {
    return a.getAFun().equals( NOTFUN );
  }

  public final static boolean isMax(ATermAppl a) {
    return a.getAFun().equals( MAXFUN );
  }

  public final static boolean isMin(ATermAppl a) {
    return a.getAFun().equals( MINFUN );
  }

  public final static boolean isCard(ATermAppl a) {
    if( isMin( a ) || isMax( a ) ) {
          return true;
        }
        else if( isAnd( a ) ) {
      a = (ATermAppl) a.getArgument( 0 );
      return isMin( a ) || isMax( a );
    }

    return false;
  }

  public final static boolean isLiteral(ATermAppl a) {
    return a.getAFun().equals( LITFUN );
  }

  final static public boolean isVar(ATermAppl a) {
    return a.getAFun().equals( VARFUN );
  }

  final static public boolean isTransitiveChain(ATermList chain, ATerm r) {
    return chain.getLength() == 2 && chain.getFirst().equals( r ) && chain.getLast().equals( r );
  }

  public static boolean isComplexClass(ATerm c) {
    if( c instanceof ATermAppl ) {
      ATermAppl a = (ATermAppl) c;
      AFun f = a.getAFun();
      return CLASS_FUN.contains( f );
    }
    return false;
  }

  public final static boolean isPropertyAssertion(ATermAppl a) {
    return a.getAFun().equals( PROPFUN );
  }

  public final static boolean isTypeAssertion(ATermAppl a) {
    return a.getAFun().equals( TYPEFUN );
  }

  public static ATerm nnf(ATerm term) {
    if( term instanceof ATermList ) {
          return nnf( (ATermList) term );
        }
    if( term instanceof ATermAppl ) {
          return nnf( (ATermAppl) term );
        }

    return null;
  }

  public static ATermList nnf(ATermList list) {
    ATermList newList = factory.makeList();
    while( !list.isEmpty() ) {
      newList = newList.append( nnf( (ATermAppl) list.getFirst() ) );
      list = list.getNext();
    }

    return newList;
  }

  /*
   * return the term in NNF form, i.e. negation only occurs in front of atomic
   * concepts
   */
  public static ATermAppl nnf(ATermAppl term) {
    ATermAppl newterm = null;

    AFun af = term.getAFun();

    if( af.equals( ATermUtils.NOTFUN ) ) { // Function is a NOT
      // Take the first argument to the NOT, then check
      // the type of that argument to determine what needs to be done.
      ATermUtils.assertTrue( af.getArity() == 1 );
      ATermAppl arg = (ATermAppl) term.getArgument( 0 );
      af = arg.getAFun();

      if( arg.getArity() == 0 ) {
        newterm = term; // Negation is in as far as it can go
      }
      else if( af.equals( ATermUtils.NOTFUN ) ) { // Double negation.
        newterm = nnf( (ATermAppl) arg.getArgument( 0 ) );
      }
      else if( af.equals( ATermUtils.VALUEFUN ) || af.equals( ATermUtils.SELFFUN || af.equals( ATermUtils.RESTRDATATYPEFUN ) ) {
        newterm = term;
      }
      else if( af.equals( ATermUtils.MAXFUN ) ) {
        ATermInt n = (ATermInt) arg.getArgument( 1 );
        newterm = ATermUtils.makeMin( arg.getArgument( 0 ), n.getInt() + 1, nnf( arg
            .getArgument( 2 ) ) );
      }
      else if( af.equals( ATermUtils.MINFUN ) ) {
        ATermInt n = (ATermInt) arg.getArgument( 1 );
        if( n.getInt() == 0 ) {
                  newterm = ATermUtils.BOTTOM;
                }
                else {
                  newterm = ATermUtils.makeMax( arg.getArgument( 0 ), n.getInt() - 1, nnf( arg
              .getArgument( 2 ) ) );
                }
      }
      else if( af.equals( ATermUtils.CARDFUN ) ) {
        newterm = nnf( makeNot( makeExactCard( arg.getArgument( 0 ), ((ATermInt) arg
            .getArgument( 1 )), arg.getArgument( 2 ) ) ) );
      }
      else if( af.equals( ATermUtils.ANDFUN ) ) {
        newterm = ATermUtils.makeOr( nnf( negate( (ATermList) arg.getArgument( 0 ) ) ) );
      }
      else if( af.equals( ATermUtils.ORFUN ) ) {
        newterm = ATermUtils.makeAnd( nnf( negate( (ATermList) arg.getArgument( 0 ) ) ) );
      }
      else if( af.equals( ATermUtils.SOMEFUN ) ) {
        ATerm p = arg.getArgument( 0 );
        ATerm c = arg.getArgument( 1 );
        newterm = ATermUtils.makeAllValues( p, nnf( makeNot( c ) ) );
      }
      else if( af.equals( ATermUtils.ALLFUN ) ) {
        ATerm p = arg.getArgument( 0 );
        ATerm c = arg.getArgument( 1 );
        newterm = ATermUtils.makeSomeValues( p, nnf( makeNot( c ) ) );
      }
      else {
        throw new InternalReasonerException( "Unknown term type: " + term );
      }
    }
    else if( af.equals( ATermUtils.MINFUN ) || af.equals( ATermUtils.MAXFUN )
        || af.equals( ATermUtils.SELFFUN ) ) {
      newterm = term;
    }
    else if( af.equals( ATermUtils.CARDFUN ) ) {
      newterm = nnf( makeExactCard( term.getArgument( 0 ),
          ((ATermInt) term.getArgument( 1 )), term.getArgument( 2 ) ) );
    }
    else {
      // Return the term with all of its arguments in nnf
      ATerm args[] = new ATerm[term.getArity()];
      for( int i = 0; i < term.getArity(); i++ ) {
        args[i] = nnf( term.getArgument( i ) );
      }
      newterm = factory.makeAppl( af, args );
    }

    ATermUtils.assertTrue( newterm != null );

    return newterm;
  }

  public static Collection<ATermAppl> normalize(Collection<ATermAppl> terms) {
    List<ATermAppl> list = new ArrayList<ATermAppl>();
    for( ATermAppl term : terms ) {
      list.add( normalize( term ) );
    }

    return list;
  }

  public static ATermList normalize(ATermList list) {
    int size = list.getLength();
    ATerm[] terms = new ATerm[size];
    for( int i = 0; i < size; i++ ) {
      terms[i] = normalize( (ATermAppl) list.getFirst() );
      list = list.getNext();
    }

    ATermList set = toSet( terms, size );

    return set;
  }

  /**
   * Normalize the term by making following changes:
   * <ul>
   * <li>or([a1, a2,..., an]) -> not(and[not(a1), not(a2), ..., not(an)]])</li>
   * <li>some(p, c) -> all(p, not(c))</li>
   * <li>max(p, n) -> not(min(p, n+1))</li>
   * </ul>
   *
   * @param term
   * @return
   */
  public static ATermAppl normalize(ATermAppl term) {
    ATermAppl norm = term;
    AFun fun = term.getAFun();
    ATerm arg1 = (term.getArity() > 0)
      ? term.getArgument( 0 )
      : null;
    ATerm arg2 = (term.getArity() > 1)
      ? term.getArgument( 1 )
      : null;
    ATerm arg3 = (term.getArity() > 2)
      ? term.getArgument( 2 )
      : null;

    if( arg1 == null || fun.equals( SELFFUN ) || fun.equals( VALUEFUN ) || fun.equals( INVFUN )
      || fun.equals( RESTRDATATYPEFUN ) ) {
      // do nothing because these terms cannot be decomposed any further
    }
    else if( fun.equals( NOTFUN ) ) {
      if( !isPrimitive( (ATermAppl) arg1 ) ) {
              norm = simplify( makeNot( normalize( (ATermAppl) arg1 ) ) );
            }
    }
    else if( fun.equals( ANDFUN ) ) {
      norm = simplify( makeAnd( normalize( (ATermList) arg1 ) ) );
    }
    else if( fun.equals( ORFUN ) ) {
      ATermList neg = negate( (ATermList) arg1 );
      ATermAppl and = makeAnd( neg );
      ATermAppl notAnd = makeNot( and );
      norm = normalize( notAnd );
    }
    else if( fun.equals( ALLFUN ) ) {
      norm = simplify( makeAllValues( arg1, normalize( (ATermAppl) arg2 ) ) );
    }
    else if( fun.equals( SOMEFUN ) ) {
      norm = normalize( makeNot( makeAllValues( arg1, makeNot( arg2 ) ) ) );
    }
    else if( fun.equals( MAXFUN ) ) {
      norm = normalize( makeNot( makeMin( arg1, ((ATermInt) arg2).getInt() + 1, arg3 ) ) );
    }
    else if( fun.equals( MINFUN ) ) {
      norm = simplify( makeMin( arg1, (ATermInt) arg2, normalize( (ATermAppl) arg3 ) ) );
    }
    else if( fun.equals( CARDFUN ) ) {
      ATermAppl normMin = simplify( makeMin( arg1, ((ATermInt) arg2).getInt(),
          normalize( (ATermAppl) arg3 ) ) );
      ATermAppl normMax = normalize( makeMax( arg1, ((ATermInt) arg2).getInt(), arg3 ) );
      norm = simplify( makeAnd( normMin, normMax ) );
    }
        else {
          throw new InternalReasonerException( "Unknown concept type: " + term );
        }

    return norm;
  }

  /**
   * Simplify the term by making following changes:
   * <ul>
   * <li>and([]) -> TOP</li>
   * <li>all(p, TOP) -> TOP</li>
   * <li>min(p, 0) -> TOP</li>
   * <li>and([a1, and([a2,...,an])]) -> and([a1, a2, ..., an]))</li>
   * <li>and([a, not(a), ...]) -> BOTTOM</li>
   * <li>not(C) -> not(simplify(C))</li>
   * </ul>
   *
   * @param term
   * @return
   */
  public static ATermAppl simplify(ATermAppl term) {
    ATermAppl simp = term;
    AFun fun = term.getAFun();
    ATerm arg1 = (term.getArity() > 0)
      ? term.getArgument( 0 )
      : null;
    ATerm arg2 = (term.getArity() > 1)
      ? term.getArgument( 1 )
      : null;
    ATerm arg3 = (term.getArity() > 2)
      ? term.getArgument( 2 )
      : null;

    if( arg1 == null || fun.equals( SELFFUN ) || fun.equals( VALUEFUN ) || fun.equals( ATermUtils.RESTRDATATYPEFUN ) ) {
      // do nothing because term is primitive or self restriction
    }
    else if( fun.equals( NOTFUN ) ) {
      ATermAppl arg = (ATermAppl) arg1;
      if( isNot( arg ) ) {
              simp = simplify( (ATermAppl) arg.getArgument( 0 ) );
            }
            else if( isMin( arg ) ) {
        ATermInt n = (ATermInt) arg.getArgument( 1 );
        if( n.getInt() == 0 ) {
                  simp = BOTTOM;
                }
      }
    }
    else if( fun.equals( ANDFUN ) ) {
      ATermList conjuncts = (ATermList) arg1;
      if( conjuncts.isEmpty() ) {
              simp = TOP;
            }
            else {
        Set<ATermAppl> set = new HashSet<ATermAppl>();
        List<ATermAppl> negations = new ArrayList<ATermAppl>();
        MultiListIterator i = new MultiListIterator( conjuncts );
        while( i.hasNext() ) {
          ATermAppl c = i.next();
          if( c.equals( TOP ) ) {
                      continue;
                    }
                    else if( c.equals( BOTTOM ) ) {
                      return BOTTOM;
                    }
                    else if( isAnd( c ) ) {
                      i.append( (ATermList) c.getArgument( 0 ) );
                    }
                    else if( isNot( c ) ) {
                      negations.add( c );
                    }
                    else {
                      set.add( c );
                    }
        }

        for( ATermAppl notC : negations ) {
          ATermAppl c = (ATermAppl) notC.getArgument( 0 );
          if( set.contains( c ) ) {
                      return BOTTOM;
                    }
        }

        if( set.isEmpty() ) {
          if( negations.isEmpty() ) {
                      return TOP;
                    }
                    else if( negations.size() == 1 ) {
                      return negations.get( 0 );
                    }
        }
        else if( set.size() == 1 && negations.isEmpty() ) {
                  return set.iterator().next();
                }

        negations.addAll( set );
        int size = negations.size();
        ATermAppl[] terms = new ATermAppl[size];
        negations.toArray( terms );
        simp = makeAnd( toSet( terms, size ) );
      }
    }
    else if( fun.equals( ALLFUN ) ) {
      if( arg2.equals( TOP ) ) {
              simp = TOP;
            }
    }
    else if( fun.equals( MINFUN ) ) {
      ATermInt n = (ATermInt) arg2;
      if( n.getInt() == 0 ) {
              simp = TOP;
            }
      if( arg3.equals( ATermUtils.BOTTOM ) ) {
              simp = BOTTOM;
            }
    }
    else if( fun.equals( MAXFUN ) ) {
      ATermInt n = (ATermInt) arg2;
      if( n.getInt() > 0 && arg3.equals( ATermUtils.BOTTOM ) ) {
              simp = TOP;
            }
    }
        else {
          throw new InternalReasonerException( "Unknown term type: " + term );
        }

    return simp;
  }

  /**
   * Creates a simplified and assuming that all the elements have already been
   * normalized.
   *
   * @param conjuncts
   * @return
   */
  public static ATermAppl makeSimplifiedAnd(Collection<ATermAppl> conjuncts) {
    Set<ATermAppl> set = new HashSet<ATermAppl>();
    List<ATermAppl> negations = new ArrayList<ATermAppl>();
    MultiListIterator listIt = new MultiListIterator( EMPTY_LIST );
    Iterator<ATermAppl> i = new PairIterator<ATermAppl>( conjuncts.iterator(), listIt );
    while( i.hasNext() ) {
      ATermAppl c = i.next();
      if( c.equals( TOP ) ) {
              continue;
            }
            else if( c.equals( BOTTOM ) ) {
              return BOTTOM;
            }
            else if( isAnd( c ) ) {
              listIt.append( (ATermList) c.getArgument( 0 ) );
            }
            else if( isNot( c ) ) {
              negations.add( c );
            }
            else {
              set.add( c );
            }
    }

    for( ATermAppl notC : negations ) {
      ATermAppl c = (ATermAppl) notC.getArgument( 0 );
      if( set.contains( c ) ) {
              return BOTTOM;
            }
    }

    if( set.isEmpty() ) {
      if( negations.isEmpty() ) {
              return TOP;
            }
            else if( negations.size() == 1 ) {
              return negations.get( 0 );
            }
    }
    else if( set.size() == 1 && negations.isEmpty() ) {
          return set.iterator().next();
        }

    negations.addAll( set );
    int size = negations.size();
    ATermAppl[] terms = new ATermAppl[size];
    negations.toArray( terms );
    return makeAnd( toSet( terms, size ) );
  }

  public static Set<ATermAppl> findPrimitives(ATermAppl term) {
    Set<ATermAppl> primitives = new HashSet<ATermAppl>();

    findPrimitives( term, primitives, false, false );
    return primitives;
  }

  public static Set<ATermAppl> findPrimitives(ATermAppl term, boolean skipRestrictions,
      boolean skipTopLevel) {
    Set<ATermAppl> primitives = new HashSet<ATermAppl>();

    findPrimitives( term, primitives, skipRestrictions, skipTopLevel );

    return primitives;
  }
 
  public static void findPrimitives(ATermAppl term, Set<ATermAppl> primitives) {
    findPrimitives( term, primitives, false, false );
  }

  public static void findPrimitives(ATermAppl term, Set<ATermAppl> primitives,
      boolean skipRestrictions, boolean skipTopLevel) {
    AFun fun = term.getAFun();

    if( isPrimitive( term ) ) {
      primitives.add( term );
    }
    else if( fun.equals( SELFFUN ) || fun.equals( VALUEFUN ) || fun.equals( RESTRDATATYPEFUN ) ) {
      // do nothing because there is no atomic concept here
    }
    else if( fun.equals( NOTFUN ) ) {
      ATermAppl arg = (ATermAppl) term.getArgument( 0 );
      if( !isPrimitive( arg ) || !skipTopLevel ) {
              findPrimitives( arg, primitives, skipRestrictions, false );
            }
    }
    else if( fun.equals( ANDFUN ) || fun.equals( ORFUN ) ) {
      ATermList list = (ATermList) term.getArgument( 0 );
      while( !list.isEmpty() ) {
        ATermAppl arg = (ATermAppl) list.getFirst();
        if( !isNegatedPrimitive( arg ) || !skipTopLevel ) {
                  findPrimitives( arg, primitives, skipRestrictions, false );
                }
        list = list.getNext();
      }
    }
    else if( !skipRestrictions ) {
      if( fun.equals( ALLFUN ) || fun.equals( SOMEFUN ) ) {
        ATermAppl arg = (ATermAppl) term.getArgument( 1 );
        findPrimitives( arg, primitives, skipRestrictions, false );
      }
      else if( fun.equals( MAXFUN ) || fun.equals( MINFUN ) || fun.equals( CARDFUN ) ) {
        ATermAppl arg = (ATermAppl) term.getArgument( 2 );
        findPrimitives( arg, primitives, skipRestrictions, false );
      }
            else {
              throw new InternalReasonerException( "Unknown concept type: " + term );
            }
    }
  }
 
  public static Collection<ATermAppl> primitiveOrBottom(Collection<ATermAppl> collection) {
    List<ATermAppl> ret = new ArrayList<ATermAppl>();
    for( Iterator<ATermAppl> i = collection.iterator(); i.hasNext(); ) {
      ATermAppl a = i.next();
      if( isPrimitive( a ) || a == ATermUtils.BOTTOM ) {
              ret.add( a );
            }
    }
    return ret;
  }

  public static Set<ATermAppl> primitiveOrBottom(Set<ATermAppl> collection) {
    Set<ATermAppl> ret = new HashSet<ATermAppl>();
    for( Iterator<ATermAppl> i = collection.iterator(); i.hasNext(); ) {
      ATermAppl a = i.next();
      if( isPrimitive( a ) || a == ATermUtils.BOTTOM ) {
              ret.add( a );
            }
    }
    return ret;
  }

  public static ATermAppl makeRule(ATermAppl[] head, ATermAppl[] body) {
    return makeRule( null, head, body );
  }
 
  public static ATermAppl makeRule(ATermAppl name, ATermAppl[] head, ATermAppl[] body) {
    return factory.makeAppl( RULEFUN, name == null ? EMPTY : name, makeList(head), makeList(body) );   
  }
 
  public static ATermAppl makeBuiltinAtom(ATermAppl[] args) {   
    return factory.makeAppl( BUILTINFUN, makeList( args ) );
  }
}
TOP

Related Classes of org.mindswap.pellet.utils.ATermUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.