Package com.clarkparsia.pellet.rules

Source Code of com.clarkparsia.pellet.rules.ContinuousRulesStrategy

// 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 com.clarkparsia.pellet.rules;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;

import org.mindswap.pellet.ABox;
import org.mindswap.pellet.Clash;
import org.mindswap.pellet.DependencySet;
import org.mindswap.pellet.Edge;
import org.mindswap.pellet.Individual;
import org.mindswap.pellet.IndividualIterator;
import org.mindswap.pellet.Node;
import org.mindswap.pellet.PelletOptions;
import org.mindswap.pellet.Role;
import org.mindswap.pellet.tableau.branch.Branch;
import org.mindswap.pellet.tableau.branch.RuleBranch;
import org.mindswap.pellet.tableau.completion.SROIQStrategy;
import org.mindswap.pellet.tableau.completion.rule.TableauRule;
import org.mindswap.pellet.utils.Pair;
import org.mindswap.pellet.utils.Timer;

import aterm.ATermAppl;

import com.clarkparsia.pellet.expressivity.Expressivity;
import com.clarkparsia.pellet.rules.model.Rule;
import com.clarkparsia.pellet.rules.model.RuleAtom;
import com.clarkparsia.pellet.rules.rete.AlphaNetwork;
import com.clarkparsia.pellet.rules.rete.Compiler;
import com.clarkparsia.pellet.rules.rete.Interpreter;

public class ContinuousRulesStrategy extends SROIQStrategy {
  private BindingGeneratorStrategy          bindingStrategy;
  private Interpreter                  interpreter;
  private boolean                    merging;
  private Set<PartialBinding>              unsafeRules;
  private Set<PartialBinding>              partialBindings;
  private Map<Pair<Rule, VariableBinding>, Integer>  rulesApplied;
  private RulesToATermTranslator            atermTranslator;
  private RuleAtomAsserter              ruleAtomAsserter;
  private TrivialSatisfactionHelpers          atomTester;

  public ContinuousRulesStrategy(ABox abox) {
    super( abox );
    bindingStrategy = new BindingGeneratorStrategyImpl( abox );
    partialBindings = new HashSet<PartialBinding>();
    unsafeRules = new HashSet<PartialBinding>();
    rulesApplied = new HashMap<Pair<Rule, VariableBinding>, Integer>();
    atermTranslator = new RulesToATermTranslator();
    ruleAtomAsserter = new RuleAtomAsserter();
    atomTester = new TrivialSatisfactionHelpers( abox );
  }
 
  public void addUnsafeRule(Rule rule, Set<ATermAppl> explain) {
    unsafeRules.add(new PartialBinding(rule, new VariableBinding(abox), new DependencySet(explain)));
  }
 
  public void addPartialBinding(PartialBinding binding) {
      partialBindings.add(binding);
    }

  @Override
  public Edge addEdge(Individual subj, Role pred, Node obj, DependencySet ds) {
    Edge edge = super.addEdge( subj, pred, obj, ds );

    if( edge != null && !abox.isClosed() && subj.isRootNominal() && obj.isRootNominal() ) {
      if( interpreter != null ) {
        interpreter.alphaNet.activateEdge(edge);
      }
    }
   
    return edge;
  }

  @Override
  public void addType(Node node, ATermAppl c, DependencySet ds) {
    super.addType( node, c, ds );

    if( !merging && !abox.isClosed() && node.isRootNominal() && interpreter != null && node.isIndividual() ) {
      Individual ind = (Individual) node;
      interpreter.alphaNet.activateType(ind, c, ds);
    }
  }
 
  @Override
  protected boolean mergeIndividuals(Individual y, Individual x, DependencySet ds) {
      if (super.mergeIndividuals(y, x, ds)) {
        if (interpreter != null) {
          interpreter.alphaNet.activateDifferents(y);
        }
        return true;
      }
      return false;
  }

  @Override
  public boolean setDifferent(Node y, Node z, DependencySet ds) {
      if (super.setDifferent(y, z, ds)) {
      if( interpreter != null && !merging && !abox.isClosed() && y.isRootNominal() && y.isIndividual() && z.isRootNominal() && z.isIndividual()) {
        interpreter.alphaNet.activateDifferent((Individual) y, (Individual) z, ds);
      }
     
        return true;
      }
     
      return false;
  }

