使用OWL API + Openllet获取数据断言公理的解释

后端开发 2026-07-09

我想要获取Openllet Reasoner做出推断的解释。

如果我尝试使用来自 这个 的代码,我会得到错误:未计算出解释。

当我尝试使用来自 这个问题 的答案中的代码示例时,出现错误——此阶段的值不能为null。

我尝试为下一个本体获取解释:

<?xml version="1.0"?>
<rdf:RDF xmlns="ontology://tasks/7c159bcc-b490-417a-9e0c-ea28bab98628#"
     xml:base="ontology://tasks/7c159bcc-b490-417a-9e0c-ea28bab98628"
     xmlns:owl="http://www.w3.org/2002/07/owl#"
     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:xml="http://www.w3.org/XML/1998/namespace"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
     xmlns:swrla="http://swrl.stanford.edu/ontologies/3.3/swrla.owl#"
     xmlns:base-ontology="http://www.semanticweb.org/user/ontologies/base-ontology#">
    <owl:Ontology rdf:about="ontology://tasks/7c159bcc-b490-417a-9e0c-ea28bab98628">
        <owl:imports rdf:resource="http://www.semanticweb.org/user/ontologies/base-ontology"/>
    </owl:Ontology>

    <!-- ontology://tasks/7c159bcc-b490-417a-9e0c-ea28bab98628#Cargo:737106ca-5efa-4035-875b-bf8fcc865754 -->

    <owl:NamedIndividual rdf:about="ontology://tasks/7c159bcc-b490-417a-9e0c-ea28bab98628#Cargo:737106ca-5efa-4035-875b-bf8fcc865754">
        <rdf:type rdf:resource="http://www.semanticweb.org/user/ontologies/base-ontology#Груз"/>
        <base-ontology:Weight rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">24</base-ontology:Weight>
        <base-ontology:Cargo_name>Cargo1</base-ontology:Cargo_name>
    </owl:NamedIndividual>

    <!-- ontology://tasks/7c159bcc-b490-417a-9e0c-ea28bab98628#Road:5b89f851-ee26-48d3-b480-be586ea9c9c2 -->

    <owl:NamedIndividual rdf:about="ontology://tasks/7c159bcc-b490-417a-9e0c-ea28bab98628#Road:5b89f851-ee26-48d3-b480-be586ea9c9c2">
        <rdf:type rdf:resource="http://www.semanticweb.org/user/ontologies/base-ontology#Road"/>
        <base-ontology:Road_length rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">33</base-ontology:Road_length>
        <base-ontology:Coating_wear>Medium</base-ontology:Coating_wear>
        <base-ontology:Coating_type>Asphalt</base-ontology:Coating_type>
    </owl:NamedIndividual>
</rdf:RDF>

在规则本体中,我有如下规则:Road(?r), Road_length(?r, ?l), swrlb:greaterThan(?l, 25) -> Safety_eval(?r, "low"),它把来自任务本体的公理导入到工作本体中。

解决方案

@UninformedUser,

完整代码:

@Service
public class ReasoningService {

    @Autowired
    private TaskRuleOrderRepository taskRuleRepo;
    @Autowired
    private TaskOntologyRepository taskRepo;
    @Autowired
    private UserTaskRoleRepository roleRepo;
    @Autowired
    private OntologyStorage ontologyStorage;

    @Transactional(readOnly = true)
    public ReasoningResult run(UUID userId, UUID taskOntologyId) throws UnsupportedOperationException, OWLException, IOException {
        taskRepo.findById(taskOntologyId)
            .orElseThrow(() -> new EntityNotFoundException("Task ontology not found"));

        roleRepo.findByIdUserIdAndIdTaskId(userId, taskOntologyId)
            .orElseThrow(() -> new AccessDeniedException("No access"));

        OWLOntology taskOntology = ontologyStorage.loadTaskOntology(taskOntologyId);

        List<TaskRuleOrder> ruleOntologies = taskRuleRepo.findByIdTaskIdOrderByOrderNumberAsc(taskOntologyId);

        if (ruleOntologies == null || ruleOntologies.isEmpty())
            throw new IllegalStateException("No rule ontologies assigned");

        OWLOntologyManager manager = taskOntology.getOWLOntologyManager();
        UUID workId = UUID.randomUUID();
        ontologyStorage.createTaskOntology(workId);
        OWLOntology workingOntology = ontologyStorage.loadTaskOntology(workId);
        manager.addAxioms(workingOntology, taskOntology.getAxioms());

        List<InferenceStep> steps = new ArrayList<>();

        for (TaskRuleOrder ruleOntologyOrder : ruleOntologies) {
            UUID ruleId = ruleOntologyOrder.getId().getRuleId();
            OWLOntology ruleOntology = ontologyStorage.loadRuleOntology(ruleId);

            InferenceStep step = applyRules(
                workingOntology,
                ruleOntology,
                ruleId
            );

            steps.add(step);
        }

        ontologyStorage.deleteTaskOntology(workId);

        return new ReasoningResult(taskOntologyId, steps);
    }

