Package org.mindswap.pellet.tableau.completion

Source Code of org.mindswap.pellet.tableau.completion.SROIQIncStrategy

// 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) 2006 Christian Halaschek-Wiener
// Halaschek-Wiener 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.tableau.completion;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;

import org.mindswap.pellet.ABox;
import org.mindswap.pellet.DefaultEdge;
import org.mindswap.pellet.DependencySet;
import org.mindswap.pellet.Edge;
import org.mindswap.pellet.EdgeList;
import org.mindswap.pellet.Individual;
import org.mindswap.pellet.Node;
import org.mindswap.pellet.NodeMerge;
import org.mindswap.pellet.PelletOptions;
import org.mindswap.pellet.Role;
import org.mindswap.pellet.tableau.blocking.BlockingFactory;
import org.mindswap.pellet.tableau.branch.Branch;
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.Timer;

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

import com.clarkparsia.pellet.IncrementalChangeTracker;
import com.clarkparsia.pellet.expressivity.Expressivity;


/**
* The completion strategy for incremental consistency checking.
*
* @author Christian Halaschek-Wiener
*/
public class SROIQIncStrategy extends SROIQStrategy {
 
  /**
   * Constructor
   *
   * @param abox
   */
  public SROIQIncStrategy(ABox abox) {
    super(abox);
    }
    /**
     * Return individuals to which we need to apply the initialization rules
     * 
     * @return
     */
    public Iterator<Individual> getInitializeIterator() { 
      return abox.getIncrementalChangeTracker().updatedIndividuals();
 
   
   
    /**
     * Return individuals that were newly added
     * 
     * @return
     */
    public Iterator<Individual> getNewIterator() {
      return abox.getIncrementalChangeTracker().newIndividuals();
 
   
  /**
   * Return edges that were newly added
   *
   * @return
   */
  public Iterator<Edge> getNewEdgeIterator() {
    return abox.getIncrementalChangeTracker().newEdges();
  }
 
 
  /**
   * Return the unpruned indivdiuals
   *
   * @return
   */
  public Iterator<Node> getUnPrunedIterator() {
    return abox.getIncrementalChangeTracker().unprunedNodes();
  }
 
 
 
  /**
   * Return edges that were newly added
   *
   * @return
   */
  public Iterator<Edge> getRemovedEdgeIterator() {
    return abox.getIncrementalChangeTracker().deletedEdges();
  }
 
 
 
  /**
   * Return types that were deleted
   *
   * @return
   */
  public Iterator<Map.Entry<Node,Set<ATermAppl>>> getRemovedTypeIterator() {
    return abox.getIncrementalChangeTracker().deletedTypes();
  }
 

   
  /**
   * There are additional rule that must be fired in the event of incremental
   * additions and deletions in order to guarantee completeness. These are
   * done here.
   */
  public void initialize(Expressivity expr) {
   
    Timer t = abox.getKB().timers.startTimer("initialize");

    if(log.isLoggable( Level.FINE ))
      log.fine("Initialize Started");
   
    mergeList = new ArrayList<NodeMerge>();
   
        blocking = BlockingFactory.createBlocking( expr );

        configureTableauRules( expr );
       
    for (Branch branch : abox.getBranches()) {
      branch.setStrategy(this);
    }

    // if this is an incremental addition we may need to merge nodes and
    // handle newly added individuals

    // merge nodes - note branch must be temporarily set to 0 to
    // ensure that assertion
    // will not be restored during backtracking
    // int branch = abox.getBranch();
    abox.setBranch(0);
       
    mergeList.addAll(abox.getToBeMerged());
    if (!mergeList.isEmpty())
      mergeAll();

     //Apply necessary initialization to any new individual added
     //Currently, this is a replication of the code
     for( Iterator<Individual> newIt = getNewIterator(); newIt.hasNext(); ) {
      Individual n = newIt.next();

      if (n.isMerged())
        continue;

      applyUniversalRestrictions(n);
     
      unfoldingRule.apply( n );
     
      selfRule.apply(n);       
    }
    
    //handle nodes affected by the update
    for (Iterator<Individual> it = getInitializeIterator(); it.hasNext();) {
   
      Individual n = it.next();

      nominalRule.apply(n);
     
      if (n.isMerged()){
        n = n.getSame();
      }

      allValuesRule.apply( n );
    }
   
    //process new edges
    for(Iterator<Edge> it = getNewEdgeIterator(); it.hasNext();){
      Edge edge = it.next();
     
      Individual subj = edge.getFrom();
      Node obj = edge.getTo();
      if(subj.isMerged())
        subj.getSame();
      if(subj.isPruned())
        continue;

      if(obj.isMerged())
        obj.getSame();
      if(obj.isPruned())
        continue;

      Role pred = edge.getRole();       
      DependencySet ds = edge.getDepends();

      applyDomainRange(subj, pred, obj, ds);
      if (subj.isPruned() || obj.isPruned()) {
        return;
      }
      applyFunctionality(subj, pred, obj);
      if (subj.isPruned() || obj.isPruned()) {
        return;
      }

      if (pred.isObjectRole()) {
        Individual o = (Individual) obj;
        checkReflexivitySymmetry(subj, pred, o, ds);
        checkReflexivitySymmetry(o, pred.getInverse(), subj, ds);
      }
     
      //if the KB has cardinality restrictions, then we need to apply the guessing rule
          if(abox.getKB().getExpressivity().hasCardinality()){
            //update the queue so the max rule will be fired
              updateQueueAddEdge(subj, pred, obj);
          }
    }
   
    
    //merge again if necessary
    if (!mergeList.isEmpty())
      mergeAll();
   
    //set appropriate branch
    abox.setBranch(abox.getBranches().size() + 1);

    // we will also need to add stuff to the queue in the event of a
    // deletion   
     
    //Handle removed edges
    Iterator<Edge> i = getRemovedEdgeIterator();
    while( i.hasNext() ){       
      Edge e = i.next();
      Individual subj = e.getFrom();
      Node obj = e.getTo();
     
      subj = subj.getSame();
     
      subj.applyNext[Node.SOME] = 0;
      subj.applyNext[Node.MIN] = 0;
      QueueElement qe = new QueueElement( subj );
      abox.getCompletionQueue().add( qe, NodeSelector.EXISTENTIAL );
      abox.getCompletionQueue().add( qe, NodeSelector.MIN_NUMBER );
     
     
      obj = obj.getSame();
      if(obj instanceof Individual){
        Individual objInd = (Individual)obj;
        objInd.applyNext[Node.SOME] = 0;
        objInd.applyNext[Node.MIN] = 0;
        qe = new QueueElement( objInd );
        abox.getCompletionQueue().add( qe, NodeSelector.EXISTENTIAL );
        abox.getCompletionQueue().add( qe, NodeSelector.MIN_NUMBER );
      }               
    }

   
   
   
    //Handle removed types
    Iterator<Map.Entry<Node,Set<ATermAppl>>> it = getRemovedTypeIterator();
    while( it.hasNext() ){
      Node node = it.next().getKey();
     
      if( node.isIndividual() ){
        Individual ind = (Individual)node;

        //readd the conjunctions
        readdConjunctions( ind );
       
        //it could be the case that the type can be added from unfolding, a forAll application on a self loop, or the disjunction rule
        ind.applyNext[Node.ATOM] = 0;
        ind.applyNext[Node.ALL] = 0;
        ind.applyNext[Node.OR] = 0;

        QueueElement qe = new QueueElement( ind );
        abox.getCompletionQueue().add( qe, NodeSelector.ATOM );
        abox.getCompletionQueue().add( qe, NodeSelector.DISJUNCTION );

        //fire the all rule as the is no explicit call to it
        allValuesRule.apply( ind );
       
        //get out edges and check domains, some values and min values
        for( int j = 0; j < ind.getOutEdges().size(); j++ ){
          Edge e = ind.getOutEdges().edgeAt( j );
                       
          if( e.getFrom().isPruned() || e.getTo().isPruned() )
            continue;
                       
              Role pred = e.getRole();
              Node obj = e.getTo();
              DependencySet ds = e.getDepends();
         
              for( ATermAppl domain : pred.getDomains() ) {             
                if( requiredAddType( ind, domain ) ) {
              if( !PelletOptions.USE_TRACING )
                addType( ind, domain, ds.union( DependencySet.EMPTY, abox.doExplanation() ) );
              else        
                addType( ind, domain, ds.union( pred.getExplainDomain( domain ), abox.doExplanation() ) );
                }
              }

              //it could be the case that this label prevented the firing of the all values, some, or min rules of the neighbor
          if( obj instanceof Individual ){
            Individual objInd = (Individual)obj;
            objInd.applyNext[Node.ALL] = 0;
            objInd.applyNext[Node.SOME] = 0;
            objInd.applyNext[Node.MIN] = 0;
            QueueElement qeObj = new QueueElement( objInd );
            abox.getCompletionQueue().add( qeObj, NodeSelector.EXISTENTIAL );
            abox.getCompletionQueue().add( qeObj, NodeSelector.MIN_NUMBER );
           
            //apply the all values rule
            allValuesRule.apply( ind );
          }
        }
      }
       
     
      //get out edges
      for( int j = 0; j < node.getInEdges().size(); j++ ){
        Edge e = node.getInEdges().edgeAt( j );
                     
        if( e.getFrom().isPruned() || e.getTo().isPruned() )
          continue;
       
        Individual subj = e.getFrom();
              Role pred = e.getRole();              
              DependencySet ds = e.getDepends();
       
            for( ATermAppl range : pred.getRanges() ) {
              if( requiredAddType( node, range ) ) {
            if( !PelletOptions.USE_TRACING )
              addType( node, range, ds.union( DependencySet.EMPTY, abox.doExplanation() ) );
            else        
              addType( node, range, ds.union( pred.getExplainRange( range ), abox.doExplanation() ) );
              }
            }

            //it could be the case that this label prevented the firing of the all values, some, or min rules of the neighbor
        subj.applyNext[Node.ALL] = 0;
        subj.applyNext[Node.SOME] = 0;
        subj.applyNext[Node.MIN] = 0;
        QueueElement qe = new QueueElement( subj );
        abox.getCompletionQueue().add( qe, NodeSelector.EXISTENTIAL );
        abox.getCompletionQueue().add( qe, NodeSelector.MIN_NUMBER );

        allValuesRule.apply( subj );
      }
    }
   
   
    //due to unmerging nodes, edges can actually be added
    i = getNewEdgeIterator();
    while( i.hasNext() ){       
      applyPropertyRestrictions( i.next() );       
    }
   
   
    //due to unmerging any node that was pruned could need rules applied to it. This is because these rules
    //would have been originally applied to the node that the pruned node was merged into. 
    for(Iterator<Node> nodeIt = getUnPrunedIterator(); nodeIt.hasNext(); ) {
      Node n = nodeIt.next();
     
      if( n.isIndividual() ) {
        Individual ind = (Individual) n;
       
        //reset type pointers
        for( int j = 0; j < Node.TYPES; j++ )
          ind.applyNext[j] = 0;
       
        //add to all queues
        abox.getCompletionQueue().add( new QueueElement( ind ) );
       
        allValuesRule.apply( ind );
       
        //get out edges
        for( int j = 0; j < ind.getOutEdges().size(); j++ ){
          Edge e = ind.getOutEdges().edgeAt( j );
                       
          if( !e.getFrom().isPruned() && !e.getTo().isPruned() )
            applyPropertyRestrictions( e );
         
          Node obj = e.getTo();
          if( obj instanceof Individual ){
            Individual objInd = (Individual)obj;
            objInd.applyNext[Node.ALL] = 0;
            allValuesRule.apply( objInd );
          }
        }
         
       
        //get out edges
        for( int j = 0; j < ind.getInEdges().size(); j++ ){
          Edge e = ind.getInEdges().edgeAt( j );
                       
          if( !e.getFrom().isPruned() && !e.getTo().isPruned() )
            applyPropertyRestrictions( e );
         
          Individual subj= e.getFrom();
          subj.applyNext[Node.ALL] = 0;
          allValuesRule.apply( subj );
        }
      }
    }
   
        abox.setChanged( true );
        abox.setComplete( false );
        abox.setInitialized( true );

        t.stop();
       
    if(log.isLoggable( Level.FINE ))
      log.fine("Initialize Ended");
  }
    
    /**
   * Readd conjunction labels
   *
   * @param ind
   */
  protected void readdConjunctions( Individual ind ){
    for( ATermAppl conj : ind.getTypes() ){
      if( ATermUtils.isAnd( conj ) && ind.hasType( conj ) )
        addType(ind, conj, ind.getDepends( conj ) );
    }
  }
 
  /**
   * Test if a type should be readded to a node
   *
   * @param node
   * @param type
   * @return
   */
  protected boolean requiredAddType( Node node, ATermAppl type ){
    if( type == null || node.hasType( type ) && !ATermUtils.isAnd( type ) )
      return false;
    
    return true;   
  }
 
  @Override
  protected void restoreAllValues() {
    final IncrementalChangeTracker tracker = abox.getIncrementalChangeTracker();

    for( Iterator<Map.Entry<Node, Set<ATermAppl>>> it = tracker.deletedTypes(); it
        .hasNext(); ) {

      Map.Entry<Node, Set<ATermAppl>> entry = it.next();
      Node node = entry.getKey();
      Set<ATermAppl> types = entry.getValue();
     
      // find the edges which the all values rule needs to be
      // re-applied to
      EdgeList av = findAllValues( node, types );
     
      //apply the all values rules
      for(int i = 0; i < av.size(); i++){
        Edge e = av.edgeAt( i );           
        allValuesRule.applyAllValues( e.getFrom(), e.getRole(), e.getTo(), e.getDepends() );
      }
    }
   
    for( Iterator<Node> i = tracker.unprunedNodes(); i.hasNext(); ) {
      Node node = i.next();
     
      if( node instanceof Individual ){
        Individual ind = (Individual)node;
        //reset type pointers
        for( int j = 0; j < Node.TYPES; j++ )
          ind.applyNext[j] = 0;
       
        //add to all queues
        abox.getCompletionQueue().add( new QueueElement( ind ) );
       
        allValuesRule.apply( ind );
       
        //get out edges
        for( int j = 0; j < ind.getOutEdges().size(); j++ ){
          Edge e = ind.getOutEdges().edgeAt( j );
         
          Node obj = e.getTo();
          if( obj instanceof Individual ){
            Individual objInd = (Individual)obj;
            objInd.applyNext[Node.ALL] = 0;
            allValuesRule.apply( objInd );
          }
        }
      }
           
      //get out edges
      for( int j = 0; j < node.getInEdges().size(); j++ ){
        Edge e = node.getInEdges().edgeAt( j );
        Individual subj= e.getFrom();
        subj.applyNext[Node.ALL] = 0;
        allValuesRule.apply( subj );
      }
    }   
  }
 
  /**
   * Find applicable all values for a removed type during a restore
   *
   * @param node
   * @param removedTypes
   * @return
   */
  protected EdgeList findAllValues( Node node, Set<ATermAppl> removedTypes){
    EdgeList edges = new EdgeList();
   
    //handle in edges
    for(int i = 0; i < node.getInEdges().size(); i++){
      Edge e = node.getInEdges().edgeAt( i );
     
      edges.addEdgeList( findAllValues( node, e.getFrom(), removedTypes, e ) );
    }
   
   
    if( node instanceof Individual ){
      Individual ind = (Individual)node;     
     
      //handle in edges
      for(int i = 0; i < ind.getOutEdges().size(); i++){
        Edge e = ind.getOutEdges().edgeAt( i );
        Node to = e.getTo();
       
        Role inv = e.getRole().getInverse();
       
        if(inv != null && to instanceof Individual)
          edges.addEdgeList( findAllValues( ind, (Individual)to, removedTypes, new DefaultEdge( inv, (Individual)to, ind, e.getDepends() ) ) ) ;
      }
    }
   
   
    return edges;
  }

 
  /**
   * Method to find the edges which an all values could be applied to
   * 
   * @param node
   * @param neighbor
   * @param removedTypes
   * @param edge
   * @return
   */
  protected EdgeList findAllValues( Node node, Individual neighbor, Set<ATermAppl> removedTypes, Edge edge){
    EdgeList edges = new EdgeList();
   
    boolean applicable = false;   
    List<ATermAppl> avTypes = neighbor.getTypes( Node.ALL );
    List<ATermAppl> applicableRoles = new ArrayList<ATermAppl>();
   
    //inspect all values for a recently deleted type
    for( int i = 0; i < avTypes.size(); i++ ){
      ATermAppl avType = avTypes.get( i );
      ATermAppl role = (ATermAppl) avType.getArgument( 0 );
      ATermAppl type = (ATermAppl) avType.getArgument( 1 );
     
      //if we cannot use this edge then continue
      if( edge != null && !edge.getRole().isSubRoleOf( abox.getRole( role ) ) )
        continue;
     
      if( containsType( type, removedTypes ) ){
        applicable = true;       
        applicableRoles.add( type );
      }
    }
   
    //only proceed if necessary
    if( !applicable )
      return edges;
   
    //two cases depending on input
    if(edge == null){
      //get all edges to this node
      for( int i = 0; i < applicableRoles.size(); i++ ){
        ATerm p = applicableRoles.get( i );
        Role role = abox.getRole( p );

        edges.addEdgeList( neighbor.getRNeighborEdges( role, node ) );
      }     
    }else{
      edges.addEdge( edge );
    }
   
    return edges;
  }
   
 
 
  /**
   * Check if a node contains a particular type that has been removed
   * @param type
   * @param removedTypes
   * @return
   */
  private boolean containsType( ATermAppl type, Set<ATermAppl> removedTypes ){   
    boolean contains = false;
   
   
    if(ATermUtils.isAnd( type )){
      for(ATermList cs = (ATermList) type.getArgument(0); !cs.isEmpty(); cs = cs.getNext()) {
        ATermAppl conj = (ATermAppl) cs.getFirst();
       
        if( containsType( conj, removedTypes ) ){
          contains = true;
          break;
        }
      }   
    }else if( removedTypes.contains( type )){
      contains = true;
    }

    return contains;
  }

}
TOP

Related Classes of org.mindswap.pellet.tableau.completion.SROIQIncStrategy

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.