I have an RDF Graph with only one relationship(RDFS.subClassOf or is-a) between all the classes.
The 'size' of each class is equal to the total number of its subclasses.
The 'size' of each RDFS.subClassOf property is 0.5 if it is connecting from a class with fewer total number of subclasses and 1 if it is connecting from class with large total number of subclasses to class with less total number of subclasses.
I want to perform an arithmetic sum of all the sizes of each semantic component (class / relationship) in the path using the Jena RDF/Ontology API.
For example, given the camera ontology (http://protege.cim3.net/file/pub/ontologies/camera/camera.owl) one of the paths is: Thing - PurchaseableItem - Lens : Its sum would be (5 + 0.5 + 3 + 0.5 + 0) = 9.
Assuming that this builds on the answer to your previous question about constructing the type of paths that you mention in the question, can you just use:
public static int classSize( final Resource klass ) {
return klass.getModel().listSubjectsWithProperty( RDFS.subClassOf, klass ).toList().size();
}
public static double pathSize( final List<Resource> path ) {
int prevSize = classSize( path.get( 0 ));
double pathSum = prevSize;
for ( int i = 1; i < path.size(); i++ ) {
int currSize = classSize( path.get( i ));
double linkWeight = currSize < prevSize ? 0.5 : 1.0;
pathSum += linkWeight + currSize;
prevSize = currSize;
}
return pathSum;
}
Then we get the following sums for the paths. The complete code follows this output. Notice the owl:Thing
has a size of four here, not five, as you gave in the question. if the idea was to count the number of times that a class appeared as the object in a triple of rdfs:subClassOf
, there are only four triples of the form something rdfs:subClassOf owl:Thing
in the OWL file that you linked to, so it seems like its size should be four, not five. Given that consideration, note that the “Thing–PurchaseableItem–Lens” path has weight eight, as expected (one less than nine, as you mentioned in the question).
4.0 [http://www.w3.org/2002/07/owl#Thing]
7.5 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#PurchaseableItem]
4.5 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#Window]
4.5 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#Range]
4.5 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#Money]
10.0 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#PurchaseableItem, http://www.xfront.com/owl/ontologies/camera/#Camera]
8.0 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#PurchaseableItem, http://www.xfront.com/owl/ontologies/camera/#Lens]
8.0 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#PurchaseableItem, http://www.xfront.com/owl/ontologies/camera/#Body]
10.5 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#PurchaseableItem, http://www.xfront.com/owl/ontologies/camera/#Camera, http://www.xfront.com/owl/ontologies/camera/#Digital]
10.5 [http://www.w3.org/2002/07/owl#Thing, http://www.xfront.com/owl/ontologies/camera/#PurchaseableItem, http://www.xfront.com/owl/ontologies/camera/#Camera, http://www.xfront.com/owl/ontologies/camera/#Large-Format]
Complete code:
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDFS;
public class BFSInRDFWithJena {
public static List<List<Resource>> BFS( final Model model, final Queue<List<Resource>> queue, final int depth ) {
final List<List<Resource>> results = new ArrayList<>();
while ( !queue.isEmpty() ) {
final List<Resource> path = queue.poll();
results.add( path );
if ( path.size() < depth ) {
final Resource last = path.get( path.size() - 1 );
final StmtIterator stmt = model.listStatements( null, RDFS.subClassOf, last );
while ( stmt.hasNext() ) {
final List<Resource> extPath = new ArrayList<>( path );
extPath.add( stmt.next().getSubject().asResource() );
queue.offer( extPath );
}
}
}
return results;
}
public static int classSize( final Resource klass ) {
return klass.getModel().listSubjectsWithProperty( RDFS.subClassOf, klass ).toList().size();
}
public static double pathSize( final List<Resource> path ) {
int prevSize = classSize( path.get( 0 ));
double pathSum = prevSize;
for ( int i = 1; i < path.size(); i++ ) {
int currSize = classSize( path.get( i ));
double linkWeight = currSize < prevSize ? 0.5 : 1.0;
pathSum += linkWeight + currSize;
prevSize = currSize;
}
return pathSum;
}
public static void main( final String[] args ) throws IOException {
final Model model = ModelFactory.createDefaultModel();
try ( final InputStream in = BFSInRDFWithJena.class.getClassLoader().getResourceAsStream( "camera.owl" ) ) {
model.read( in, null );
}
// setup the initial queue
final Queue<List<Resource>> queue = new LinkedList<>();
final List<Resource> thingPath = new ArrayList<>();
thingPath.add( OWL.Thing.inModel( model ));
queue.offer( thingPath );
// Get the paths, and display them
final List<List<Resource>> paths = BFS( model, queue, 4 );
for ( List<Resource> path : paths ) {
System.out.println( pathSize( path ) + " " + path );
}
}
}