如何使用Jena RDF / Ontology API以编程方式计算路径长度?

时间:2013-07-25 20:52:27

标签: rdf semantic-web jena ontology

我有一个RDF图,在所有类之间只有一个关系(RDFS.subClassOf或is-a)。

每个类的“大小”等于其子类的总数。 如果每个RDFS.subClassOf属性的连接来自具有较少子类总数的类,则它的“大小”为0.5;如果它从具有较大子类总数的类连接到具有较少子类总数的类,则为1。

我想使用Jena RDF / Ontology API对路径中每个语义组件(类/关系)的所有大小进行算术求和。

例如,鉴于相机本体(http://protege.cim3.net/file/pub/ontologies/camera/camera.owl),其中一条路径为:Thing - PurchaseableItem - 镜头:其总和为(5 + 0.5 + 3 + 0.5 + 0)= 9.

1 个答案:

答案 0 :(得分:1)

假设这是建立在previous question关于构建问题中提到的路径类型的答案的基础上的,你可以使用:

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;
}

然后我们得到以下路径的总和。完整的代码遵循此输出。请注意,owl:Thing的大小为4,而不是5,正如您在问题中所给出的那样。如果想要计算一个类在rdfs:subClassOf的三元组中作为对象出现的次数,则在您链接到的OWL文件中只有四个形式为something rdfs:subClassOf owl:Thing的三元组,所以似乎它的大小应该是四,而不是五。考虑到这一点,请注意“Thing-PurchaseableItem-Lens”路径的重量为8,正如预期的那样(比你在问题中提到的少一个)。

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]

完整代码:

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 );
        }
    }
}