Skip to content

gen-owl rules: deactivated rules emitted; enum values, value_presence, cardinality and has_member mistranslated in rule GCIs #43

Open

Description

@jdsika

What

owlgen translates each rule into a GCI, (pre and C) SubClassOf post (owlgen.py, add_class). On upstream main 5aa87ad it has five defects:

  1. deactivated: true is ignored: the output is isomorphic to that of the active rule.
  2. Enum values become literals. equals_string / equals_string_in on an enum-ranged slot becomes a literal DataOneOf, although the slot is an owl:ObjectProperty and the permissible values are IRIs (meaning, or the enum IRI plus the PV text). This happens in the default owl:Class and in owl:NamedIndividual PV mode. The literal path dates from fix(owlgen): enum range slots with none_of/all_of/any_of - equals_string linkml/linkml#3468.
  3. value_presence is ignored: ABSENT becomes some, i.e. presence.
  4. Cardinalities and has_member inside rule conditions are dropped. The filler falls back to default_range (xsd:string), even on object properties.
  5. Quantifiers are mixed: top-level conditions use some, while nested boolean operands use only, which holds vacuously when the slot is absent.

Reproduction

id: https://example.org/x
name: x
prefixes: {linkml: https://w3id.org/linkml/, ex: https://example.org/}
default_prefix: ex
default_range: string
imports: [linkml:types]
enums:
  Color: {permissible_values: {Red: {meaning: ex:Red}, Blue: {meaning: ex:Blue}}}
classes:
  T:
    attributes: {guard: {}, color: {range: Color}, tags: {multivalued: true}}
    rules:
      - preconditions: {slot_conditions: {guard: {value_presence: PRESENT}}}    # add deactivated: true -> same output
        postconditions: {slot_conditions: {color: {equals_string: Red}}}
      - preconditions: {slot_conditions: {guard: {value_presence: ABSENT}}}
        postconditions: {slot_conditions: {tags: {maximum_cardinality: 1}}}

gen-owl --no-metaclasses --no-type-objects schema.yaml gives:

  • First rule: (guard some xsd:string) and T SubClassOf color some DataOneOf("Red"). Here ex:color is an owl:ObjectProperty and ex:Color is unionOf(ex:Red ex:Blue).
  • Second rule: (guard some xsd:string) and T SubClassOf tags some xsd:string. The ABSENT precondition reads as presence, and the cardinality is gone.
  • Nested operands: with any_of: [{slot_conditions: {a: {equals_string_in: [x]}}}, ...] in the precondition, the operands become a only DataOneOf("x").

References

  • OWL 2 Structural Specification §8.2.1: ObjectSomeValuesFrom( ObjectPropertyExpression ClassExpression ). A data range (§7.4 DataOneOf) is not a class expression.
  • OWL 2 Direct Semantics §2.2: "ΔD is a nonempty set disjoint with ΔI".
  • Metamodel deactivated: "a deactivated rule is not executed by the rules engine".

Proposed fix

Acceptance criteria

  • Tests on the generated GCIs for each item, including both PV modes and nested operands.
  • A satisfiability check, where an OWL reasoner is available in CI.

Activity

  1. changed the title [-]gen-owl rules: deactivated rules emitted; equals_string on an enum with meaning rendered as a literal in the rule GCI[/-] [+]gen-owl rules: deactivated rules emitted; enum values, value_presence, cardinality and has_member mistranslated in rule GCIs[/+] on Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions