Example #1
0
  /**
   * Partition the members of an iterator into two lists, according to whether they are named or
   * anonymous classes
   *
   * @param i An iterator to partition
   * @param named A list of named classes
   * @param anon A list of anonymous classes
   */
  protected static void partitionByNamed(
      Iterator<? extends OntClass> i, List<OntClass> named, List<OntClass> anon) {
    while (i.hasNext()) {
      OntClass c = i.next();
      boolean ignore = false;

      // duplicate check: we ignore this class if we've already got it
      if (named.contains(c)) {
        ignore = true;
      }

      // subsumption check: c must have only anon classes or Thing
      // as super-classes to still qualify as a root class
      Resource thing = c.getProfile().THING();
      for (Iterator<OntClass> j = c.listSuperClasses(); !ignore && j.hasNext(); ) {
        OntClass sup = j.next();
        if (!((thing != null && sup.equals(thing)) || sup.isAnon() || sup.equals(c))) {
          ignore = true;
        }
      }

      if (!ignore) {
        // place the class in the appropriate partition
        (c.isAnon() ? anon : named).add(c);
      }
    }
  }
Example #2
0
  /**
   * Answer a list of the named hierarchy roots of a given {@link OntModel}. This will be similar to
   * the results of {@link OntModel#listHierarchyRootClasses()}, with the added constraint that
   * every member of the returned iterator will be a named class, not an anonymous class expression.
   * The named root classes are calculated from the root classes, by recursively replacing every
   * anonymous class with its direct sub-classes. Thus it can be seen that the values in the list
   * consists of the shallowest fringe of named classes in the hierarchy.
   *
   * @param m An ontology model
   * @return A list of classes whose members are the named root classes of the class hierarchy in
   *     <code>m</code>
   */
  public static List<OntClass> namedHierarchyRoots(OntModel m) {
    List<OntClass> nhr = new ArrayList<OntClass>(); // named roots
    List<OntClass> ahr = new ArrayList<OntClass>(); // anon roots

    // do the initial partition of the root classes
    partitionByNamed(m.listHierarchyRootClasses(), nhr, ahr);

    // now push the fringe down until we have only named classes
    while (!ahr.isEmpty()) {
      OntClass c = ahr.remove(0);
      partitionByNamed(c.listSubClasses(true), nhr, ahr);
    }

    return nhr;
  }
Example #3
0
  /**
   * Answer the lowest common ancestor of two classes, assuming that the given class is the root
   * concept to start searching from. See {@link #getLCA(OntModel, OntClass, OntClass)} for details.
   *
   * @param m The ontology model being queried to find the LCA, which should conform to the reasoner
   *     capabilities described above
   * @param root The root concept, which will be the starting point for the algorithm
   * @param u An ontology class
   * @param v An ontology class
   * @return The LCA of <code>u</code> and <code>v</code>
   * @exception JenaException if the language profile of the given model does not define a top
   *     concept (e.g. <code>owl:Thing</code>)
   */
  public static OntClass getLCA(OntModel m, OntClass root, OntClass u, OntClass v) {
    // check some common cases first
    if (u.equals(root) || v.equals(root)) {
      return root;
    }

    if (u.hasSubClass(v)) {
      return u;
    }

    if (v.hasSubClass(u)) {
      return v;
    }

    // not a common case, so apply Tarjan's LCA algorithm
    LCAIndex index = new LCAIndex();
    lca(root, u, v, index);
    return (OntClass) index.getLCA(u, v);
  }
Example #4
0
  /**
   * Compute the LCA disjoint set at <code>cls</code>, noting that we are searching for the LCA of
   * <code>uCls</code> and <code>vCls</code>.
   *
   * @param cls The class we are testing (this is 'u' in the Wiki article)
   * @param uCls One of the two classes we are searching for the LCA of. We have simplified the set
   *     P of pairs to the unity set {uCls,vCls}
   * @param vCls One of the two classes we are searching for the LCA of. We have simplified the set
   *     P of pairs to the unity set {uCls,vCls}
   * @param index A data structure mapping resources to disjoint sets (since we can't side-effect
   *     Jena resources), and which is used to record the LCA pairs
   */
  protected static DisjointSet lca(OntClass cls, OntClass uCls, OntClass vCls, LCAIndex index) {
    //        log.debug( "Entering lca(), cls = " + cls );
    DisjointSet clsSet = index.getSet(cls);
    if (clsSet.isBlack()) {
      // already visited
      return clsSet;
    }

    // not visited yet
    clsSet.setAncestor(clsSet);

    // for each child of cls
    for (Iterator<OntClass> i = cls.listSubClasses(true); i.hasNext(); ) {
      OntClass child = i.next();

      if (child.equals(cls) || child.equals(cls.getProfile().NOTHING())) {
        // we ignore the reflexive case and bottom
        continue;
      }

      // compute the LCA of the sub-tree
      DisjointSet v = lca(child, uCls, vCls, index);

      // union the two disjoint sets together
      clsSet.union(v);

      // propagate the distinguished member
      clsSet.find().setAncestor(clsSet);
    }

    // this node is done
    clsSet.setBlack();

    // are we inspecting one of the elements we're interested in?
    if (cls.equals(uCls)) {
      checkSolution(uCls, vCls, index);
    } else if (cls.equals(vCls)) {
      checkSolution(vCls, uCls, index);
    }

    return clsSet;
  }