Package org.mindswap.pellet

Source Code of org.mindswap.pellet.Node

// 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;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import java.util.logging.Level;
import java.util.logging.Logger;
import org.mindswap.pellet.exceptions.InternalReasonerException;
import org.mindswap.pellet.tableau.completion.queue.NodeSelector;
import org.mindswap.pellet.tableau.completion.queue.QueueElement;
import org.mindswap.pellet.utils.ATermUtils;
import org.mindswap.pellet.utils.Bool;
import org.mindswap.pellet.utils.SetUtils;

import aterm.ATerm;
import aterm.ATermAppl;
import aterm.ATermList;

import com.clarkparsia.pellet.utils.CollectionUtils;

/**
* @author Evren Sirin
*
*/
public abstract class Node {
  public final static Logger log = Logger.getLogger( Node.class.getName() );
 
  public final static int BLOCKABLE = Integer.MAX_VALUE;
  public final static int NOMINAL   = 0;
 
  public final static int CHANGED   = 0x7F;
  public final static int UNCHANGED = 0x00;
  public final static int ATOM = 0;
  public final static int OR   = 1;
  public final static int SOME = 2;
  public final static int ALL  = 3;
  public final static int MIN  = 4;
  public final static int MAX  = 5;
  public final static int NOM  = 6;
  public final static int TYPES = 7;
 
  protected ABox abox;
  protected ATermAppl name;
  protected Map<ATermAppl, DependencySet> depends;
  private boolean isRoot;
  private boolean isConceptRoot;   
 
  /**
   * If this node is merged to another one, points to that node otherwise
   * points to itself. This is a linked list implementation of disjoint-union
   * data structure.
   */
  protected Node mergedTo = this;
   
    protected EdgeList inEdges;
 
  /**
   * Dependency information about why merged happened (if at all)
   */
  protected DependencySet mergeDepends = null;
 
  protected DependencySet pruned = null;
 
  /**
   * Set of other nodes that have been merged to this node. Note that this
   * is only the set of nodes directly merged to this one. A recursive traversal
   * is required to get all the merged nodes.
   */
  protected Set<Node> merged;
 
  protected Map<Node, DependencySet> differents;
 
  protected Node(ATermAppl name, ABox abox) {
    this.name = name;
    this.abox = abox;   

    isRoot = !ATermUtils.isAnon( name );
    isConceptRoot = false;
   
    mergeDepends = DependencySet.INDEPENDENT;
    differents = CollectionUtils.makeMap();
    depends = CollectionUtils.makeMap();

        inEdges = new EdgeList();
  }

  protected Node(Node node, ABox abox) {
    this.name = node.getName();
    this.abox = abox;

    isRoot = node.isRoot;
    isConceptRoot = node.isConceptRoot;
   
    mergeDepends = node.mergeDepends;
    mergedTo = node.mergedTo;
    merged = node.merged;
    pruned = node.pruned;

    // do not copy differents right now because we need to
    // update node references later anyway
    differents = node.differents;
    depends = CollectionUtils.makeMap(node.depends);
           
        inEdges = node.inEdges;
  }
 
  @Override
  public int hashCode() {
      return name.hashCode();
  }
 
  @Override
  public boolean equals(Object obj) {
      return (obj == this) || ((obj.getClass() == getClass()) && ((Node) obj).name.equals(name));
  }
 
  protected void updateNodeReferences() {
        mergedTo = abox.getNode( mergedTo.getName() );

        Map<Node, DependencySet> diffs = new HashMap<Node, DependencySet>( differents.size() );
        for(Map.Entry<Node, DependencySet> entry : differents.entrySet() ) {
            Node node = entry.getKey();

            diffs.put( abox.getNode( node.getName() ), entry.getValue() );
        }
        differents = diffs;

        if( merged != null ) {
            Set<Node> sames = new HashSet<Node>( merged.size() );
            for( Node node : merged ) {
                sames.add( abox.getNode( node.getName() ) );
            }
            merged = sames;
        }       
       
        EdgeList oldEdges = inEdges;
        inEdges = new EdgeList(oldEdges.size());
        for(int i = 0; i < oldEdges.size(); i++) {
            Edge edge = oldEdges.edgeAt(i);
           
            Individual from = abox.getIndividual( edge.getFrom().getName() );
      Edge newEdge = new DefaultEdge( edge.getRole(), from, this, edge.getDepends() );
     
      inEdges.addEdge( newEdge );       
      if( !isPruned() )
        from.getOutEdges().addEdge( newEdge );
        }
    }

  /**
   * Indicates that node has been changed in a way that requires us to recheck
   * the concepts of given type.
   * 
   * @param type type of concepts that need to be rechecked
   */
  public void setChanged(int type) {   
    //Check if we need to updated the completion queue
    //Currently we only updated the changed lists for checkDatatypeCount()
    QueueElement newElement = new QueueElement(this);

    //update the datatype queue
    if( (type == Node.ALL || type == Node.MIN) && PelletOptions.USE_COMPLETION_QUEUE )
      abox.getCompletionQueue().add( newElement, NodeSelector.DATATYPE );   

    // add node to effected list
    if( abox.getBranch() >= 0 && PelletOptions.TRACK_BRANCH_EFFECTS )
      abox.getBranchEffectTracker().add( abox.getBranch(), this.getName() );
 

 
  /**
   * Returns true if this is the node created for the concept satisfiability check.
   * 
   * @return
   */
  public boolean isConceptRoot() {
      return isConceptRoot;
  }
 
  public void setConceptRoot( boolean isConceptRoot ) {
      this.isConceptRoot = isConceptRoot;
  }
 
  public boolean isBnode() {
    return ATermUtils.isBnode( name );
  }

  public boolean isNamedIndividual() {
    return isRoot && !isConceptRoot && !isBnode();
  }
 
  public boolean isRoot() {
    return isRoot || isNominal();
 
 
  public abstract boolean isLeaf();
   
  public boolean isRootNominal() {
    return isRoot && isNominal();
  }
 
  public abstract Node copyTo(ABox abox);
 
  protected void addInEdge(Edge edge) {
        inEdges.addEdge( edge );  
    }

    public EdgeList getInEdges() {
      return inEdges;
   
   
    public boolean removeInEdge(Edge edge) {
        boolean removed = inEdges.removeEdge(edge);
       
        if( !removed ){
         throw new InternalReasonerException("Trying to remove a non-existing edge " + edge);          
        }
       
        return true;
    }
   
    public void removeInEdges() {
        inEdges = new EdgeList();
    }

    public void reset(boolean onlyApplyTypes) {
      assert onlyApplyTypes || isRootNominal() : "Only asserted individuals can be reset: " + this;
     
    if( PelletOptions.USE_COMPLETION_QUEUE )
      abox.getCompletionQueue().add( new QueueElement( this ) );
   
    if( onlyApplyTypes )
      return;
   
    if( pruned != null )
      unprune( DependencySet.NO_BRANCH );
   
      mergedTo = this;
      mergeDepends = DependencySet.INDEPENDENT;
      merged = null;
     
      Iterator<DependencySet> i = differents.values().iterator();
      while( i.hasNext()) {
        DependencySet d = i.next();
      if( d.getBranch() != DependencySet.NO_BRANCH ) {
        i.remove();
      }         
    }
     
      resetTypes();
     
      inEdges.reset();
    }
   
    protected void resetTypes() {
      Iterator<DependencySet> i = depends.values().iterator();
      while( i.hasNext()) {
        DependencySet d = i.next();
      if( d.getBranch() != DependencySet.NO_BRANCH ) {
        i.remove();
      }         
    }
    }
   
  public Boolean restorePruned(int branch) {   

    if( PelletOptions.TRACK_BRANCH_EFFECTS )
      abox.getBranchEffectTracker().add( abox.getBranch(), name );

    if( pruned != null ) {
      if( pruned.getBranch() > branch ) {     
        if( log.isLoggable( Level.FINE ) )
            log.fine("RESTORE: " + this + " merged node " + mergedTo + " " + mergeDepends);
       
        if( mergeDepends.getBranch() > branch )
            undoSetSame();
       
        unprune( branch );

        if( PelletOptions.USE_INCREMENTAL_CONSISTENCY )
          abox.getIncrementalChangeTracker().addUnprunedNode( this );

        // we may need to remerge this node
        if( this instanceof Individual ) {
          final Individual ind = (Individual) this;

          if( PelletOptions.USE_COMPLETION_QUEUE ) {
            ind.applyNext[Node.NOM] = 0;
            abox.getCompletionQueue().add( new QueueElement( this ),
                NodeSelector.NOMINAL );
          }

        }

        return Boolean.TRUE;
      }
      else {
        if( log.isLoggable( Level.FINE ) )
          log.fine("DO NOT RESTORE: pruned node " + this + " = " + mergedTo + " " + mergeDepends)

        return Boolean.FALSE;
      }
      }
     
      return null;
  }
 
 
  public boolean restore(int branch) {   

    if( PelletOptions.TRACK_BRANCH_EFFECTS )
      abox.getBranchEffectTracker().add( abox.getBranch(), name );

    boolean restored = false;
   
    List<ATermAppl> conjunctions = new ArrayList<ATermAppl>();

   
    boolean removed = false;
   
    for( Iterator<ATermAppl> i = getTypes().iterator(); i.hasNext(); ) {                 
      ATermAppl c = i.next()
      DependencySet d = getDepends(c);
     
      boolean removeType = PelletOptions.USE_SMART_RESTORE
//                ? ( !d.contains( branch ) )
                ? ( d.max() >= branch )
        : ( d.getBranch() > branch )

      if( removeType ) {
        removed = true;
       
        if( log.isLoggable( Level.FINE ) )
                    log.fine("RESTORE: " + this + " remove type " + c + " " + d + " " + branch);
       
        //track that this node is affected
        if( PelletOptions.USE_INCREMENTAL_CONSISTENCY && this instanceof Individual ) {
          abox.getIncrementalChangeTracker().addDeletedType( this, c );
        }
               
        i.remove();
        removeType(c);
        restored = true;
      }
      else if( PelletOptions.USE_SMART_RESTORE && ATermUtils.isAnd( c ) ) {
          conjunctions.add( c );
      }         
    }     
   
    //update the queue with things that could readd this type
    if( removed && PelletOptions.USE_COMPLETION_QUEUE && this instanceof Individual ) {
      Individual ind = (Individual)this;
      ind.applyNext[Node.ATOM] = 0;
      ind.applyNext[Node.OR] = 0;
     
      QueueElement qe = new QueueElement( this );
      abox.getCompletionQueue().add( qe, NodeSelector.DISJUNCTION );
      abox.getCompletionQueue().add( qe, NodeSelector.ATOM );
    }

   
    // with smart restore there is a possibility that we remove a conjunct
    // but not the conjunction. this is the case if conjunct was added before
    // the conjunction but depended on an earlier branch. so we need to make
    // sure all conjunctions are actually applied
    if( PelletOptions.USE_SMART_RESTORE ) {
      for( Iterator<ATermAppl> i = conjunctions.iterator(); i.hasNext(); ) {
        ATermAppl c = i.next();
        DependencySet d = getDepends(c);
        for(ATermList cs = (ATermList) c.getArgument(0); !cs.isEmpty(); cs = cs.getNext()) {
          ATermAppl conj = (ATermAppl) cs.getFirst();
         
          addType(conj, d);
        }           
          }
    }       
       
    for( Iterator<Entry<Node,DependencySet>> i = differents.entrySet().iterator(); i.hasNext(); ) {
      Entry<Node,DependencySet> entry = i.next();
      Node node = entry.getKey();
      DependencySet d = entry.getValue();

      if( d.getBranch() > branch ) {     
        if( log.isLoggable( Level.FINE ) )
          log.fine("RESTORE: " + name + " delete difference " + node);
        i.remove();
        restored = true;
      }     
    }
   
    removed = false;
    for( Iterator<Edge> i = inEdges.iterator(); i.hasNext(); ) {
      Edge e = i.next();
      DependencySet d = e.getDepends();
           
      if( d.getBranch() > branch ) {          
        if( log.isLoggable( Level.FINE ) )
          log.fine("RESTORE: " + name + " delete reverse edge " + e);
               
        if( PelletOptions.USE_INCREMENTAL_CONSISTENCY )
          abox.getIncrementalChangeTracker().addDeletedEdge( e );

        i.remove();
        restored = true;
        removed = true;
      }          
    }
   
    if( removed && PelletOptions.USE_COMPLETION_QUEUE ) {
      QueueElement qe = new QueueElement( this );
      abox.getCompletionQueue().add( qe, NodeSelector.EXISTENTIAL );
      abox.getCompletionQueue().add( qe, NodeSelector.MIN_NUMBER );
    }

    return restored;
  }
 
  public void addType(ATermAppl c, DependencySet ds) {
      if( isPruned() )
          throw new InternalReasonerException( "Adding type to a pruned node " + this + " " + c );
      else if( isMerged() )
          return;
     
      // add to effected list
      if( abox.getBranch() >= 0 && PelletOptions.TRACK_BRANCH_EFFECTS ) {
      abox.getBranchEffectTracker().add( abox.getBranch(), this.getName() );
    }
   
    int b = abox.getBranch();
   
    int max = ds.max();
    if(b == -1 && max != 0)
        b = max + 1;
    ds = ds.copy( b );
    depends.put(c, ds);
   
    abox.setChanged( true );
  }

  public boolean removeType(ATermAppl c) {
    return depends.remove(c) != null;
  }

  public boolean hasType(ATerm c) {
    return depends.containsKey(c);
  }
 
  public Bool hasObviousType(ATermAppl c) {
    DependencySet ds = getDepends( c );

    if( ds != null ) {
      if( ds.isIndependent() ) {
        return Bool.TRUE;
      }
    }
    else if( (ds = getDepends(ATermUtils.negate(c))) != null ) {
      if( ds.isIndependent() ) {
        return Bool.FALSE;
      }
    }
    else if( isIndividual() && ATermUtils.isNominal( c ) ) {
      // TODO probably redundant if : Bool.FALSE
      if( !c.getArgument( 0 ).equals( this.getName() ) ) {
        return Bool.FALSE;
      }
      else {
        return Bool.TRUE;
      }
    }

    if( isIndividual() ) {
      ATermAppl r = null;
      ATermAppl d = null;

      if( ATermUtils.isNot( c ) ) {
        final ATermAppl notC = (ATermAppl) c.getArgument( 0 );
        if( ATermUtils.isAllValues( notC ) ) {
          r = (ATermAppl) notC.getArgument( 0 );
          d = ATermUtils.negate( (ATermAppl) notC.getArgument( 1 ) );
        }
      }
      else if( ATermUtils.isSomeValues( c ) ) {
        r = (ATermAppl) c.getArgument( 0 );
        d = (ATermAppl) c.getArgument( 1 );
      }

      if( r != null ) {
        Individual ind = (Individual) this;

        Role role = abox.getRole( r );

        if( !role.isObjectRole() || !role.isSimple() ) {
          return Bool.UNKNOWN;
        }

        EdgeList edges = ind.getRNeighborEdges( role );

        Bool ot = Bool.FALSE;

        for( int e = 0; e < edges.size(); e++ ) {
          Edge edge = edges.edgeAt( e );

          if( !edge.getDepends().isIndependent() ) {
            ot = Bool.UNKNOWN;
            continue;
          }

          Individual y = (Individual) edge.getNeighbor( ind );

          // TODO all this stuff in one method - this is only for
          // handling AND
          // clauses - they are implemented in abox.isKnownType
          ot = ot.or( abox.isKnownType( y, d, SetUtils.<ATermAppl>emptySet() ) );// y.hasObviousType(d));

          if( ot.isTrue() ) {
            return ot;
          }
        }
        return ot;
      }
    }

    return Bool.UNKNOWN;
  }

  public boolean hasObviousType( Collection<ATermAppl> coll ) {
    for(Iterator<ATermAppl> i = coll.iterator(); i.hasNext();) {
            ATermAppl c = i.next();
           
        DependencySet ds = getDepends( c );
       
        if( ds != null && ds.isIndependent() )
          return true;
        }
   
    return false;
  }     

  boolean hasPredecessor( Individual x ) {
    return x.hasSuccessor( this );
  }
 
  public abstract boolean hasSuccessor( Node x );
 
  public abstract DependencySet getNodeDepends();
 
  public DependencySet getDepends(ATerm c) {
    return depends.get(c);
  }
 
  public Map<ATermAppl,DependencySet> getDepends() {
    return depends;
  }
 
  public Set<ATermAppl> getTypes() {
    return depends.keySet();
 

  public void removeTypes() {
    depends.clear();
  }

  public int prunedAt() {     
    return pruned.getBranch();
  }
 
  public boolean isPruned() {
    return pruned != null;
  }
 
  public DependencySet getPruned() {
    return pruned;
  }
   
  public abstract void prune(DependencySet ds);

  public void unprune( int branch ) {
        pruned = null;

        boolean added = false;
       
        for(int i = 0; i < inEdges.size(); i++) {
            Edge edge = inEdges.edgeAt( i );
            DependencySet d = edge.getDepends();

            if( d.getBranch() <= branch ) {
                Individual pred = edge.getFrom();
                Role role = edge.getRole();

                // if both pred and *this* were merged to other nodes (in that order)
                // there is a chance we might duplicate the edge so first check for
                // the existence of the edge
                if( !pred.getOutEdges().hasExactEdge( pred, role, this ) ) {
                    pred.addOutEdge( edge );

                    // update affected
          if( PelletOptions.TRACK_BRANCH_EFFECTS ) {
            abox.getBranchEffectTracker().add( d.getBranch(), pred.name );
            abox.getBranchEffectTracker().add( d.getBranch(), name );
          }
                   
                    if( PelletOptions.USE_COMPLETION_QUEUE ){
                        added = true;
                        pred.applyNext[Node.MAX] = 0;
                       
                        QueueElement qe = new QueueElement( pred );
                      abox.getCompletionQueue().add( qe, NodeSelector.MAX_NUMBER );
                      abox.getCompletionQueue().add( qe, NodeSelector.GUESS );
                      abox.getCompletionQueue().add( qe, NodeSelector.CHOOSE );
                      abox.getCompletionQueue().add( qe, NodeSelector.UNIVERSAL );      
                    }
                   
                    if( log.isLoggable( Level.FINE ) )
                        log.fine( "RESTORE: " + name + " ADD reverse edge " + edge );
                }
            }
        }
       
        if( added ){
          if( this instanceof Individual ){
            Individual ind = (Individual)this;
            ind.applyNext[Node.MAX] = 0;
            QueueElement qe = new QueueElement( ind );
            abox.getCompletionQueue().add( qe, NodeSelector.MAX_NUMBER );
            abox.getCompletionQueue().add( qe, NodeSelector.GUESS );
            abox.getCompletionQueue().add( qe, NodeSelector.CHOOSE );
            abox.getCompletionQueue().add( qe, NodeSelector.UNIVERSAL );      
          }
        }
    }

  public abstract int getNominalLevel();
 
  public abstract boolean isNominal();
 
  public abstract boolean isBlockable();
 
  public abstract boolean isLiteral();
 
  public abstract boolean isIndividual();
 
  public int mergedAt() {     
    return mergeDepends.getBranch();
  }
 
  public boolean isMerged() {
    return mergedTo != this;
  }

  public Node getMergedTo() {
    return mergedTo;
  }
 
//  public DependencySet getMergeDependency() {
//    return mergeDepends;
//  }
 
    /**
     * Get the dependency if this node is merged to another node. This
     * node may be merged to another node which is later merged to another
     * node and so on. This function may return the dependency for the
     * first step or the union of all steps.
     *
     */
    public DependencySet getMergeDependency( boolean all ) {
        if( !isMerged() || !all )
            return mergeDepends;

        DependencySet ds = mergeDepends;
        Node node = mergedTo;
        while( node.isMerged() ) {
            ds = ds.union( node.mergeDepends, abox.doExplanation() );
            node = node.mergedTo;           
        }
       
        return ds;
    }
   
  public Node getSame() {
    if(mergedTo == this)
      return this;
   
    return mergedTo.getSame();
  }
 
  public void undoSetSame() {
    mergedTo.removeMerged( this );
    mergeDepends = DependencySet.INDEPENDENT;
    mergedTo = this;     
  }
 
  private void addMerged( Node node ) {
      if( merged == null )
          merged = new HashSet<Node>( 3 );
      merged.add( node );
  }
   
  public Set<Node> getMerged() {
    if ( merged == null )
      return SetUtils.emptySet();
      return merged;
  }
 
  public Map<Node,DependencySet> getAllMerged() {
    Map<Node,DependencySet> result = new HashMap<Node,DependencySet>();
    getAllMerged( DependencySet.INDEPENDENT, result );
    return result;
  }
 
  private void getAllMerged(DependencySet ds, Map<Node,DependencySet> result) {
    if ( merged == null )
      return;
   
    for( Node mergedNode : merged ) {
      DependencySet mergeDS = ds.union( mergedNode.getMergeDependency( false ), false );
      result.put( mergedNode, mergeDS );
      mergedNode.getAllMerged( mergeDS, result );
    }   
  }
 
  private void removeMerged( Node node ) {
      merged.remove( node );
      if( merged.isEmpty() )
          merged = null; // free space
  }
 
  public boolean setSame(Node node, DependencySet ds) {
    if( isSame( node ) )
        return false;
        if( isDifferent( node ) ) {
            //CHW - added for incremental reasoning support - this is needed as we will need to backjump if possible
            if(PelletOptions.USE_INCREMENTAL_CONSISTENCY)
              abox.setClash( Clash.nominal( this, ds.union(this.mergeDepends, abox.doExplanation()).union(node.mergeDepends, abox.doExplanation()), node.getName() ));
            else
              abox.setClash( Clash.nominal( this, ds, node.getName() ) );
           
        return false;
    }
   
    mergedTo = node;
    mergeDepends = ds.copy( abox.getBranch() );
    node.addMerged( this );
    return true;
  }
 
  public boolean isSame(Node node) {
    return getSame().equals( node.getSame() );
  }
   
  public boolean isDifferent( Node node ) {
    return differents.containsKey(node);
  }
   
  public Set<Node> getDifferents() {
    return differents.keySet();
  }

  public DependencySet getDifferenceDependency(Node node) {
    return differents.get(node);
 

  public boolean setDifferent(Node node, DependencySet ds) {

    // add to effected list
    if( abox.getBranch() >= 0 && PelletOptions.TRACK_BRANCH_EFFECTS )
      abox.getBranchEffectTracker().add( abox.getBranch(), node.getName() );

    if( isDifferent( node ) )
      return false;
    if( isSame( node ) ) {
      ds = ds.union( this.getMergeDependency( true ), abox.doExplanation() );
      ds = ds.union( node.getMergeDependency( true ), abox.doExplanation() );
      abox.setClash( Clash.nominal( this, ds, node.getName() ));

      if (!ds.isIndependent()) {
        return false;
      }
    }
   
    ds = ds.copy( abox.getBranch() );
    differents.put(node, ds);
    node.setDifferent(this, ds);
    abox.setChanged( true );
    return true;
  }
 
  public void inheritDifferents( Node y, DependencySet ds ) {
    for( Map.Entry<Node,DependencySet> entry : y.differents.entrySet() ) {
      Node yDiff = entry.getKey();
      DependencySet finalDS = ds.union( entry.getValue(), abox.doExplanation() );
     
      setDifferent( yDiff, finalDS );
    }
  }

  public ATermAppl getName() {
    return name;
  }
 
  public abstract ATermAppl getTerm();
 
  public String getNameStr() {
    return name.getName();
  }
 
  public String toString() {
    return ATermUtils.toString( name );
  }
 
  /**
   * A string that identifies this node either using its name or the path
   * of individuals that comes to this node. For example, a node that has
   * been generated by the completion rules needs to be identified with
   * respect to a named individual. Ultimately, we need the shortest path
   * or something like that but right now we just use the first inEdge
   *
   * @return
   */
  public List<ATermAppl> getPath() { 
      LinkedList<ATermAppl> path = new LinkedList<ATermAppl>();

        if(isNamedIndividual())
            path.add(name);
      else {
            Set<Node> cycle = new HashSet<Node>();
        Node node = this;
        while(!node.getInEdges().isEmpty()) {
            Edge inEdge = node.getInEdges().edgeAt(0);
            node = inEdge.getFrom();
                if( cycle.contains( node ) )
                    break;
                else
                    cycle.add( node );
              path.addFirst( inEdge.getRole().getName() );
                if( node.isNamedIndividual() ) {
                    path.addFirst( node.getName() );
                    break;
                }
        }
      }
     
   
    return path;
  }
 

  /**
   * getABox
   *
   * @return
   */
  public ABox getABox() {
    return abox;
  }
}

TOP

Related Classes of org.mindswap.pellet.Node

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.