Package pellet

Source Code of pellet.PelletClassify

// 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 pellet;

import static pellet.PelletCmdOptionArg.NONE;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedList;
import java.util.logging.Level;

import org.mindswap.pellet.KnowledgeBase;
import org.mindswap.pellet.PelletOptions;
import org.mindswap.pellet.taxonomy.printer.ClassTreePrinter;
import org.mindswap.pellet.taxonomy.printer.TaxonomyPrinter;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLException;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyChange;

import aterm.ATermAppl;

import com.clarkparsia.modularity.IncrementalClassifier;
import com.clarkparsia.modularity.OntologyDiff;
import com.clarkparsia.modularity.io.IncrementalClassifierPersistence;
import com.clarkparsia.pellet.owlapiv3.OWLAPILoader;
import com.clarkparsia.pellet.owlapiv3.OWLClassTreePrinter;

/**
* <p>
* Title: PelletClassify
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2008
* </p>
* <p>
* Company: Clark & Parsia, LLC. <http://www.clarkparsia.com>
* </p>
*
* @author Markus Stocker
*/
public class PelletClassify extends PelletCmdApp {
 
  /**
   * Maximum radix for encoding of the MD5 of the root ontology URI
   */
  private static final int ENCODING_RADIX = 36;
 
  /**
   * The pattern for the names of the files containing the persisted data of the incremental classifier. The
   * parameter in the pattern should be replaced with the MD5 of the root ontology IRI (to prevent mixing up
   * files that belong to different ontologies).
   */
  private static final String FILE_NAME_PATTERN   = "persisted-state-%s.zip";
 
  /**
   * The directory where persisted state is saved (for now, this is the current directory).
   */
  private File saveDirectory = new File( "." );
 
  /**
   * Boolean flag whether the state of the classifier saved on disk is up-to-date
   */
  private boolean currentStateSaved = false;

  public PelletClassify() {
  }

  @Override
  public String getAppCmd() {
    return "pellet classify " + getMandatoryOptions() + "[options] <file URI>...";
  }

  @Override
  public String getAppId() {
    return "PelletClassify: Classify the ontology and display the hierarchy";
  }

  @Override
  public PelletCmdOptions getOptions() {
    PelletCmdOptions options = getGlobalOptions();
   
    PelletCmdOption option = new PelletCmdOption( "persist" );
    option.setShortOption( "p" );
    option.setDescription( "Enable persistence of classification results. The classifier will save its internal state in a file, and will reuse it the next time this ontology is loaded, therefore saving classification time. This option can only be used with OWLAPIv3 loader." );
    option.setIsMandatory( false );
    option.setArg( NONE );
    options.add( option );
   
    options.add( getLoaderOption() );
    options.add( getIgnoreImportsOption() );
    options.add( getInputFormatOption() );
   
    return options;
  }

  @Override
  public void run() {
    if( options.getOption("persist").getValueAsBoolean() ) {
      runIncrementalClassify();
    }
    else {
      runClassicClassify();
    }
  }
 
  /**
   * Performs classification using the non-incremental (classic) classifier
   */
  private void runClassicClassify() {
    KnowledgeBase kb = getKB();
   
    startTask( "consistency check" );
    boolean isConsistent = kb.isConsistent();   
    finishTask( "consistency check" );

    if( !isConsistent )
      throw new PelletCmdException( "Ontology is inconsistent, run \"pellet explain\" to get the reason" );

    startTask( "classification" );
    kb.classify();
    finishTask( "classification" );

    TaxonomyPrinter<ATermAppl> printer = new ClassTreePrinter();
    printer.print( kb.getTaxonomy() );
  }
 
  /**
   * Performs classification using the incremental classifier (and persisted data)
   */
  private void runIncrementalClassify() {
    String loaderName = options.getOption( "loader" ).getValueAsString();
   
    if( !"OWLAPIv3".equals( loaderName ) ) {
      logger.log( Level.WARNING, "Ignoring -l " + loaderName + " option. When using --persist the only allowed loader is OWLAPIv3" );
    }
   
    OWLAPILoader loader = (OWLAPILoader) getLoader( "OWLAPIv3" );
   
    loader.parse( getInputFiles() );
    OWLOntology ontology = loader.getOntology();
   
    IncrementalClassifier incrementalClassifier = createIncrementalClassifier( ontology );
   
    if ( !incrementalClassifier.isClassified() ) {
      startTask( "consistency check" );
      boolean isConsistent = incrementalClassifier.isConsistent();
      finishTask( "consistency check" );

      if( !isConsistent )
        throw new PelletCmdException( "Ontology is inconsistent, run \"pellet explain\" to get the reason" );

      startTask( "classification" );
      incrementalClassifier.classify();
      finishTask( "classification" );
    }

    TaxonomyPrinter<OWLClass> printer = new OWLClassTreePrinter();
    printer.print( incrementalClassifier.getTaxonomy() );
   
    if( !currentStateSaved ) {
      persistIncrementalClassifier( incrementalClassifier, ontology );
    }
  }
 
  /**
   * Creates incremental classifier by either creating it from scratch or by reading its state from file (if there exists such a state)
   * @param ontology the ontology (the current state of it)
   * @return the incremental classifier
   */
  private IncrementalClassifier createIncrementalClassifier( OWLOntology ontology ) {
    File saveFile = determineSaveFile( ontology );
    IncrementalClassifier result = null;
   
    // first try to restore the classifier from the file (if one exists)
    if( saveFile.exists() ) {
      result = loadIncrementalClassifier( ontology, saveFile );
    }
   
    // if it was not possible to restore the classifier, create one from scratch
    if( result == null ) {
      result = new IncrementalClassifier( ontology );
    }
   
    result.getReasoner().getKB().setTaxonomyBuilderProgressMonitor(
                                                                   PelletOptions.USE_CLASSIFICATION_MONITOR
                                                                                   .create());
   
    return result;
  }
 
  /**
   * Stores the current state of the incremental classifier to a file (the file name is determined automatically
   * based on ontology's IRI).
   *
   * @param incrementalClassifier the incremental classifier to be stored
   * @param ontology the ontology
   */
  private void persistIncrementalClassifier( IncrementalClassifier incrementalClassifier, OWLOntology ontology ) {
    File saveFile = determineSaveFile( ontology );
   
    try {
      verbose( "Saving the state of the classifier to " + saveFile );
          FileOutputStream outputStream = new FileOutputStream( saveFile );
          IncrementalClassifierPersistence.save( incrementalClassifier, outputStream );
        }
        catch( IOException e ) {
          logger.log( Level.WARNING, "Unable to persist the current classifier state: " + e.toString() );
        }   
  }
 
  /**
   * Loads the incremental classifier from a file. If the ontology changed since the state of the classifier was
   * persisted, the classifier will be incrementally updated with the changes.
   *
   * @param ontology the ontology (its current state, since class
   * @param file the file from which the persisted state will be read
   * @return the read classifier or null, if it was not possible to read the classifier
   */
  private IncrementalClassifier loadIncrementalClassifier( OWLOntology ontology, File file ) {
    try {
      FileInputStream inputStream = new FileInputStream( file );
   
      verbose( "Reading persisted classifier state from " + file );
      IncrementalClassifier result = IncrementalClassifierPersistence.load( inputStream, ontology );
     
      // check whether anything changed in the ontology in the time between the incremental classifier
      // was persisted and the current time
      OntologyDiff ontologyDiff = OntologyDiff.diffAxioms( result.getAxioms(), ontology.getAxioms() );
     
      if( ontologyDiff.getDiffCount() > 0 ) {
        verbose( "There were changes to the underlying ontology since the classifier was persisted. Incrementally updating the classifier" );
        result.ontologiesChanged( new LinkedList<OWLOntologyChange>( ontologyDiff.getChanges( ontology ) ) );
      } else {
        currentStateSaved = true;
      }
     
      return result;
    }
    catch( IOException e ) {
      logger.log( Level.WARNING, "Unable to read the persisted information from a file. Pellet will perform full classification: " + e );
     
      return null;
    }
        catch( OWLException e ) {
          logger.log( Level.WARNING, "Unable to incrementally update the classifier. Pellet will perform full classification: " + e );
         
          return null;
        }
  }
 
  /**
   * Computes the name of the file to which the state of the incremental classifier will be persisted/read from.
   *
   * @return the file name
   */
  private File determineSaveFile( OWLOntology ontology ) {
    String fileName = String.format( FILE_NAME_PATTERN, hashOntologyIRI( ontology ) );
   
    return new File( saveDirectory, fileName );
  }
 
  /**
   * Computes the hash code of the ontology IRI and returns the string representation of the hash code. The hash code
   * is used to identify which files contain information about the particular ontology (and we can't use directly IRIs since they can contain special
   * characters that are not allowed in file names, not to mention that this would make the file names too long).
   *
   * @return the string representation of the hash code of the ontology IRI
   */
  private String hashOntologyIRI( OWLOntology ontology ) {
    byte[] uriBytes = ontology.getOntologyID().getOntologyIRI().toString().getBytes();

    MessageDigest MD5 = null;
   
    try {
      MD5 = MessageDigest.getInstance( "MD5" );
    } catch( NoSuchAlgorithmException e ) {
      throw new PelletCmdException( "MD5 digest algorithm is not available." );
    }
   
    byte[] hashBytes = MD5.digest( uriBytes );
   
    BigInteger bi = new BigInteger( 1, hashBytes );
   
    return bi.toString( ENCODING_RADIX );
  }
}
TOP

Related Classes of pellet.PelletClassify

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.