Package org.mindswap.pellet.tableau.cache

Source Code of org.mindswap.pellet.tableau.cache.AbstractConceptCache

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

import static com.clarkparsia.pellet.utils.TermFactory.TOP;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

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.Role;
import org.mindswap.pellet.exceptions.InternalReasonerException;
import org.mindswap.pellet.tbox.impl.Unfolding;
import org.mindswap.pellet.utils.ATermUtils;
import org.mindswap.pellet.utils.Bool;
import org.mindswap.pellet.utils.MultiValueMap;
import org.mindswap.pellet.utils.SetUtils;
import org.mindswap.pellet.utils.fsm.Transition;
import org.mindswap.pellet.utils.fsm.TransitionGraph;

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

/**
* <p>
* Title:
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2007
* </p>
* <p>
* Company: Clark & Parsia, LLC. <http://www.clarkparsia.com>
* </p>
*
* @author Evren Sirin
*/
public abstract class AbstractConceptCache implements ConceptCache {
  public final static Logger  log  = Logger.getLogger( AbstractConceptCache.class.getName() );
 
  private int  maxSize;

  /**
   * Creates an empty cache with at most <code>maxSize</code> elements which
   * are neither named or negations of names.
   *
   * @param maxSize
   */
  public AbstractConceptCache(int maxSize) {
    this.maxSize = maxSize;
  }
 
  protected boolean isFull() {
    return size() == maxSize;
  }

  public Bool getSat(ATermAppl c) {
    CachedNode cached = get( c );
    return cached == null
      ? Bool.UNKNOWN
      : Bool.create( !cached.isBottom() );
  }

  public boolean putSat(ATermAppl c, boolean isSatisfiable) {
    CachedNode cached = get( c );
    if( cached != null ) {
      if( isSatisfiable != !cached.isBottom() )
        throw new InternalReasonerException( "Caching inconsistent results for " + c );
      return false;
    }
    else if( isSatisfiable ) {
      put( c, CachedNodeFactory.createSatisfiableNode() );
    }
    else {
      ATermAppl notC = ATermUtils.negate( c );

      put( c, CachedNodeFactory.createBottomNode() );
      put( notC, CachedNodeFactory.createTopNode() );

    }

    return true;
  }

  public int getMaxSize() {
    return maxSize;
  }

  public void setMaxSize(int maxSize) {
    this.maxSize = maxSize;
  }
 

  private Bool checkTrivialClash(CachedNode node1, CachedNode node2) {
    Bool result = null;

    if( node1.isBottom() || node2.isBottom() ) {
      result = Bool.TRUE;
    }
    else if( node1.isTop() || node2.isTop() ) {
      result = Bool.FALSE;
    }
    else if( !node1.isComplete() || !node2.isComplete() ) {
      result = Bool.UNKNOWN;
    }

    return result;
  }

  public Bool isMergable(KnowledgeBase kb, CachedNode root1, CachedNode root2) {
    Bool result = checkTrivialClash( root1, root2 );
    if( result != null )
      return result.not();

    CachedNode roots[] = new CachedNode[] { root1, root2 };
    boolean isIndependent = root1.isIndependent() && root2.isIndependent();
   
    int root = roots[0].getDepends().size() < roots[1].getDepends().size()
      ? 0
      : 1;
    int otherRoot = 1 - root;
    for( Entry<ATermAppl, DependencySet> entry : roots[root].getDepends().entrySet() ) {
      ATermAppl c = entry.getKey();
      ATermAppl notC = ATermUtils.negate( c );

      DependencySet ds2 = roots[otherRoot].getDepends().get( notC );
      if( ds2 != null ) {
        DependencySet ds1 = entry.getValue();
        boolean allIndependent = isIndependent && ds1.isIndependent() && ds2.isIndependent();
        if( allIndependent ) {
          if( log.isLoggable( Level.FINE ) )
            log.fine( roots[root] + " has " + c + " " + roots[otherRoot]
                + " has negation " + ds1.max() + " " + ds2.max() );
          return Bool.FALSE;
        }
        else {
          if( log.isLoggable( Level.FINE ) )
            log.fine( roots[root] + " has " + c + " " + roots[otherRoot]
                + " has negation " + ds1.max() + " " + ds2.max() );
          result = Bool.UNKNOWN;
        }
      }
    }

    // if there is a suspicion there is no way to fix it later so return now
    if( result != null )
      return result;

    for( root = 0; root < 2; root++ ) {
      otherRoot = 1 - root;

      for( ATermAppl c : roots[root].getDepends().keySet() ) {
        if( ATermUtils.isPrimitive( c ) ) {
          result = checkBinaryClash( kb, c, roots[root], roots[otherRoot] );
        }
        else if( ATermUtils.isAllValues( c ) ) {
          result = checkAllValuesClash( kb, c, roots[root], roots[otherRoot] );
        }
        else if( ATermUtils.isNot( c ) ) {
          ATermAppl arg = (ATermAppl) c.getArgument( 0 );
          if( ATermUtils.isMin( arg ) ) {       
            result = checkMaxClash( kb, c, roots[root], roots[otherRoot] );
          }
          else if( ATermUtils.isSelf( arg ) ) {
            result = checkSelfClash( kb, arg, roots[root], roots[otherRoot] );
          }
        }

        if( result != null )
          return result;
      }
    }
   
    boolean bothNamedIndividuals = (root1 instanceof Individual && root2 instanceof Individual);

    if( kb.getExpressivity().hasFunctionality() || kb.getExpressivity().hasFunctionalityD() ) {
      root = (roots[0].getOutEdges().size() + roots[0].getInEdges().size()) < (roots[1]
          .getOutEdges().size() + roots[1].getInEdges().size())
        ? 0
        : 1;
      otherRoot = 1 - root;

      if( bothNamedIndividuals )
        result = checkFunctionalityClashWithDifferents( (Individual) roots[root],
            (Individual) roots[otherRoot] );
      else
        result = checkFunctionalityClash( roots[root], roots[otherRoot] );
      if( result != null )
        return result;
    }

    if( bothNamedIndividuals ) {
      Individual ind1 = (Individual) root1;
      Individual ind2 = (Individual) root2;
      DependencySet ds = ind1.getDifferenceDependency( ind2 );
      if( ds != null ) {
        return ds.isIndependent()
          ? Bool.FALSE
          : Bool.UNKNOWN;
      }
     
      for (Edge edge : ind1.getOutEdges()) {
        if (edge.getRole().isIrreflexive() && edge.getTo().equals(ind2)) {
          return edge.getDepends().isIndependent()
            ? Bool.FALSE
            : Bool.UNKNOWN;
        }
      }
     
      for (Edge edge : ind1.getInEdges()) {
        if (edge.getRole().isIrreflexive() && edge.getFrom().equals(ind2)) {
          return edge.getDepends().isIndependent()
            ? Bool.FALSE
            : Bool.UNKNOWN;
        }
      }
    }
   
    if( kb.getExpressivity().hasDisjointRoles() ) {
      Bool clash = checkDisjointPropertyClash( root1, root2 );
      if (clash != null ) {
        if( log.isLoggable( Level.FINE ) )
          log.fine( "Cannot determine if two named individuals can be merged or not: " + roots[0] + "  + roots[1]" );
        return Bool.UNKNOWN;   
      }
    }

    // if there is no obvious clash then c1 & not(c2) is satisfiable
    // therefore c1 is NOT a subclass of c2.
    return Bool.TRUE;
  }
 
  private Bool checkBinaryClash(KnowledgeBase kb, ATermAppl c, CachedNode root, CachedNode otherRoot) {
        Iterator<Unfolding> unfoldingList = kb.getTBox().unfold( c );

        while( unfoldingList.hasNext() ) {
      Unfolding unfolding = unfoldingList.next();
          ATermAppl unfoldingCondition = unfolding.getCondition();
         
          if( !unfoldingCondition.equals( TOP )
            && otherRoot.getDepends().containsKey( unfoldingCondition ) ) {
            return Bool.UNKNOWN;
          }
        }
       
        return null;
  }

  private Bool checkAllValuesClash(KnowledgeBase kb, ATermAppl av, CachedNode root,
      CachedNode otherRoot) {
    ATerm r = av.getArgument( 0 );
    if( r.getType() == ATerm.LIST )
      r = ((ATermList) r).getFirst();
    Role role = kb.getRole( r );

    if( !role.hasComplexSubRole() ) {
      if( otherRoot.hasRNeighbor( role ) ) {
        if( log.isLoggable( Level.FINE ) )
          log
              .fine( root + " has " + av + " " + otherRoot + " has " + role
                  + " neighbor" );

        return Bool.UNKNOWN;
      }
    }
    else {
      TransitionGraph<Role> tg = role.getFSM();
      for( Transition<Role> t : tg.getInitialState().getTransitions() ) {
        if( otherRoot.hasRNeighbor( t.getName() ) ) {
          if( log.isLoggable( Level.FINE ) )
            log.fine( root + " has " + av + " " + otherRoot + " has " + t.getName()
                + " neighbor" );

          return Bool.UNKNOWN;
        }
      }
    }

    return null;
  }

  private Bool checkMaxClash(KnowledgeBase kb, ATermAppl mc, CachedNode root, CachedNode otherRoot) {
    ATermAppl maxCard = (ATermAppl) mc.getArgument( 0 );

    Role maxR = kb.getRole( maxCard.getArgument( 0 ) );
    int max = ((ATermInt) maxCard.getArgument( 1 )).getInt() - 1;

    int n1 = getRNeighbors( root, maxR ).size();
    int n2 = getRNeighbors( otherRoot, maxR ).size();

    if( n1 + n2 > max ) {
      if( log.isLoggable( Level.FINE ) )
        log.fine( root + " has " + mc + " " + otherRoot + " has R-neighbor" );
      return Bool.UNKNOWN;
    }

    return null;
  }

  private Bool checkSelfClash(KnowledgeBase kb, ATermAppl self, CachedNode root, CachedNode otherRoot) {
    Role r = kb.getRole( self.getArgument( 0 ) );
   
    for( Edge e : otherRoot.getOutEdges() ) {
      if( e.getRole().isSubRoleOf( r ) && e.getToName().equals( otherRoot.getName() ) ) {
        if( log.isLoggable( Level.FINE ) )
          log.fine( root + " has not(" + self + ") " + otherRoot + " has self edge" );
        boolean allIndependent = root.isIndependent()
          && otherRoot.isIndependent()
          && e.getDepends().isIndependent();
        return allIndependent ? Bool.FALSE : Bool.UNKNOWN;
      }
    }

    return null;
  }
 
  private Bool checkFunctionalityClash(CachedNode root, CachedNode otherRoot) {
    Set<Role> checked = new HashSet<Role>();
    for( Edge edge : root.getOutEdges() ) {
      Role role = edge.getRole();

      if( !role.isFunctional() )
        continue;

      Set<Role> functionalSupers = role.getFunctionalSupers();
      for( Iterator<Role> j = functionalSupers.iterator(); j.hasNext(); ) {
        Role supRole = j.next();

        if( checked.contains( supRole ) )
          continue;

        checked.add( supRole );

        if( otherRoot.hasRNeighbor( supRole ) ) {
          if( log.isLoggable( Level.FINE ) )
            log.fine( root + " and " + otherRoot + " has " + supRole );
          return Bool.UNKNOWN;
        }
      }
    }

    for( Edge edge : root.getInEdges() ) {
      Role role = edge.getRole().getInverse();

      if( role == null || !role.isFunctional() )
        continue;

      Set<Role> functionalSupers = role.getFunctionalSupers();
      for( Iterator<Role> j = functionalSupers.iterator(); j.hasNext(); ) {
        Role supRole = j.next();

        if( checked.contains( supRole ) )
          continue;

        checked.add( supRole );

        if( otherRoot.hasRNeighbor( supRole ) ) {
          if( log.isLoggable( Level.FINE ) )
            log.fine( root + " and " + otherRoot + " has " + supRole );
          return Bool.UNKNOWN;
        }
      }
    }

    return null;
  }
 
  private Bool checkFunctionalityClashWithDifferents(Individual root, Individual otherRoot) {
    Bool result = null;
    for( Edge edge : root.getOutEdges() ) {
      Role role = edge.getRole();

      if( !role.isFunctional() )
        continue;

      Set<Role> functionalSupers = role.getFunctionalSupers();
      for( Iterator<Role> j = functionalSupers.iterator(); j.hasNext(); ) {
        Role supRole = j.next();

        EdgeList otherEdges = otherRoot.getRNeighborEdges( supRole );
        for( Edge otherEdge : otherEdges ) {
          DependencySet ds = edge.getTo().getDifferenceDependency( otherEdge.getNeighbor( otherRoot ) );
          if( log.isLoggable( Level.FINE ) )
            log.fine( root + " and " + otherRoot + " has " + supRole + " " + edge + " " + otherEdge );
          if( ds != null && ds.isIndependent() )
            return Bool.FALSE;
          result = Bool.UNKNOWN;
        }
      }
    }

    for( Edge edge : root.getInEdges() ) {
      Role role = edge.getRole().getInverse();

      if( role == null || !role.isFunctional() )
        continue;

      Set<Role> functionalSupers = role.getFunctionalSupers();
      for( Iterator<Role> j = functionalSupers.iterator(); j.hasNext(); ) {
        Role supRole = j.next();

        EdgeList otherEdges = otherRoot.getRNeighborEdges( supRole );
        for( Edge otherEdge : otherEdges ) {
          DependencySet ds = edge.getTo().getDifferenceDependency( otherEdge.getNeighbor( otherRoot ) );
          if( log.isLoggable( Level.FINE ) )
            log.fine( root + " and " + otherRoot + " has " + supRole + " " + edge + " " + otherEdge );
          if( ds != null && ds.isIndependent() )
            return Bool.FALSE;
          result = Bool.UNKNOWN;
        }
      }
    }

    return result;
  }
 
  private MultiValueMap<ATermAppl, Role> collectNeighbors(CachedNode ind) {
    MultiValueMap<ATermAppl, Role> neighbors = new MultiValueMap<ATermAppl, Role>();
    for( Edge edge : ind.getInEdges() ) {
      Role role = edge.getRole();
      ATermAppl neighbor = edge.getFromName();

      if( !ATermUtils.isBnode( neighbor ) )
        neighbors.putSingle( neighbor, role );
    }
   
    for( Edge edge : ind.getOutEdges() ) {
      Role role = edge.getRole();
      ATermAppl neighbor = edge.getToName();
      if( role.isObjectRole() && !ATermUtils.isBnode( neighbor ) )
        neighbors.putSingle( neighbor, role.getInverse() );
    }
    return neighbors;
  }
   
 
  private boolean checkDisjointProperties(Set<Role> roles1, Set<Role> roles2) {
    Set<Role> allDisjoints = new HashSet<Role>();
    for( Role role : roles1 ) {
      allDisjoints.addAll( role.getDisjointRoles() );
    }
    return SetUtils.intersects( allDisjoints, roles2 );
  }
 
  private Bool checkDisjointPropertyClash(CachedNode root1, CachedNode root2) {
    MultiValueMap<ATermAppl, Role> neighbors1 = collectNeighbors( root1 );
    if( neighbors1.isEmpty() )
      return null;

    MultiValueMap<ATermAppl, Role> neighbors2 = collectNeighbors( root2 );
    if( neighbors2.isEmpty() )
      return null;

    for( Entry<ATermAppl, Set<Role>> e : neighbors1.entrySet() ) {
      ATermAppl commonNeighbor = e.getKey();
      Set<Role> roles1 = e.getValue();
      Set<Role> roles2 = neighbors2.get( commonNeighbor );

      if( roles2 == null )
        continue;

      if( checkDisjointProperties( roles1, roles2 ) )
        return Bool.UNKNOWN;
    }

    return null;
  }

  public Bool checkNominalEdges(KnowledgeBase kb, CachedNode pNode, CachedNode cNode) {
    Bool result = Bool.UNKNOWN;

    if( pNode.isComplete() && cNode.isComplete() && cNode.isIndependent() ) {
      result = checkNominalEdges( kb, pNode, cNode, false );
      if( result.isUnknown() )
        result = checkNominalEdges( kb, pNode, cNode, true );
    }

    return result;
  }

  private Bool checkNominalEdges(KnowledgeBase kb, CachedNode pNode, CachedNode cNode,
      boolean checkInverses) {
    EdgeList edges = checkInverses
      ? cNode.getInEdges()
      : cNode.getOutEdges();
    for( Edge edge : edges ) {
      Role role = checkInverses
        ? edge.getRole().getInverse()
        : edge.getRole();
      DependencySet ds = edge.getDepends();

      if( !ds.isIndependent() )
        continue;

      boolean found = false;
      ATermAppl val = checkInverses
        ? edge.getFromName()
        : edge.getToName();

      if( !role.isObjectRole() ) {
        found = pNode.hasRNeighbor( role );
      }
      else if( !isRootNominal( kb, val ) ) {
        if( !role.hasComplexSubRole() )
          found = pNode.hasRNeighbor( role );
        else {
          TransitionGraph<Role> tg = role.getFSM();
          Iterator<Transition<Role>> it = tg.getInitialState().getTransitions().iterator();
          while( !found && it.hasNext() ) {
            Transition<Role> tr = it.next();
            found = pNode.hasRNeighbor( tr.getName() );
          }
        }
      }
      else {
        Set<ATermAppl> neighbors = null;

        if( role.isSimple() || !(pNode instanceof Individual) )
          neighbors = getRNeighbors( pNode, role );
        else {
          neighbors = new HashSet<ATermAppl>();
          kb.getABox().getObjectPropertyValues( pNode.getName(), role, neighbors,
              neighbors, false );
        }
       
        Individual ind = kb.getABox().getIndividual( val ).getSame();
        Set<ATermAppl> samesAndMaybes = new HashSet<ATermAppl>();
        kb.getABox().getSames( ind, samesAndMaybes, samesAndMaybes );
       
        found = SetUtils.intersects( samesAndMaybes, neighbors );
      }

      if( !found ) {
        return Bool.FALSE;
      }

    }

    return Bool.UNKNOWN;
  }

  /**
   * @param val
   * @return
   */
  private boolean isRootNominal(KnowledgeBase kb, ATermAppl val) {
    Individual ind = kb.getABox().getIndividual( val );
   
    return ind != null && ind.isRootNominal();
  }
 


  /**
   * {@inheritDoc}
   */
  private Set<ATermAppl> getRNeighbors(CachedNode node, Role role) {
    Set<ATermAppl> neighbors = new HashSet<ATermAppl>();

    for( Edge edge : node.getOutEdges() ) {
      Role r = edge.getRole();
      if( r.isSubRoleOf( role ) ) {
        neighbors.add( edge.getToName() );
      }
    }

    if( role.isObjectRole() ) {
      role = role.getInverse();
      for( Edge edge : node.getInEdges() ) {
        Role r = edge.getRole();
        if( r.isSubRoleOf( role ) ) {
          neighbors.add( edge.getFromName() );
        }
      }
    }

    return neighbors;
  }
}
TOP

Related Classes of org.mindswap.pellet.tableau.cache.AbstractConceptCache

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.