Skip to content

Commit

Permalink
Merge pull request #20 from phyloref/add_factpp_as_reasoner
Browse files Browse the repository at this point in the history
This PR adds a --reasoner command line option which can be used to change reasoners, and adds the FaCT++ 1.5.2 reasoner as an optional reasoner. Since FaCT++ depends on OWL 4.x, it reverts the OWLAPI from 5.0.4 to 4.2.7, which required a few minor code changes. Since FaCT++ uses native libraries (through the Java Native Interface), I've also added a README that explains how to download and set up those libraries.
  • Loading branch information
gaurav committed Aug 8, 2018
2 parents 35887c6 + b6a68cb commit 9607296
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 58 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# JNI libraries
*.jnilib

# Eclipse files
.classpath
.settings/
bin/

# Compiled class file
*.class
Expand Down
14 changes: 14 additions & 0 deletions lib/factplusplus/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Using FaCT++ with JPhyloRef

JPhyloRef picks up the latest version of FaCT++ published to a Maven repository
(currently [Factplusplus 1.5.2] on Berkeley BOP), but this doesn't include the
native libraries necessary to make the reasoner work. You will need to download
them separately from the [factplusplus Google Code Archive].

When invoking JPhyloRef from the command line, you may need to provide the path
to the native library using the `java.library.path` setting, such as:

java -Djava.library.path='lib/factplusplus/FaCT++-OSX-v1.5.2/64bit/' -jar target/jphyloref-0.2-SNAPSHOT.jar webserver --reasoner fact++

[Factplusplus 1.5.2]: https://mvnrepository.com/artifact/uk.ac.manchester.cs/factplusplus/1.5.2
[factplusplus Google Code Archive]: https://code.google.com/archive/p/factplusplus/downloads
42 changes: 34 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<repositories>
<repository>
<id>BBOP</id>
<name>Berkeley BOP</name>
<url>http://code.berkeleybop.org/maven/repository/</url>
</repository>
</repositories>

<dependencies>
<!-- For processing command line arguments -->
<dependency>
Expand All @@ -24,13 +32,6 @@
<version>1.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/net.sourceforge.owlapi/jfact -->
<dependency>
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>jfact</artifactId>
<version>5.0.1</version>
</dependency>

<!-- For producing testing output -->
<dependency>
<groupId>org.tap4j</groupId>
Expand Down Expand Up @@ -62,12 +63,37 @@
<scope>runtime</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.eclipse.rdf4j/rdf4j-rio-api -->
<dependency>
<groupId>org.eclipse.rdf4j</groupId>
<artifactId>rdf4j-rio-api</artifactId>
<version>2.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.github.jsonld-java/jsonld-java -->
<dependency>
<groupId>com.github.jsonld-java</groupId>
<artifactId>jsonld-java</artifactId>
<version>0.12.0</version>
</dependency>

<!-- REASONERS -->

<!-- JFact is our default reasoner -->
<!-- https://mvnrepository.com/artifact/net.sourceforge.owlapi/jfact -->
<dependency>
<groupId>net.sourceforge.owlapi</groupId>
<artifactId>jfact</artifactId>
<version>4.0.4</version>
</dependency>

<!-- Fact++ is a very fast JNI-based reasoner -->
<dependency>
<groupId>uk.ac.manchester.cs</groupId>
<artifactId>factplusplus</artifactId>
<version>1.5.2</version>
</dependency>

<!-- Adds a StaticLoggerBinder for logging (as per phyloref/jphyloref#18) -->
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
Expand All @@ -83,7 +109,7 @@
<version>3.8.1</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/org/phyloref/jphyloref/JPhyloRef.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
Expand All @@ -11,6 +13,13 @@
import org.phyloref.jphyloref.commands.ReasonCommand;
import org.phyloref.jphyloref.commands.TestCommand;
import org.phyloref.jphyloref.commands.WebserverCommand;
import org.phyloref.jphyloref.helpers.ReasonerHelper;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
import org.semanticweb.owlapi.util.Version;
import org.semanticweb.owlapi.util.VersionInfo;

/**
Expand Down Expand Up @@ -40,6 +49,11 @@ public class JPhyloRef {
public void execute(String[] args) {
// Prepare to parse command line arguments.
Options opts = new Options();

// Add global options.
ReasonerHelper.addCommandLineOptions(opts);

// Add per-command options.
for(Command cmd: commands) {
cmd.addCommandLineOptions(opts);
}
Expand All @@ -60,6 +74,9 @@ public void execute(String[] args) {
HelpCommand help = new HelpCommand();
help.execute(cmdLine);
} else {
// Look for global options:
// --reasoner: Set the reasoner.

// The first unprocessed argument should be the command.
String command = cmdLine.getArgList().get(0);

Expand Down Expand Up @@ -134,6 +151,15 @@ public void execute(CommandLine cmdLine) {
);
}
}

// Display global options, including the list of possible reasoners.
System.out.println("\nWe also accept some global options, including:");
System.out.println(" --reasoner <reasonerName>: sets the reasoner name, which should be one of:");
Map<String, OWLReasonerFactory> reasonerList = ReasonerHelper.getReasonerFactories();
for(String name: reasonerList.keySet()) {
OWLReasonerFactory factory = reasonerList.get(name);
System.out.println(" '" + name + "': " + ReasonerHelper.getReasonerNameAndVersion(factory));
}

// One final blank line, please.
System.out.println("");
Expand Down
27 changes: 13 additions & 14 deletions src/main/java/org/phyloref/jphyloref/commands/TestCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.apache.commons.cli.Options;
import org.phyloref.jphyloref.helpers.OWLHelper;
import org.phyloref.jphyloref.helpers.PhylorefHelper;
import org.phyloref.jphyloref.helpers.ReasonerHelper;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.ClassExpressionType;
Expand All @@ -30,6 +31,8 @@
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.reasoner.BufferingMode;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
import org.semanticweb.owlapi.search.EntitySearcher;
import org.semanticweb.owlapi.util.AutoIRIMapper;
import org.semanticweb.owlapi.vocab.OWLRDFVocabulary;
Expand Down Expand Up @@ -88,10 +91,6 @@ public void addCommandLineOptions(Options opts) {
"i", "input", true,
"The input ontology to read in RDF/XML (can also be provided without the '-i')"
);
opts.addOption(
"nr", "no-reasoner", false,
"Turn off reasoning (all tests will fail!)"
);
}

/**
Expand All @@ -105,7 +104,6 @@ public void addCommandLineOptions(Options opts) {
public void execute(CommandLine cmdLine) throws RuntimeException {
// Extract command-line options
String str_input = cmdLine.getOptionValue("input");
boolean flag_no_reasoner = cmdLine.hasOption("no-reasoner");

if(str_input == null && cmdLine.getArgList().size() > 1) {
// No 'input'? Maybe it's just provided as a left-over option?
Expand All @@ -119,7 +117,7 @@ public void execute(CommandLine cmdLine) throws RuntimeException {
// Create File object to load
File inputFile = new File(str_input);
System.err.println("Input: " + inputFile);

// Set up an OWL Ontology Manager to work with.
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();

Expand All @@ -141,12 +139,13 @@ public void execute(CommandLine cmdLine) throws RuntimeException {
System.err.println("Loaded ontology: " + ontology);

// Reason over the loaded ontology -- but only if the user wants that!
JFactReasonerConfiguration config = new JFactReasonerConfiguration();
JFactReasoner reasoner = null;
// Set up an OWLReasoner to work with.
OWLReasonerFactory reasonerFactory = ReasonerHelper.getReasonerFactoryFromCmdLine(cmdLine);
OWLReasoner reasoner = null;
if(reasonerFactory != null) reasoner = reasonerFactory.createReasoner(ontology);
Set<OWLNamedIndividual> phylorefs;

// Get a list of all phyloreferences.
if(!flag_no_reasoner) reasoner = new JFactReasoner(ontology, config, BufferingMode.BUFFERING);
phylorefs = PhylorefHelper.getPhyloreferences(ontology, reasoner);

// Okay, time to start testing! Each phyloreference counts as one test.
Expand Down Expand Up @@ -211,11 +210,11 @@ public void execute(CommandLine cmdLine) throws RuntimeException {
Set<OWLNamedIndividual> nodes;
if(reasoner != null) {
// Use the reasoner to determine which nodes are members of this phyloref as a class
nodes = reasoner.getInstances(phylorefAsClass, false).entities()
nodes = reasoner.getInstances(phylorefAsClass, false).getFlattened().stream()
// This includes the phyloreference itself. We only want to
// look at phylogeny nodes here. So, let's filter down to named
// individuals that are asserted to be cdao:Nodes.
.filter(indiv -> EntitySearcher.getTypes(indiv, ontology).anyMatch(
.filter(indiv -> EntitySearcher.getTypes(indiv, ontology).stream().anyMatch(
type -> (!type.getClassExpressionType().equals(ClassExpressionType.OWL_CLASS)) ||
type.asOWLClass().getIRI().equals(PhylorefHelper.IRI_CDAO_NODE)
))
Expand Down Expand Up @@ -253,7 +252,7 @@ public void execute(CommandLine cmdLine) throws RuntimeException {

for(OWLNamedIndividual node: nodes) {
// Get a list of all expected phyloreference labels from the OWL file.
Set<String> expectedPhylorefsNamed = EntitySearcher.getDataPropertyValues(node, expectedPhyloreferenceNamedProperty, ontology)
Set<String> expectedPhylorefsNamed = EntitySearcher.getDataPropertyValues(node, expectedPhyloreferenceNamedProperty, ontology).stream()
.map(literal -> literal.getLiteral()) // We ignore languages for now.
.collect(Collectors.toSet());

Expand Down Expand Up @@ -300,7 +299,7 @@ public void execute(CommandLine cmdLine) throws RuntimeException {
}

// Look for all unmatched specifiers reported for this phyloreference
Set<OWLAxiom> axioms = EntitySearcher.getReferencingAxioms(phyloref, ontology).collect(Collectors.toSet());
Set<OWLAxiom> axioms = new HashSet<>(EntitySearcher.getReferencingAxioms(phyloref, ontology));
Set<OWLNamedIndividual> unmatched_specifiers = new HashSet<>();
for(OWLAxiom axiom: axioms) {
if(axiom.containsEntityInSignature(unmatchedSpecifierProperty)) {
Expand All @@ -324,7 +323,7 @@ public void execute(CommandLine cmdLine) throws RuntimeException {
}

// Retrieve holdsStatusInTime to determine the active status of this phyloreference.
Set<OWLAnnotation> holdsStatusInTime = EntitySearcher.getAnnotations(phylorefAsClass, ontology, pso_holdsStatusInTime).collect(Collectors.toSet());
Set<OWLAnnotation> holdsStatusInTime = new HashSet<>(EntitySearcher.getAnnotations(phylorefAsClass, ontology, pso_holdsStatusInTime));

// Instead of checking which time interval were are in, we take a simpler approach: we look for all
// statuses that have a start date but not an end date, i.e. those which have yet to end.
Expand Down
Loading

0 comments on commit 9607296

Please sign in to comment.