Package org.mindswap.pellet.tableau.completion.incremental

Source Code of org.mindswap.pellet.tableau.completion.incremental.IncrementalRestore

// Copyright (c) 2006 - 2008, Clark & Parsia, LLC. <http://www.clarkparsia.com>
// This source code is 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

package org.mindswap.pellet.tableau.completion.incremental;

import java.util.logging.Level;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.mindswap.pellet.DependencySet;
import org.mindswap.pellet.Edge;
import org.mindswap.pellet.EdgeList;
import org.mindswap.pellet.Individual;
import org.mindswap.pellet.KnowledgeBase;
import org.mindswap.pellet.Node;
import org.mindswap.pellet.PelletOptions;
import org.mindswap.pellet.Role;
import org.mindswap.pellet.exceptions.InternalReasonerException;
import org.mindswap.pellet.tableau.branch.Branch;
import org.mindswap.pellet.utils.ATermUtils;
import org.mindswap.pellet.utils.intset.IntSet;

import aterm.ATermAppl;

import com.clarkparsia.pellet.IncrementalChangeTracker;

/**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2008</p>
*
* <p>Company: Clark & Parsia, LLC. <http://www.clarkparsia.com></p>
*
* @author Evren Sirin
*/
public class IncrementalRestore {
  public static void restoreDependencies(KnowledgeBase kb) {
    IncrementalRestore restore = new IncrementalRestore( kb );
    restore.restoreDependencies();
  }
 
  private KnowledgeBase kb; 

  private IncrementalRestore(KnowledgeBase kb) {
    this.kb = kb;
  }

  /**
   * Restore a branch add dependency
   *
   * @param assertion
   * @param branch
   */
  private void restoreBranchAdd(ATermAppl assertion, BranchAddDependency branch) {
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "    Removing branch add? " + branch.getBranch() );
 
    // get merge dependency
    DependencySet ds = branch.getBranch().getTermDepends();
 
    // remove the dependency
    ds.removeExplain( assertion );
 
    // undo merge if empty
    if( ds.getExplain().isEmpty() ) {
      if( DependencyIndex.log.isLoggable( Level.FINE ) )
        DependencyIndex.log.fine( "           Actually removing branch!" );
 
      Collection<ATermAppl> allEffects = PelletOptions.TRACK_BRANCH_EFFECTS
        ? kb.getABox().getBranchEffectTracker().getAll( branch.getBranch().getBranch() )
        : kb.getABox().getNodeNames();
 
      List<IntSet> updatedList = new ArrayList<IntSet>();
 
      for( ATermAppl a : allEffects ) {
 
        // get the actual node
        Node node = kb.getABox().getNode( a );
 
        // update type dependencies
        Map<ATermAppl,DependencySet> types = node.getDepends();
 
        for( Entry<ATermAppl,DependencySet> entry : types.entrySet() ) {
          // get ds for type
          DependencySet tDS = entry.getValue();
 
          // DependencySet.copy() does not create a new bitset object,
          // so we need to track which bitsets have been
          // updated, so we do not process the same bitset multiple
          // times
          boolean exit = false;
          for( int i = 0; i < updatedList.size(); i++ ) {
            if( updatedList.get( i ) == tDS.getDepends() )
              exit = true;
          }
 
          if( exit )
            continue;
 
          updatedList.add( tDS.getDepends() );
 
          // update branch if necessary
          if( tDS.getBranch() > branch.getBranch().getBranch() ) {
            tDS = tDS.copy( tDS.getBranch() - 1 );
          }
 
          for( int i = branch.getBranch().getBranch(); i <= kb.getABox().getBranches().size(); i++ ) {
            // update dependency set
            if( tDS.contains( i ) ) {
              tDS.remove( i );
              tDS.add( i - 1 );
            }
          }
         
          entry.setValue( tDS );
        }
 
        // update edge depdencies
        EdgeList edges = node.getInEdges();
        for( Edge edge: edges ) {
          DependencySet tDS = edge.getDepends();
 
          // DependencySet.copy() does not create a new bitset object,
          // so we need to track which bitsets have been
          // updated, so we do not process the same bitset multiple
          // times
          boolean exit = false;
          for( int i = 0; i < updatedList.size(); i++ ) {
            if( updatedList.get( i ) == tDS.getDepends() )
              exit = true;
          }
 
          if( exit )
            continue;
 
          updatedList.add( tDS.getDepends() );
 
          // update branch if necessary
          if( tDS.getBranch() > branch.getBranch().getBranch() )
            tDS = tDS.copy( edge.getDepends().getBranch() - 1 );
 
          for( int i = branch.getBranch().getBranch(); i <= kb.getABox().getBranches().size(); i++ ) {
            // update dependency set
            if( tDS.contains( i ) ) {
              tDS.remove( i );
              tDS.add( i - 1 );
            }
          }
         
          edge.setDepends( tDS );
        }
 
        // //TODO:The following code update outedges as well - after
        // testing is seems that this is un-necessary
        // if(node instanceof Individual){
        // Individual ind = (Individual)node;
        //         
        // //update edge depdencies
        // //update type dependencies
        // edges = ind.getInEdges();
        // for(Iterator eIt = edges.iterator(); eIt.hasNext();){
        // //get next type
        // Edge edge = (Edge)eIt.next();
        //           
        // //update branch if necessary
        // if(edge.getDepends().branch > branch.getBranch().branch)
        // edge.getDepends().branch--;
        //
        // for(int i = branch.getBranch().branch; i <=
        // kb.getABox().getBranches().size(); i++){
        // //update dependency set
        // if(edge.getDepends().contains(i)){
        // edge.getDepends().remove(i);
        // edge.getDepends().add(i-1);
        // }
        // }
        // }
        // }
      }
 
      if( PelletOptions.TRACK_BRANCH_EFFECTS )
        kb.getABox().getBranchEffectTracker().remove( branch.getBranch().getBranch() + 1 );
 
      // !!!!!!!!!!!!!!!! Next update kb.getABox() branches !!!!!!!!!!!!!!
      // remove the branch from branches
      List<Branch> branches = kb.getABox().getBranches();
 
      // decrease branch id for each branch after the branch we're
      // removing
      // also need to change the dependency set for each label
      for( int i = branch.getBranch().getBranch(); i < branches.size(); i++ ) {
        // cast for ease
        Branch br = branches.get( i );
       
        DependencySet tDS = br.getTermDepends();
       
        // update the term depends in the branch
        if( tDS.getBranch() > branch.getBranch().getBranch() )
          tDS = tDS.copy( tDS.getBranch() - 1 );
 
        for( int j = branch.getBranch().getBranch(); j < kb.getABox().getBranches().size(); j++ ) {
          if( tDS.contains( j ) ) {
            tDS.remove( j );
            tDS.add( j - 1 );
          }
        }
 
        // also need to decrement the branch number
        br.setBranch( br.getBranch() - 1 );
        br.setTermDepends( tDS );
      }
 
      // remove the actual branch
      branches.remove( branch.getBranch() );
 
      // set the branch counter
      kb.getABox().setBranch( kb.getABox().getBranch() - 1 );
    }
  }

  /**
   * Restore a clash dependency
   *
   * @param assertion
   * @param clash
   */
  private void restoreClash(ATermAppl assertion, ClashDependency clash) {
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "    Restoring clash dependency clash: " + clash.getClash() );
 
    // remove the dependency
    clash.getClash().getDepends().removeExplain( assertion );
 
    // undo clash if empty and is independent
    if( clash.getClash().getDepends().getExplain().isEmpty() && clash.getClash().getDepends().isIndependent() ) {
      if( DependencyIndex.log.isLoggable( Level.FINE ) )
        DependencyIndex.log.fine( "           Actually removing clash!" );
 
      kb.getABox().setClash( null );
    }
  }

  /**
   * Restore a disjunct, merge pairs, etc. of a branch that has been closed
   * due to a clash whose dependency set contains an assertion that has been
   * deleted
   *
   * @param assertion
   * @param branch
   */
  private void restoreCloseBranch(ATermAppl assertion, CloseBranchDependency branch) {
    // only proceed if tryNext is larger than 1!
    if( branch.getTheBranch().getTryNext() > -1 ) {
      if( DependencyIndex.log.isLoggable( Level.FINE ) )
        DependencyIndex.log.fine( "    Undoing branch remove - branch "
            + branch.getBranch() + "  -  " + branch.getInd() + "   tryNext: "
            + branch.getTryNext() );
 
      // shift try next for branch
      branch.getTheBranch().shiftTryNext( branch.getTryNext() );
    }
  }

  /**
   * Method to remove all stuctures dependent on an kb.getABox() assertion from the
   * kb.getABox(). This is used for incremental reasoning under kb.getABox() deletions.
   *
   * @param ATermAppl
   *            assertion The deleted assertion
   */
  private void restoreDependencies() {
 
    // iterate over all removed assertions
    for( ATermAppl next : kb.getDeletedAssertions() ) {
      // get the dependency entry
      DependencyEntry entry = kb.getDependencyIndex().getDependencies( next );
 
      if( entry != null ) {
        if( DependencyIndex.log.isLoggable( Level.FINE ) )
          DependencyIndex.log.fine( "Restoring dependencies for " + next );
 
        // restore the entry
        restoreDependency( next, entry );
      }
 
      // remove the entry in the index for this assertion
      kb.getDependencyIndex().removeDependencies( next );
    }
 
  }

  /**
   * Perform the actual rollback of a depenedency entry
   *
   * @param assertion
   * @param entry
   */
  private void restoreDependency(ATermAppl assertion, DependencyEntry entry) {
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "  Restoring Edge Dependencies:" );
    for( Edge next : entry.getEdges() ) {
      restoreEdge( assertion, next );
    }
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "  Restoring Type Dependencies:" );
    for( TypeDependency next : entry.getTypes() ) {
      restoreType( assertion, next );
    }
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "  Restoring Merge Dependencies: " + entry.getMerges() );
    for( MergeDependency next : entry.getMerges() ) {
      restoreMerge( assertion, next );
    }
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "  Restoring Branch Add Dependencies: "
          + entry.getBranchAdds() );
    for( BranchAddDependency next : entry.getBranchAdds() ) {
      restoreBranchAdd( assertion, next );
    }
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "  Restoring Branch Remove DS Dependencies: "
          + entry.getBranchAdds() );
    for( CloseBranchDependency next : entry.getCloseBranches() ) {
      restoreCloseBranch( assertion, next );
    }
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "  Restoring clash dependency: " + entry.getClash() );
    if( entry.getClash() != null ) {
      restoreClash( assertion, entry.getClash() );
    }
 
  }

  /**
   * Restore an edge - i.e., remove it
   *
   * @param assertion
   * @param edge
   */
  private void restoreEdge(ATermAppl assertion, Edge theEdge) {
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "    Removing edge? " + theEdge );
 
    // the edge could have previously been removed so return
    if( theEdge == null )
      return;
 
    // get the object
    Individual subj = kb.getABox().getIndividual( theEdge.getFrom().getName() );
    Node obj = kb.getABox().getNode( theEdge.getTo().getName() );
    Role role = kb.getRole( theEdge.getRole().getName() );
 
    // loop over all edges for the subject
    EdgeList edges = subj.getEdgesTo( obj, role );
    for( int i = 0; i < edges.size(); i++ ) {
      Edge edge = edges.edgeAt( i );
      if( edge.getRole().equals( role ) ) {
        // get dependency set for the edge
        DependencySet ds = edge.getDepends();
 
        // clean it
        ds.removeExplain( assertion );
 
        // remove if the dependency set is empty
        if( ds.getExplain().isEmpty() ) {
          final IncrementalChangeTracker tracker = kb.getABox().getIncrementalChangeTracker();
          // need to check if the
 
          subj.removeEdge( edge );
          obj.removeInEdge( edge );
 
          // update the removed set of edges
          tracker.addDeletedEdge( edge );
 
          // add to updated individuals
          tracker.addUpdatedIndividual( subj );
 
          // TODO: Do we need to add literals?
          if( obj instanceof Individual )
            tracker.addUpdatedIndividual( (Individual) obj );
 
          if( DependencyIndex.log.isLoggable( Level.FINE ) )
            DependencyIndex.log.fine( "           Actually removed edge!" );
        }
        break;
      }
    }
  }

  /**
   * Restore a merge dependency
   *
   * @param assertion
   * @param merge
   */
  private void restoreMerge(ATermAppl assertion, MergeDependency merge) {
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) )
      DependencyIndex.log.fine( "    Removing merge? " + merge.getInd() + " merged to "
          + merge.getmergedIntoInd() );
 
    // get merge dependency
    DependencySet ds = kb.getABox().getNode( merge.getInd() ).getMergeDependency( false );
 
    // remove the dependency
    ds.removeExplain( assertion );
 
    // undo merge if empty
    if( ds.getExplain().isEmpty() ) {
      if( DependencyIndex.log.isLoggable( Level.FINE ) )
        DependencyIndex.log.fine( "           Actually removing merge!" );
 
      // get nodes
      Node ind = kb.getABox().getNode( merge.getInd() );
      Node mergedToInd = kb.getABox().getNode( merge.getmergedIntoInd() );
 
      // check that they are actually the same - else throw error
      if( !ind.isSame( mergedToInd ) )
        throw new InternalReasonerException( " Restore merge error: " + ind
            + " not same as " + mergedToInd );
 
      if( !ind.isPruned() )
        throw new InternalReasonerException( " Restore merge error: " + ind + " not pruned" );
 
      // unprune to prune branch
      ind.unprune( ind.getPruned().getBranch() );
 
      // undo set same
      ind.undoSetSame();
 
      // add to updated
      // Note that ind.unprune may add edges, however we do not need to
      // add them to the updated individuals as
      // they will be added when the edge is removed from the node which
      // this individual was merged to
      // add to updated
      final IncrementalChangeTracker tracker = kb.getABox().getIncrementalChangeTracker();
 
      // because this node was pruned, we must guarantee that all of
      // its lables have been fired
      tracker.addUnprunedNode( ind );
 
      if( ind instanceof Individual ) {
        tracker.addUpdatedIndividual( (Individual) ind );
      }
 
      if( mergedToInd instanceof Individual ) {
        tracker.addUpdatedIndividual( (Individual) mergedToInd );
      }
    }
  }

  /**
   * Restore a type dependency
   *
   * @param assertion
   * @param type
   */
  private void restoreType(ATermAppl assertion, TypeDependency type) {
 
    final Node node = kb.getABox().getNode( type.getInd() );
    final ATermAppl desc = type.getType();
 
    if( DependencyIndex.log.isLoggable( Level.FINE ) ) {
      if( node instanceof Individual )
        DependencyIndex.log.fine( "    Removing type? " + desc + " from "
            + ((Individual) node).debugString() );
      else
        DependencyIndex.log.fine( "    Removing type? " + desc + " from " + node );
    }
 
    // get the dependency set - Note: we must normalize the concept
    DependencySet ds = node.getDepends( ATermUtils.normalize( desc ) );
 
    // return if null - this can happen as currently I have dupilicates in
    // the index
    if( ds == null || desc == ATermUtils.TOP )
      return;
 
    // clean it
    ds.removeExplain( assertion );
 
    // remove if the explanation set is empty
    if( ds.getExplain().isEmpty() ) {
      final IncrementalChangeTracker tracker = kb.getABox().getIncrementalChangeTracker();
 
      kb.getABox().removeType( node.getName(), desc );
 
      // update the set of removed types
      tracker.addDeletedType( node, type.getType() );
 
      // add to updated individuals
      if( node instanceof Individual ) {
        Individual ind = (Individual) node;
        tracker.addUpdatedIndividual( ind );
 
        // also need to add all edge object to updated individuals -
        // this is needed to fire allValues/domain/range rules etc.
        for( Edge e : ind.getInEdges() ) {
          tracker.addUpdatedIndividual( e.getFrom() );
        }
        for( Edge e : ind.getOutEdges() ) {
          if( e.getTo() instanceof Individual )
            tracker.addUpdatedIndividual( (Individual) e.getTo() );
        }
      }
 
      if( DependencyIndex.log.isLoggable( Level.FINE ) )
        DependencyIndex.log.fine( "           Actually removed type!" );
    }
  }

}
TOP

Related Classes of org.mindswap.pellet.tableau.completion.incremental.IncrementalRestore

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.