/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
HermiT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with HermiT. If not, see <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.semanticweb.HermiT.model.AtomicConcept;
import org.semanticweb.HermiT.monitor.TableauMonitor;
import org.semanticweb.owlapi.reasoner.FreshEntityPolicy;
import org.semanticweb.owlapi.reasoner.IndividualNodeSetPolicy;
import org.semanticweb.owlapi.reasoner.OWLReasonerConfiguration;
import org.semanticweb.owlapi.reasoner.ReasonerProgressMonitor;
public class Configuration implements Serializable,Cloneable,OWLReasonerConfiguration {
private static final long serialVersionUID=7741510316249774519L;
/**
* Tableau monitors can be used to be informed about what HermiT does and they can be useful for debugging the reasoner.
*/
public static enum TableauMonitorType {
/**
* The standard setting is no monitor, i.e., no information is recorded and printed about what the reasoner does.
*/
NONE,
/**
* The TIMING tableau monitor print information about the tableau (number of nodes etc) in certain time intervals.
*/
TIMING,
/**
* Waits at certain points (e.g., before building a tableau) for a keystroke by the user and is apart from that like
* TIMING.
*/
TIMING_WITH_PAUSE,
/**
* This opens a debugging application for HermiT. HermiT can be controlled with special commands from within the
* debugging application. Without history HermiT does not record information about how assertions have been derived, so
* one cannot see the derivation history for an assertion.
*/
DEBUGGER_NO_HISTORY,
/**
* This opens a debugging application for HermiT. HermiT can be controlled with special commands from within the
* debugging application. HermiT will keep, for each derived fact/assertion, how the assertion was derived. This is
* obviously using a lot more memory than normal, but can be useful when debugging the reasoner.
*/
DEBUGGER_HISTORY_ON
}
/**
* Sets the blocking type used by HermiT. This can be combined with settings for the blocking strategy (anywhere or
* ancestor or core blocking).
*/
public static enum DirectBlockingType {
/**
* Forces HermiT to use single blocking even if the ontology is not suitable for single blocking (contains inverse roles).
*/
SINGLE,
/**
* Forces HermiT to use pairwise blocking even if the ontology does not require that (contains no inverses).
*/
PAIR_WISE,
/**
* Chooses the optimal blocking. If the ontology contains nominals HermiT will use single simple core blocking
* (works even with inverses) and otherwise HermiT uses single blocking if the ontology contains no inverses and
* pairwise blocking otherwise.
*/
OPTIMAL
}
/**
* The blocking strategy determines how which nodes HermiT considers for blockers.
*/
public static enum BlockingStrategyType {
/**
* Forces HermiT to use anywhere blocking. Anywhere blocking usually creates smaller models than ancestor blocking.
* It might be slower, but seems to work better in average cases.
*/
ANYWHERE,
/**
* Forces HermiT to use ancestor blocking. Generates usually the biggest model, but can be faster in some cases than
* the other strategies.
*/
ANCESTOR,
/**
* An approximate blocking strategy and HermiT validates whether the block is ok before terminating. Concepts that
* were added nondeterministically and concepts that are propagated from the parent node are considered for
* blocking. Produces smaller models (less memory) than ANYWHERE and ANCESTOR, but can be slower in
* particular since caching cannot be used with this blocking strategy. Caching is normally used if the
* ontology does not contain nominals.
*/
COMPLEX_CORE,
/**
* An approximate blocking strategy and HermiT validates whether the block is ok before terminating. Only
* concepts that where added when the node was created are considered for blocking (e.g., for
* ClassAssertion(ObjectSomeValuesFrom(r C) a) an r-successor say b is created with C in the label of b and
* C counts for blocking; any concept added later to the label is not considered for blocking. ) This can generate
* very small models, but might increase the time required in particular for classification of ontologies without
* nominals since caching cannot yet be used with this strategy. This is the default for ontologies with nominals
* where caching cannot be used anyway.
*/
SIMPLE_CORE,
/**
* If the ontology contains nominals HermiT uses SIMPLE_CORE otherwise ANYWHERE.
*/
OPTIMAL
}
/**
* Switches caching on or off (caching can only be used with non-core blocking and if the ontology does not contain nominals).
* With caching HermiT caches blockers. The first satisfiability test can be slow, but in subsequent tests blocking can occur
* much earlier from cached blockers, which saves time and memory.
*/
public static enum BlockingSignatureCacheType {
/**
* Forces HermiT to use caching (if compatible with the ontology).
*/
CACHED,
/**
* Disables caching.
*/
NOT_CACHED
}
/**
* Sets a strategy type that determines how HermiT expands the model.
*/
public static enum ExistentialStrategyType {
/**
* Strategy for expanding all existentials on the oldest node in the tableau with unexpanded existentials.
* This usually closely approximates a breadth-first expansion. (Existentials introduced onto parent nodes
* as a result of constraints on their children can produce newer nodes of lower depth than older nodes,
* which could result in slight non-breadth-first behavior.)
*/
CREATION_ORDER,
/**
* Individual reuse tries to reuse existing individuals first before creating a fresh successor. This can
* introduce a lot of non-determinism, but the models can be much smaller (less memory required).
*/
INDIVIDUAL_REUSE,
/**
* For EL ontologies this existential strategy can be set to use a deterministic version of individual
* reuse that behaves similar to EL-style algorithms.
*/
EL
}
/**
* One can implement an instance of this class and pass it to HermiT. HermiT will then print warning with the
* warning() method of the interface, e.g., if it ignores an unsupported datatype. HermiT does not provide an
* implementation for the interface itself though.
*/
public WarningMonitor warningMonitor;
/**
* If a progress monitor is set, HermiT will report the progress of a classification task. This is used for
* example by Protege.
*/
public ReasonerProgressMonitor reasonerProgressMonitor;
public TableauMonitorType tableauMonitorType;
public DirectBlockingType directBlockingType;
public BlockingStrategyType blockingStrategyType;
public BlockingSignatureCacheType blockingSignatureCacheType;
public ExistentialStrategyType existentialStrategyType;
/**
* If HermiT encounters a non-OWL2 datatype, it normally throws an error. If set to true, axioms containing unsupported
* datatypes will be ignored.
*/
public boolean ignoreUnsupportedDatatypes;
/**
* Can be used to set a custom Tableau monitor.
*/
public TableauMonitor monitor;
/**
* The parameters are passed to the Tableau class instance, but currently no parameters are used.
*/
public Map<String,Object> parameters;
/**
* If set to some value, reasoning in HermiT is interrupted as soon as any individual reasoning task takes any longer than
* individualTaskTimeout ms.
*/
public long individualTaskTimeout;
public IndividualNodeSetPolicy individualNodeSetPolicy;
public FreshEntityPolicy freshEntityPolicy;
/**
* If set to true, then each disjunct of a disjunction is associated with a punish factor and whenever a disjunct causes
* a clash, the punish factor is increased. Whenever HermiT has to pick a disjunction, it picks the disjunction with
* the least punish factor that has not yet been tried for that node and disjunction.
*/
public boolean useDisjunctionLearning;
/**
* If set to true, then axioms that are to be added or removed are buffered and the addition and removal is only performed
* when the flush() method of the reasoner is called.
*/
public boolean bufferChanges;
/**
* The default value is true and HermiT will throw an exception if it finds the ontology to be inconsistent.
*
* If set to false, HermiT will not throw an exception for inconsistent ontologies. The only exception is when asked for data property values for an
* individual and a data property because any of the infinitely many data values would be an answer. Restricting answers to just the data values in the
* signature does not make much sense. If the parameter is set to false and the ontology is inconsistent, all classes occurring in the ontology are, for
* example, returned as subclasses of owl:nothing. Some answers might be unexpected or unintuitive, e.g., a property will be both reflexive and irreflexive
* etc. Use with care, e.g., only when trying to get explanations of inconsistencies, where throwing an error might not be helpful.
*/
public boolean throwInconsistentOntologyException;
public PrepareReasonerInferences prepareReasonerInferences;
/**
* The default value is false and HermiT will use a specialiased classification strategy for deterministic ontologies, which often is faster, but not always.
* If the value is set to true, then HermiT will use the Quasi Ordering Classification method even for deterministic ontologies.
*/
public boolean forceQuasiOrderClassification;
public Configuration() {
warningMonitor=null;
reasonerProgressMonitor=null;
tableauMonitorType=Configuration.TableauMonitorType.NONE;
directBlockingType=Configuration.DirectBlockingType.OPTIMAL;
blockingStrategyType=Configuration.BlockingStrategyType.OPTIMAL;
blockingSignatureCacheType=Configuration.BlockingSignatureCacheType.CACHED;
existentialStrategyType=Configuration.ExistentialStrategyType.CREATION_ORDER;
ignoreUnsupportedDatatypes=false;
monitor=null;
parameters=new HashMap<String,Object>();
individualTaskTimeout=-1;
bufferChanges=true;
individualNodeSetPolicy=IndividualNodeSetPolicy.BY_NAME;
freshEntityPolicy=FreshEntityPolicy.ALLOW;
useDisjunctionLearning=true;
throwInconsistentOntologyException=true;
prepareReasonerInferences=null;
forceQuasiOrderClassification=false;
}
protected void setIndividualReuseStrategyReuseAlways(Set<? extends AtomicConcept> concepts) {
parameters.put("IndividualReuseStrategy.reuseAlways",concepts);
}
public void loadIndividualReuseStrategyReuseAlways(File file) throws IOException {
Set<AtomicConcept> concepts=loadConceptsFromFile(file);
setIndividualReuseStrategyReuseAlways(concepts);
}
protected void setIndividualReuseStrategyReuseNever(Set<? extends AtomicConcept> concepts) {
parameters.put("IndividualReuseStrategy.reuseNever",concepts);
}
public void loadIndividualReuseStrategyReuseNever(File file) throws IOException {
Set<AtomicConcept> concepts=loadConceptsFromFile(file);
setIndividualReuseStrategyReuseNever(concepts);
}
protected Set<AtomicConcept> loadConceptsFromFile(File file) throws IOException {
Set<AtomicConcept> result=new HashSet<AtomicConcept>();
BufferedReader reader=new BufferedReader(new FileReader(file));
try {
String line=reader.readLine();
while (line!=null) {
result.add(AtomicConcept.create(line));
line=reader.readLine();
}
return result;
}
finally {
reader.close();
}
}
public Configuration clone() {
try {
Configuration result=(Configuration)super.clone();
result.parameters=new HashMap<String,Object>(parameters);
return result;
}
catch (CloneNotSupportedException cantHappen) {
return null;
}
}
public static interface WarningMonitor {
void warning(String warning);
}
public long getTimeOut() {
return individualTaskTimeout;
}
public IndividualNodeSetPolicy getIndividualNodeSetPolicy() {
return individualNodeSetPolicy;
}
public ReasonerProgressMonitor getProgressMonitor() {
return reasonerProgressMonitor;
}
public FreshEntityPolicy getFreshEntityPolicy() {
return freshEntityPolicy;
}
public static class PrepareReasonerInferences {
public boolean classClassificationRequired=true;
public boolean objectPropertyClassificationRequired=true;
public boolean dataPropertyClassificationRequired=true;
public boolean objectPropertyDomainsRequired=true;
public boolean objectPropertyRangesRequired=true;
public boolean realisationRequired=true;
public boolean objectPropertyRealisationRequired=true;
public boolean dataPropertyRealisationRequired=true;
public boolean sameAs=true;
}
}