Skip to content

EXTENDS validation with feasibility-pruned partition search#105

Open
ericprud wants to merge 2 commits into
linkml:masterfrom
ericprud:extends-validation
Open

EXTENDS validation with feasibility-pruned partition search#105
ericprud wants to merge 2 commits into
linkml:masterfrom
ericprud:extends-validation

Conversation

@ericprud

Copy link
Copy Markdown
Collaborator

What

Implements ShEx 2.1 EXTENDS / ABSTRACT / RESTRICTS evaluation, plus a feasibility layer that prunes the partition search.

  • satisfiesExtendedShape (p5_5): neighbourhood triples are allocated to the triple constraints of the extension targets (reached through references, AND/OR branches and extends chains). A constraint reached through several chains — diamond inheritance — allocates its triples to every one of them, so a triple cannot evade one chain's NOT by hiding in another. Extension targets are evaluated through ordinary satisfies() against their allocated part, so ShapeOr / ShapeAnd / ShapeNot parents work uniformly.
  • Node-scoped restriction stack: extension evaluation sees only its allocated part while value-expression recursion on other nodes sees the whole graph; the (node, shape) evaluation cache is bypassed under a restriction (the same pair can genuinely differ between parts — cf. shex.js's identical rule under subGraph).
  • satisfiesShapeDecl (p5_3): restricts are conjuncts; an abstract declaration is satisfied only through a non-abstract descendant (except when evaluated as an EXTENDS target); labeled shapes with registered extensions get the same descendant fallback. Handles both ShExJ 2.1 ShapeDecl and legacy inline-id flavours, and threads the declaration's id to ShapeExternal (2.1 moved labels onto the decl).
  • pyshex/utils/feasibility.py: a sound refutation test over partial bags of TripleConstraint matches — refutes structurally hopeless neighbourhoods (with Missing property reasons) before any partitioning, and pre-filters the 2^n EXTRA permutation loop. Ported from the same analysis implemented and proved for Apache Jena (jena-shex/docs/matching-search-optimization.md), rudof and shex.js.

shexSpec/shexTest validation manifest

schemas tests passed failed skipped (traits)
ShExJ 1182 1093 0 89
ShExC 1184 1091 0 93

Baseline could not run the current manifest at all (NotImplementedError on the first ShapeDecl).

Notes for review

🤖 Generated with Claude Code

Implements ShEx 2.1 EXTENDS/ABSTRACT/RESTRICTS evaluation:

- satisfiesExtendedShape: neighbourhood triples are allocated to the triple
  constraints of the extension targets (through references, AND/OR branches and
  extends chains); a constraint reached through several chains (diamond
  inheritance) allocates its triples to every one of them, so a triple cannot
  evade one chain's constraints by hiding in another. Extension targets are
  evaluated through ordinary satisfies() against their allocated part, so
  ShapeOr / ShapeAnd / ShapeNot parents work uniformly.
- Node-scoped restriction stack: extension evaluation sees only its allocated
  part while value-expression recursion on other nodes sees the whole graph;
  the (node, shape) evaluation cache is bypassed under a restriction (the same
  pair can genuinely differ between parts).
- satisfiesShapeDecl: restricts are conjuncts; an abstract declaration is
  satisfied only through a non-abstract descendant (except as an EXTENDS
  target); labeled shapes with registered extensions get the same descendant
  fallback. Handles both ShExJ 2.1 ShapeDecl and legacy inline-id flavours.
- pyshex/utils/feasibility.py: a sound refutation test over partial bags of
  TripleConstraint matches, used to prune hopeless neighbourhoods before
  partition enumeration and to pre-filter EXTRA permutations. Ported from the
  same analysis implemented for Apache Jena, rudof and shex.js.

shexSpec/shexTest validation manifest:
  ShExJ:  1182 tests = 1093 passed, 0 failed, 89 trait-skips
  ShExC:  1184 tests = 1091 passed, 0 failed, 93 trait-skips
  (baseline could not run: NotImplementedError on the first ShapeDecl)

pyshexc is temporarily sourced from the EXTENDS-grammar PR branch
(linkml/grammar-python-antlr-linkml#4); repoint to PyPI when released.
Requires tests/data/shexTest (git submodule) for the manifest tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tive IRIs

- SchemaLoader: IMPORT resolution (recursive merge, cycle-guarded, extensionless
  imports completed with .shex before redirect); relative IRIs parse against the
  schema's canonical location; ShExJ (JSON) input gets base absolutization
  (ObjectLiteral lexical values excluded).
- ShapeAssociation accepts blank node selectors.
- Test harness: preserve told bnode labels in rdflib parsing; sht:map JSON shape
  maps; canonical-space shape/focus/data-base alignment; empty skip_traits.
- shexTest data fix pushed to shexSpec/shexTest#69: stale start2RefS2.json.

shexTest validation manifest, zero trait-skips:
  ShExJ: 1182 = 1182 passed, 0 failed, 0 skips
  ShExC: 1184 = 1180 passed, 0 failed, 4 skips (schemas pyshexc cannot parse)
was: 1093/0/89 and 1091/0/93.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant