All Downloads are FREE. Search and download functionalities are using the official Maven repository.

openllet.OpenlletClassify Maven / Gradle / Ivy

There is a newer version: 2.6.5
Show newest version
// Copyright (c) 2006 - 2008, Clark & Parsia, LLC. 
// 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: [email protected]

package openllet;

import static openllet.OpenlletCmdOptionArg.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 java.util.stream.Collectors;
import openllet.aterm.ATermAppl;
import openllet.core.KnowledgeBase;
import openllet.core.OpenlletOptions;
import openllet.core.taxonomy.printer.ClassTreePrinter;
import openllet.core.taxonomy.printer.TaxonomyPrinter;
import openllet.modularity.IncrementalClassifier;
import openllet.modularity.OntologyDiff;
import openllet.modularity.io.IncrementalClassifierPersistence;
import openllet.owlapi.OWLAPILoader;
import openllet.owlapi.OWLClassTreePrinter;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLOntology;

/**
 * 

* Copyright: Copyright (c) 2008 *

*

* Company: Clark & Parsia, LLC. *

* * @author Markus Stocker */ public class OpenlletClassify extends OpenlletCmdApp { /** * 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 final File saveDirectory = new File("."); /** * Boolean flag whether the state of the classifier saved on disk is up-to-date */ private boolean _currentStateSaved = false; public OpenlletClassify() { } @Override public String getAppCmd() { return "openllet classify " + getMandatoryOptions() + "[_options] ..."; } @Override public String getAppId() { return "OpenlletClassify: Classify the ontology and display the hierarchy"; } @Override public OpenlletCmdOptions getOptions() { final OpenlletCmdOptions options = getGlobalOptions(); final OpenlletCmdOption option = new OpenlletCmdOption("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 OWLAPI _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() { final KnowledgeBase kb = getKB(); startTask("consistency check"); final boolean isConsistent = kb.isConsistent(); finishTask("consistency check"); if (!isConsistent) throw new OpenlletCmdException("Ontology is inconsistent, run \"openllet explain\" to get the reason"); startTask("classification"); kb.classify(); finishTask("classification"); final TaxonomyPrinter printer = new ClassTreePrinter(); printer.print(kb.getTaxonomy()); } /** * Performs classification using the incremental classifier (and persisted _data) */ private void runIncrementalClassify() { final String loaderName = _options.getOption("loader").getValueAsString(); if (!"OWLAPI".equals(loaderName)) _logger.log(Level.WARNING, "Ignoring -l " + loaderName + " option. When using --persist the only allowed loader is OWLAPI"); final OWLAPILoader loader = (OWLAPILoader) getLoader("OWLAPI"); loader.parse(getInputFiles()); final OWLOntology ontology = loader.getOntology(); final IncrementalClassifier incrementalClassifier = createIncrementalClassifier(ontology); if (!incrementalClassifier.isClassified()) { startTask("consistency check"); final boolean isConsistent = incrementalClassifier.isConsistent(); finishTask("consistency check"); if (!isConsistent) throw new OpenlletCmdException("Ontology is inconsistent, run \"openllet explain\" to get the reason"); startTask("classification"); incrementalClassifier.classify(); finishTask("classification"); } final TaxonomyPrinter 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(final OWLOntology ontology) { final 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(OpenlletOptions.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(final IncrementalClassifier incrementalClassifier, final OWLOntology ontology) { final File saveFile = determineSaveFile(ontology); try { verbose("Saving the state of the classifier to " + saveFile); final FileOutputStream outputStream = new FileOutputStream(saveFile); IncrementalClassifierPersistence.save(incrementalClassifier, outputStream); } catch (final IOException e) { _logger.log(Level.WARNING, "Unable to persist the current classifier state.", e); } } /** * 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(final OWLOntology ontology, final File file) { try { final FileInputStream inputStream = new FileInputStream(file); verbose("Reading persisted classifier state from " + file); final 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 final OntologyDiff ontologyDiff = OntologyDiff.diffAxioms(result.axioms(), ontology.axioms().collect(Collectors.toSet())); 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<>(ontologyDiff.getChanges(ontology))); } else _currentStateSaved = true; return result; } catch (final IOException e) { _logger.log(Level.WARNING, "Unable to read the persisted information from a file. Openllet 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(final OWLOntology ontology) { final 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(final OWLOntology ontology) { final byte[] uriBytes = ontology.getOntologyID().getOntologyIRI().toString().getBytes(); MessageDigest MD5 = null; try { MD5 = MessageDigest.getInstance("MD5"); } catch (final NoSuchAlgorithmException e) { throw new OpenlletCmdException("MD5 digest algorithm is not available.", e); } final byte[] hashBytes = MD5.digest(uriBytes); final BigInteger bi = new BigInteger(1, hashBytes); return bi.toString(ENCODING_RADIX); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy