Package com.clarkparsia.pellet.el

Source Code of com.clarkparsia.pellet.el.JenaBasedELClassifier$FreeVariableStore

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.mindswap.pellet.taxonomy.TaxonomyBuilder;
import org.mindswap.pellet.utils.ATermUtils;
import org.mindswap.pellet.utils.MultiValueMap;

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

import com.clarkparsia.pellet.utils.CollectionUtils;
import com.hp.hpl.jena.graph.Graph;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.reasoner.InfGraph;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.reasoner.TriplePattern;
import com.hp.hpl.jena.reasoner.rulesys.Builtin;
import com.hp.hpl.jena.reasoner.rulesys.ClauseEntry;
import com.hp.hpl.jena.reasoner.rulesys.Functor;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Node_RuleVariable;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.reasoner.rulesys.builtins.NotEqual;
import com.hp.hpl.jena.sparql.graph.GraphFactory;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;

/**
* <p>
* Title:
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: Clark & Parsia, LLC. <http://www.clarkparsia.com>
* </p>
*
* @author Harris Lin
*/
public class JenaBasedELClassifier extends RuleBasedELClassifier implements TaxonomyBuilder
  private static final String PREDICATE_PREFIX = "tag:clarkparsia.com,2008:pellet:el:predicate:";
  private static final Node PRED_SUB = Node.createURI(PREDICATE_PREFIX + "subclassOf");
  private static final Builtin NOT_EQUAL = new NotEqual();
 
  private final Node TOP;
  private final Node BOTTOM;
 
  private NameStore m_Names;
  private VariableStore m_Variables;
  private Set<Rule> m_Rules;
  private Graph m_Facts;
 
  public JenaBasedELClassifier() {
    m_Names = new NameStore();
    m_Variables = new VariableStore();
    m_Rules = CollectionUtils.makeSet();
    m_Facts =  GraphFactory.createDefaultGraph();
   
    TOP = m_Names.get(ATermUtils.TOP);
    BOTTOM = m_Names.get(ATermUtils.BOTTOM);
    makeRuleAxioms();
  }
 
  protected void addClasses(Collection<ATermAppl> classes) {
    for (ATermAppl c : classes) {
      Node n = m_Names.get(c);
      m_Facts.add(Triple.create(n, PRED_SUB, n));
      m_Facts.add(Triple.create(n, PRED_SUB, TOP));
    }
  }
 
  protected MultiValueMap<ATermAppl, ATermAppl> run(Collection<ATermAppl> classes) {
    addClasses( classes );
    addClasses( m_Names.getAllAnons() );
   
    Reasoner reasoner = new GenericRuleReasoner(new ArrayList<Rule>(m_Rules));
   
    InfGraph inf = reasoner.bind( m_Facts );
    inf.prepare();
   
    MultiValueMap<ATermAppl, ATermAppl> subsumers = getSubsumptions(inf);
    for( ATermAppl c : classes ) {
      subsumers.add( ATermUtils.BOTTOM, c );     
    }
    return subsumers;
  }
 
  protected MultiValueMap<ATermAppl, ATermAppl> getSubsumptions(Graph graph) {
    MultiValueMap<ATermAppl, ATermAppl> subsumers = new MultiValueMap<ATermAppl, ATermAppl>();
    ExtendedIterator it = graph.find(Node.ANY, PRED_SUB, Node.ANY);
    while (it.hasNext()) {
      Triple tri = (Triple) it.next();
      Node sub = tri.getSubject();
      Node sup = tri.getObject();
      if (NameStore.isAnon(sub) || NameStore.isAnon(sup)) continue;
     
      subsumers.add(toATermAppl(sub), toATermAppl(sup));
    }
    it.close();
   
    return subsumers;
  }
 
  private ATermAppl toATermAppl(Node n) {
    if (TOP.hasURI(n.getURI())) {
      return ATermUtils.TOP;
    } else if (BOTTOM.hasURI(n.getURI())) {
      return ATermUtils.BOTTOM;
    } else {
      return ATermUtils.makeTermAppl(n.getURI());
    }
  }
 
  /**
   * {@inheritDoc}
   */
  protected void addSubclassRule(ATermAppl sub, ATermAppl sup) {
    addSubclassRule(sub, sup, new FreeVariableStore());
  }
 
  /**
   * {@inheritDoc}
   */
  protected void addRoleDomainRule(ATermAppl p, ATermAppl domain) {
    List<ClauseEntry> body = CollectionUtils.makeList();
    List<ClauseEntry> head = CollectionUtils.makeList();
   
    FreeVariableStore freeVar = new FreeVariableStore();
    Node var0 = freeVar.next();
    Node var1 = freeVar.next();
    body.add(makeSubOfSomeTriple(var0, p, var1));
    translateSuper(head, domain, freeVar, var0);
   
    m_Rules.add(new Rule(head, body));
  }

  /**
   * {@inheritDoc}
   */
  protected void addRoleRangeRule(ATermAppl p, ATermAppl range) {
    List<ClauseEntry> body = CollectionUtils.makeList();
    List<ClauseEntry> head = CollectionUtils.makeList();
   
    FreeVariableStore freeVar = new FreeVariableStore();
    Node var0 = freeVar.next();
    Node var1 = freeVar.next();
    body.add(makeSubOfSomeTriple(var0, p, var1));
    ATermAppl someOfRange = ATermUtils.makeSomeValues(p, range);
    translateSuper(head, someOfRange, freeVar, var0);
   
    m_Rules.add(new Rule(head, body));
  }

  /**
   * {@inheritDoc}
   */
  protected void addRoleChainRule(ATerm[] chain, ATermAppl sup) {
    if (chain.length < 1) return;
   
    List<ClauseEntry> body = CollectionUtils.makeList();
   
    FreeVariableStore freeVar = new FreeVariableStore();
    Node var[] = new Node[chain.length + 1];
    var[0] = freeVar.next();
    for (int i = 0; i < chain.length; i++) {
      var[i + 1] = freeVar.next();
      body.add(makeSubOfSomeTriple(var[i], (ATermAppl) chain[i], var[i + 1]));
    }
   
    ClauseEntry head = makeSubOfSomeTriple(var[0], sup, var[var.length - 1]);
   
    m_Rules.add(new Rule(Collections.singletonList(head), body));
  }

  /**
   * {@inheritDoc}
   */
  protected void addRoleHierarchyRule(ATermAppl sub, ATermAppl sup) {
    addRoleChainRule(new ATerm[] {sub}, sup);
  }

 
  private void makeRuleAxioms() {
    makeBottomAxiom();
  }

  private void makeBottomAxiom() {
    FreeVariableStore freeVar = new FreeVariableStore();
    Node var0 = freeVar.next();
    Node var1 = freeVar.next();
    Node var2 = freeVar.next();
    List<ClauseEntry> body = CollectionUtils.makeList();
    body.add(makeSubOfSomeTriple(var0, var1, var2));
    body.add(makePropertyAssertionFunctor(var1));
    body.add(makeSubclassTriple(var2, BOTTOM));
    ClauseEntry head = makeSubclassTriple(var0, BOTTOM);
   
    m_Rules.add(new Rule(Collections.singletonList(head), body));
  }

  private void addSubclassRule(ATermAppl sub, ATermAppl sup, FreeVariableStore freeVar) {
    List<ClauseEntry> body = CollectionUtils.makeList();
    List<ClauseEntry> head = CollectionUtils.makeList();
   
    Node var = freeVar.next();
    translateSub(body, sub, freeVar, var);
    translateSuper(head, sup, freeVar, var);
    m_Rules.add(new Rule(head, body));
  }

  private void translateSub(List<ClauseEntry> outBody, ATermAppl sub, FreeVariableStore freeVar, Node currentVar) {
    AFun fun = sub.getAFun();
    if (ATermUtils.isPrimitive(sub) || ATermUtils.isBottom(sub)) {
      outBody.add(makeSubclassTriple(currentVar, m_Names.get(sub)));
    } else if (fun.equals( ATermUtils.ANDFUN )) {
      ATermList list = (ATermList) sub.getArgument(0);
     
      while( !list.isEmpty() ) {
        ATermAppl conj = (ATermAppl) list.getFirst();
        translateSub(outBody, conj, freeVar, currentVar);
        list = list.getNext();
      }
    } else if (fun.equals( ATermUtils.SOMEFUN )) {
      ATermAppl prop = (ATermAppl) sub.getArgument(0);
      ATermAppl q = (ATermAppl) sub.getArgument(1);
      Node nextVar = freeVar.next();
      outBody.add(makeSubOfSomeTriple(currentVar, prop, nextVar));
      translateSub(outBody, q, freeVar, nextVar);
    } else {
      assert false;
    }
  }
 
  private void translateSuper(List<ClauseEntry> outHead, ATermAppl sup, FreeVariableStore freeVar, Node currentVar) {
    AFun fun = sup.getAFun();
    if (ATermUtils.isPrimitive(sup) || ATermUtils.isBottom(sup)) {
      outHead.add(makeSubclassTriple(currentVar, m_Names.get(sup)));
    } else if (fun.equals( ATermUtils.ANDFUN )) {
      ATermList list = (ATermList) sup.getArgument(0);
     
      while( !list.isEmpty() ) {
        ATermAppl conj = (ATermAppl) list.getFirst();
        translateSuper(outHead, conj, freeVar, currentVar);
        list = list.getNext();
      }
    } else if (fun.equals( ATermUtils.SOMEFUN )) {
      ATermAppl prop = (ATermAppl) sup.getArgument(0);
      ATermAppl q = (ATermAppl) sup.getArgument(1);
     
      if (!ATermUtils.isPrimitive(q) && !ATermUtils.isBottom(q)) {
        //Normalization - breaking complex concepts within someValues
        ATermAppl anon = m_Names.getNextAnon();
//        addSubclassRule(anon, q);
        translateSuperSome( anon, q );
        q = anon;
      }
     
      outHead.add(makeSubOfSomeTriple(currentVar, prop, m_Names.get(q)));
    } else {
      assert false;
    }
  }

  private void translateSuperSome(ATermAppl anon, ATermAppl sup) {
    AFun fun = sup.getAFun();
    if( ATermUtils.isPrimitive( sup ) || ATermUtils.isBottom( sup ) ) {
      m_Facts.add( makeSubclassFact( anon, sup ) );
    }
    else if( fun.equals( ATermUtils.ANDFUN ) ) {
      ATermList list = (ATermList) sup.getArgument( 0 );

      while( !list.isEmpty() ) {
        ATermAppl conj = (ATermAppl) list.getFirst();
        translateSuperSome( anon, conj );
        list = list.getNext();
      }
    }
    else if( fun.equals( ATermUtils.SOMEFUN ) ) {
      ATermAppl prop = (ATermAppl) sup.getArgument( 0 );
      ATermAppl q = (ATermAppl) sup.getArgument( 1 );

      if( !ATermUtils.isPrimitive( q ) && !ATermUtils.isBottom( q ) ) {
        // Normalization - breaking complex concepts within someValues
        ATermAppl nextAnon = m_Names.getNextAnon();
        translateSuperSome( nextAnon, q );
        q = nextAnon;
      }

      m_Facts.add( makeSubOfSomeFact( anon, prop, q ) );
    }
    else {
      assert false;
    }   
  }
 
  private Triple makeSubclassFact(ATermAppl t1, ATermAppl t2) {
    return makeSubclassFact( m_Names.get( t1 ), m_Names.get( t2 ) );
  }
 
  private Triple makeSubclassFact(Node t1, Node t2) {
    return Triple.create(t1, PRED_SUB, t2);
  }
 
  private Triple makeSubOfSomeFact(ATermAppl t1, ATermAppl t2, ATermAppl t3) {
    return Triple.create(m_Names.get( t1 ), m_Names.get( t2 ), m_Names.get( t3 ));
  }
 
  private TriplePattern makeSubclassTriple(Node t1, Node t2) {
    return new TriplePattern(t1, PRED_SUB, t2);
  }
 
  private TriplePattern makeSubOfSomeTriple(Node t1, ATermAppl p, Node t2) {
    return makeSubOfSomeTriple(t1, m_Names.get(p), t2);
  }
 
  private TriplePattern makeSubOfSomeTriple(Node t1, Node p, Node t2) {
    return new TriplePattern(t1, p, t2);
  }
 
  private Functor makePropertyAssertionFunctor(Node p) {
    Functor f = new Functor("isNotSubClass", new Node[] {p, PRED_SUB});
    f.setImplementor(NOT_EQUAL);
    return f;
  }

 
  static class NameStore {
    private static final String ANON = "tag:clarkparsia.com,2008:pellet:el:anon:";
    private static final int FIRST_ANON = 0;
   
    private Map<ATermAppl, Node> m_Constants = CollectionUtils.makeMap();
    private int m_NextAnon = FIRST_ANON;
   
    public Node get(ATermAppl term) {
      Node c = m_Constants.get(term);
      if (c == null) {
        if (term == ATermUtils.BOTTOM) {
          c = Node.createURI("_BOTTOM_");
        } else {
          c = Node.createURI(term.getName());
        }
        m_Constants.put(term, c);
      }
      return c;
    }
   
    public ATermAppl getNextAnon() {
      return makeAnon(m_NextAnon++);
    }
   
    public Set<ATermAppl> getAllAnons() {
      Set<ATermAppl> anons = CollectionUtils.makeSet();
      for (int i = FIRST_ANON; i < m_NextAnon; i++) {
        anons.add(makeAnon(i));
      }
      return anons;
    }
   
    public static boolean isAnon(Node c) {
      return c.getURI().startsWith(ANON);
    }
   
    private static ATermAppl makeAnon(int id) {
      return ATermUtils.makeTermAppl(ANON + id);
    }
  }
 
  static class VariableStore {
    private static final String PREFIX = "x";
   
    private List<Node> m_Variables = CollectionUtils.makeList();
   
    public Node get(int target) {
      for (int size = m_Variables.size(); size <= target; size++) {
        m_Variables.add(new Node_RuleVariable(PREFIX + size, size));
      }
      return m_Variables.get(target);
    }
  }
 
  class FreeVariableStore {
    private int m_Next = 0;
   
    public Node next() {
      return m_Variables.get(m_Next++);
    }
  }

}
TOP

Related Classes of com.clarkparsia.pellet.el.JenaBasedELClassifier$FreeVariableStore

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.