    private InferenceStep applyRules(OWLOntology workingOntology, OWLOntology ruleOntology, UUID ruleOntologyId) throws UnsupportedOperationException, OWLException, IOException {
        OWLOntologyManager manager = workingOntology.getOWLOntologyManager();

        Set<SWRLRule> rules = ruleOntology.getAxioms(AxiomType.SWRL_RULE);
        manager.addAxioms(workingOntology, rules);

        OpenlletReasonerFactory rf = OpenlletReasonerFactory.getInstance();
        OpenlletReasoner reasoner = rf.createReasoner(workingOntology);

        reasoner.getKB().realize();
        reasoner.precomputeInferences();

        Set<OWLAxiom> inferred = extractInferredAxioms(reasoner, workingOntology);
        List<String> explanations = new ArrayList<>();

        ExplanationGeneratorFactory<OWLAxiom> genFac = createExplanationGeneratorFactory(rf, null, OWLManager::createOWLOntologyManager);
        ExplanationGenerator<OWLAxiom> gen = genFac.createExplanationGenerator(inferred, null);

        for (OWLAxiom infer : inferred) {
            System.out.println("Inferred axiom: " + infer.toString());
            try {
                Set<Explanation<OWLAxiom>> explanation = gen.getExplanations(infer, 5);
                System.out.println("Explanation: " + explanation.toString());
                explanations.add(explanation.toString());
            } catch (Exception e) {
                System.out.println("ERROR IN EXPLANATION:");
                e.printStackTrace();
                System.out.println("END ERROR");
            }
        }

        manager.addAxioms(workingOntology, inferred);

        reasoner.flush();
        reasoner.dispose();

        workingOntology.removeAxioms(rules);

        return new InferenceStep(
            ruleOntologyId,
            inferred.stream().map(axiom -> axiom.toString()).toList(),
            explanations
        );
    }

    private Set<OWLAxiom> extractInferredAxioms(OpenlletReasoner reasoner, OWLOntology ontology) {

        OWLDataFactory factory = ontology.getOWLOntologyManager().getOWLDataFactory();

        Set<OWLAxiom> asserted = ontology.getABoxAxioms(Imports.INCLUDED);

        Set<OWLAxiom> inferred = new HashSet<>();

        for (OWLNamedIndividual individual : ontology.getIndividualsInSignature()) {

            NodeSet<OWLClass> types = reasoner.getTypes(individual, false);

            for (OWLClass cls : types.getFlattened()) {
                inferred.add(factory.getOWLClassAssertionAxiom(cls, individual));
            }

            for (OWLObjectProperty prop : ontology.objectPropertiesInSignature().toList()) {

                NodeSet<OWLNamedIndividual> values =
                    reasoner.getObjectPropertyValues(individual, prop);

                for (OWLNamedIndividual value : values.getFlattened()) {
                    inferred.add(factory.getOWLObjectPropertyAssertionAxiom(
                        prop, individual, value
                    ));
                }
            }

            for (OWLDataProperty prop : ontology.dataPropertiesInSignature().toList()) {

                Set<OWLLiteral> values =
                    reasoner.getDataPropertyValues(individual, prop);

                for (OWLLiteral val : values) {
                    inferred.add(factory.getOWLDataPropertyAssertionAxiom(
                        prop, individual, val
                    ));
                }
            }
        }
        inferred.removeAll(asserted);
        inferred.removeIf(ax ->
            ax.toString().contains("owl:Thing") ||
            ax.toString().contains("topDataProperty") ||
            ax.toString().contains("topObjectProperty")
        );
        return inferred;
    }

    public static ExplanationGeneratorFactory<OWLAxiom> createExplanationGeneratorFactory(
        OWLReasonerFactory reasonerFactory, ExplanationProgressMonitor<OWLAxiom> progressMonitor,
        Supplier<OWLOntologyManager> m) {
        EntailmentCheckerFactory<OWLAxiom> checker =
            new SatisfiabilityEntailmentCheckerFactory(reasonerFactory, m);
        Configuration<OWLAxiom> config = new Configuration<>(checker,
            new StructuralTypePriorityExpansionStrategy<OWLAxiom>(
                InitialEntailmentCheckStrategy.PERFORM, m),
            new DivideAndConquerContractionStrategy<OWLAxiom>(), progressMonitor, m);
        return new BlackBoxExplanationGeneratorFactory<>(config);
    }
}

堆栈跟踪:

java.lang.IllegalStateException: value cannot be null at this stage
at org.semanticweb.owlapi.util.OWLAPIPreconditions.verifyNotNull(OWLAPIPreconditions.java:56)
at org.semanticweb.owlapi.util.OWLAPIPreconditions.verifyNotNull(OWLAPIPreconditions.java:40)
at uk.ac.manchester.cs.owl.explanation.ordering.ExplanationOrdererImplNoManager$SeedExtractor.getTarget(ExplanationOrdererImplNoManager.java:309)
at uk.ac.manchester.cs.owl.explanation.ordering.ExplanationOrdererImplNoManager.getOrderedExplanation(ExplanationOrdererImplNoManager.java:174)
at org.semanticweb.owl.explanation.api.Explanation.toString(Explanation.java:149)
at java.base/java.lang.String.valueOf(Unknown Source)
at java.base/java.lang.StringBuilder.append(Unknown Source)
at java.base/java.util.AbstractCollection.toString(Unknown Source)
at com.logistic.ontologies.service.reasoning.ReasoningService.applyRules(ReasoningService.java:130)
at com.logistic.ontologies.service.reasoning.ReasoningService.run(ReasoningService.java:94)
2026-05-11 17:04:32


    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2026-05-11 17:04:32


    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章