  public Collection<PartialBinding> applyRete() {
    Timer t;
    if( PelletOptions.ALWAYS_REBUILD_RETE ) {
      t = timers.startTimer( "rule-rebuildRete" );

      partialBindings.clear();
      partialBindings.addAll(unsafeRules);
      interpreter.reset();
      t.stop();
    }

    t = timers.startTimer( "rule-reteRun" );
    interpreter.run();
    t.stop();
   
    return interpreter.getBindings();
  }
 
 

  public void applyRuleBindings() {

    int total = 0;

    for( PartialBinding ruleBinding : partialBindings ) {
      Rule rule = ruleBinding.getRule();
      VariableBinding initial = ruleBinding.getBinding();

      for( VariableBinding binding : bindingStrategy.createGenerator( rule, initial ) ) {

        Pair<Rule, VariableBinding> ruleKey = new Pair<Rule, VariableBinding>( rule,
            binding );
        if( !rulesApplied.containsKey( ruleKey ) ) {
          total++;

          if( log.isLoggable( Level.FINE ) ) {
            log.fine( "Rule: " + rule );
            log.fine( "Binding: " + binding );
            log.fine( "total:" + total );
          }
         
          int branch = createDisjunctionsFromBinding( binding, rule, ruleBinding
              .getDependencySet() );
         
          if( branch >= 0 ) {
            rulesApplied.put( ruleKey, branch );
          }
         
          if( abox.isClosed() ) {
            return;
          }
        }
      }

    }
  }

  public void complete(Expressivity expr) {
    Timer t;

    Expressivity expressivity = abox.getKB().getExpressivity();

    initialize( expressivity );

    merging = false;
    t = timers.startTimer( "rule-buildReteRules" );
    Compiler compiler = new Compiler(this);
    for (Entry<Rule, Rule> e : abox.getKB().getNormalizedRules().entrySet()) {
      Rule rule = e.getKey();
      Rule normalizedRule = e.getValue();

      if (normalizedRule == null)
        continue;

      Set<ATermAppl> explain = abox.doExplanation() ? rule.getExplanation(atermTranslator) : Collections
                      .<ATermAppl> emptySet();

      try {
              compiler.compile(normalizedRule, explain);
            }
            catch (UnsupportedOperationException uoe) {
              throw new RuntimeException("Unsupported rule " + normalizedRule, uoe);
            }
    }
    t.stop();
   
    AlphaNetwork alphaNet = compiler.getAlphaNet();
    if (abox.doExplanation()) {
      alphaNet.setDoExplanation(true);
    }
    interpreter = new Interpreter(alphaNet);
    partialBindings.clear();
    partialBindings.addAll(unsafeRules);
    rulesApplied.clear();


//    t.stop();   

//    t = timers.startTimer( "rule-compileReteFacts" );
    applyRete();
//    t.stop();

    while( !abox.isComplete() ) {
      while( abox.isChanged() && !abox.isClosed() ) {
        completionTimer.check();

        abox.setChanged( false );

        if( log.isLoggable( Level.FINE ) ) {
          log.fine( "Branch: " + abox.getBranch() + ", Depth: " + abox.stats.treeDepth
              + ", Size: " + abox.getNodes().size() + ", Mem: "
              + (Runtime.getRuntime().freeMemory() / 1000) + "kb" );
          abox.validate();
          // printBlocked();
          abox.printTree();
          interpreter.alphaNet.print();
        }

        IndividualIterator i = abox.getIndIterator();

        for( TableauRule tableauRule : tableauRules ) {
          tableauRule.apply( i );
          if( abox.isClosed() )
            break;
        }
       
        if( abox.isClosed() )
          break;

        if (!abox.isChanged() && !partialBindings.isEmpty()) {
//          t = timers.startTimer( "rule-bindings" );
          applyRuleBindings();
//          t.stop();
          if( abox.isClosed() )
            break;
        }

      }

      if( abox.isClosed() ) {
        if( log.isLoggable( Level.FINE ) )
          log.fine( "Clash at Branch (" + abox.getBranch() + ") " + abox.getClash() );

        if( backtrack() )
          abox.setClash( null );
        else
          abox.setComplete( true );
      }
      else {
        if( PelletOptions.SATURATE_TABLEAU ) {
          Branch unexploredBranch = null;
          for( int i = abox.getBranches().size() - 1; i >= 0; i-- ) {
            unexploredBranch = abox.getBranches().get( i );
            unexploredBranch.setTryNext( unexploredBranch.getTryNext() + 1 );
            if( unexploredBranch.getTryNext() < unexploredBranch.getTryCount() ) {
              restore( unexploredBranch );
              System.out.println( "restoring branch " + unexploredBranch.getBranch()
                  + " tryNext = " + unexploredBranch.getTryNext()
                  + " tryCount = " + unexploredBranch.getTryCount() );
              unexploredBranch.tryNext();
              break;
            }
            else {
              System.out.println( "removing branch " + unexploredBranch.getBranch() );
              abox.getBranches().remove( i );
              unexploredBranch = null;
            }
          }
          if( unexploredBranch == null ) {
            abox.setComplete( true );
          }
        }
        else
          abox.setComplete( true );
      }
    }
  }

  private int createDisjunctionsFromBinding(VariableBinding binding, Rule rule, DependencySet ds) {
    List<RuleAtom> atoms = new ArrayList<RuleAtom>();

    for( RuleAtom atom : rule.getBody() ) {
      DependencySet atomDS = atomTester.isAtomTrue( atom, binding );
      if( atomDS != null ) {
        ds = ds.union( atomDS, abox.doExplanation() );
      }
      else {
        atoms.add( atom );
      }
    }
   
    // all the atoms in the body are true
    if( atoms.isEmpty() ) {
      if( rule.getHead().isEmpty() ) {
        if( log.isLoggable( Level.FINE ) )
          log.fine( "Empty head for rule " + rule );
        abox.setClash( Clash.unexplained( null, ds ) );       
      }
      else {
        for( RuleAtom atom : rule.getHead() ) {
          ruleAtomAsserter.assertAtom( atom, binding, ds, false, abox, this );
        }
      }
      return -1;
    }
   
    int bodyAtomCount = atoms.size();

    for( RuleAtom atom : rule.getHead() ) {
      DependencySet atomDS = atomTester.isAtomTrue( atom, binding );
      if( atomDS == null ) {
        atoms.add( atom );
      }
    }
   
    // all no head atoms are added to the list they are all true (unless
    // there were no head atoms to begin with) which means there is nothing
    // to be done
    if( atoms.size() == bodyAtomCount && !rule.getHead().isEmpty() ) {
      return -1;
    }
    // if there is only one atom in the list that should be a body atom
    // (otherwise it would mean that all body atoms are true which would
    // have been caught with the if condition at the beginning) and we
    // can directly assert it without creating a disjunction
    else if( atoms.size() == 1 ) {
      ruleAtomAsserter.assertAtom( atoms.get( 0 ), binding, ds, true, abox, this );
      return -1;
    }
    else {   
      RuleBranch r = new RuleBranch( abox, this, ruleAtomAsserter, atoms, binding, bodyAtomCount, ds );
      addBranch( r );
      r.tryNext();
      return r.getBranch();
    }
  }

  @Override
  public void mergeTo(Node y, Node z, DependencySet ds) {
    merging = true;
    super.mergeTo( y, z, ds );
    if( !abox.isClosed() && (interpreter != null) && (y.isRootNominal() || z.isRootNominal()) ) {
//      if( y.isRootNominal() )
//        runRules |= interpreter.removeMentions( y.getTerm() );
//      if( z.isIndividual() )
//        runRules |= interpreter.rete.processIndividual( (Individual) z );
    }
    merging = false;
  }

  @Override
  public void restore(Branch branch) {
    super.restore( branch );
    restoreRules( branch );
  }

  @Override
  public void restoreLocal(Individual ind, Branch branch) {
    super.restoreLocal( ind, branch );
    restoreRules( branch );
  }

  private void restoreRules(Branch branch) {
    int total = 0;
    for( Iterator<Map.Entry<Pair<Rule, VariableBinding>, Integer>> ruleAppIter = rulesApplied
        .entrySet().iterator(); ruleAppIter.hasNext(); ) {
      Map.Entry<Pair<Rule, VariableBinding>, Integer> ruleBranchEntry = ruleAppIter.next();
      if( ruleBranchEntry.getValue() > branch.getBranch() ) {
        // System.out.println( "Removing " + ruleBranchEntry.getKey() );
        ruleAppIter.remove();
        total++;
      }
    }

    for( Iterator<PartialBinding> iter = partialBindings.iterator(); iter
        .hasNext(); ) {
      PartialBinding binding = iter.next();
      if( binding.getBranch() > branch.getBranch() ) {
        iter.remove();
      }
    }

    interpreter.restore( branch.getBranch() );
    // rebuildFacts = true;
  }
}
TOP

Related Classes of com.clarkparsia.pellet.rules.ContinuousRulesStrategy

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.