Repository navigation
fix(runtime): subsetting feature without a value holds values of the subsetted feature - #1512
Conversation
… into fix/subsetter-values-from-subsetted
…subsetted feature A subsetting feature stating no value of its own holds values of the feature it subsets where that feature holds values by its own declaration, as many as its lower bound asks (KerML 1.0 §7.3.4.4); a binding constraint on it picks the values its other end holds (§7.4.6). A subsetted feature holding fewer values than the bound asks is the multiplicity violation the read already reports, not objects made up. In ShapeItems::Box every binding of the faces' edges and vertices holds, vertices holds the faces' 24 vertices and size(vertices) == size(edges) holds. Co-Authored-By: jason.han <hanhuijun@gmail.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
…s; a subsetter follows writes A binding stating more than one link gives the subsetting feature as many of its other end's values as it links (bindingLinks, shared with CheckBindingOn). A binding an owner declares through the feature's path guides the nested subsetter as its own do, walking the owner chain as resolveBindings does, where its other end states a value of its own. The subsetter is listed as a dependent of every feature it draws from, so a write to one unmaterializes it and the next read draws from what the feature then holds. Co-Authored-By: jason.han <hanhuijun@gmail.com>
|
Second push, three movements in |
Co-Authored-By: jason.han <hanhuijun@gmail.com>
|
Third push, comments only: the four comments this branch added that ran to three to five lines ( |
Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/spec-compliance.md
|
Fourth push: a merge of #1508's current head |
…es-from-subsetted
…es-from-subsetted Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # internal/exec/runtime/testdata/conformance/instance_library_geometry_box.expected.json
|
Fifth push: a merge of develop |
What and why
A subsetting feature that states no value of its own — no
=, no default, no binding determining it whole — now holds values of the feature it subsets, as many as its lower bound asks, instead of objectsmaterializeIntrinsicValuemade up for the bound that the subsetted feature never held.In
ShapeItems::Cuboid,item tfe [2] :> edges;held twoStructuredCurveobjects of its own, none a value ofedges; everybinding [1] bind [0..1] tfe = [0..1] tf.edgesofBoxwas then violated (the ends shared no value),verticesheld 18 objects made up fortflv,tfrv, … where the faces hold 24, and the library's assertedsize(vertices) == size(edges)was violated. On the same readingitem two [2] :> edges;besideedges [6] = faces.esheld two objects outsideedges.materializeFromSubsetted(internal/exec/runtime/subsetting.go) runs before a required or binding-constrained subsetter is filled:subsettedPoolgathers the values the subsetted features hold by their own declaration (a value expression, a write or a binding-derived value), narrowed to the subsetter's types withcanClassify;bindingWitnessestakes, per binding on the subsetter — its own or one an owner declares through the feature's path, walking the owner chain asresolveBindingsdoes; an owner's binding counts only where its other end states a value of its own, since one that would itself draw from what it subsets (cf.edges = beinConeOrCylinder, withbe :> edges = faces.edges) has none to give yet — as many values as the binding links (bindingLinks, shared withCheckBindingOn);pickFromPoolfills the rest of the lower bound with pooled values no sibling subsetter holds yet (siblingSubsetterValues).faces [6]undertf : Rectangle :> faces) or holding only adefaultis no pool, so its subsetters keep making their own values and it keeps rolling them up; a feature with no declared subsetted feature is untouched.Context.drawingSubsetterskeeps a subsetter that is drawing its values out ofsubsettingContributionsof the feature it draws from, so the read it triggers does not recurse into it; the subsetter is listed as a dependent of every source it draws from (listRead), so a write to one unmaterializes it.Specification basis
Box's twelve edge subsetters hold twelve distinct edges and its eight vertex subsetters hold the faces' vertices the bindings name.Behaviour changes
ShapeItems::Box(package G { private import ShapeItems::*; item b : Box; }, develop → branch):b.tfetwo objects of its own → two values ofedges(b.tf.e1,b.ff.e1);b.tflvthree objects of its own → three values ofb.tf.vertices;b.vertices->size()18 → 24;b.edges->size()24 → 24;b.faces->size()6 → 6;b.subitems66 → 54 (develop: the 6 faces, their 24Rectangleedges, 18 made-upStructuredCurveand 18 made-upStructuredPoint; branch: the same faces and edges plus their 24 actual vertices);-validate=G::bbinding verdicts 38 reported, 0 held / 38 violated (six bindings with an empty end reached no verdict) → 44 reported, 44 held / 0 violated; the four asserted constraints ofBox(size(vertices) == size(edges)and the three face-pair constraints) all hold (before:size(vertices) == size(edges)violated). On develop before fix(runtime): read a binding linking some value of each end as a constraint #1508 the same reads were a binding-end error.ShapeItems::Cylinder:cyl.edges->size()2 → 2,cyl.betwoStructuredCurveobjects of its own → the two values ofedges(cyl.edges->includes(cyl.be#(1))false → true);cyl.ae[]→[].ShapeItems::Cone:cone.apex[]→[].part def Q { item coll : Node [4] = (x, y, z, w); item two [2] :> coll; }:q.coll->includes(q.two#(1))false → true,q.two#(1) == q.xfalse → true. The variant withcoll : Node [4]holding no declared value is unchanged:collhas no values of its own,twomakes two andcollrolls them up.binding_partial_collections_splitconformance:left [1] :> nodesandright [1] :> nodesbound[0..1] left = [0..1] rightnow share the node the binding links (left.1isright.1, verdict holds); before they held two objects of their own and the verdict was violated. The robustness case for ends sharing no value (TestRuntimeRobustnessPartialBinding) now uses two features that subset nothing, which is the model that case describes.binding [2] bind [0..2] picked = [0..2] lateonpicked [3] :> coll,late = (c, d)) gives the subsetter as many of the other end's values as it links (pickedholdsc,dand thena; the verdict holds).binding [1] bind [0..1] child.picked = [0..1] chosenbesidepart child : Childwithpicked [2] :> coll) guides the nested subsetter as its own bindings do:child.pickedholdschosen's value and then another ofcoll; the verdict holds.coll := (z, y)afterpick [1] :> collheldxmakespickholdz), as a reference subsetter follows its source.OccurrencesTest::p1.v2 → 2,new OccurrencesTest::P1().v2 → 2.Fixture, golden and sweep movement
internal/exec/runtime/testdata/conformance/instance_library_geometry_box.expected.json:box.vertices18 → 24 instances;box.tfe.1isbox.tf.e1andbox.tfe.2isbox.ff.e1(the two edgestfe's bindings name).box.subitems66 → 54 objects: the 18StructuredCurveand 18StructuredPointthe edge and vertex subsetters made up are gone and the faces' 24 actual vertices are in;subitems.7istf.e1and now alsotfe.1,subitems.11isurle.2,vertices.24issubitems.54.internal/exec/runtime/testdata/conformance/binding_partial_collections_split.expected.json:left.1/right.1distinct → identical, first verdict violated → holds (above).internal/exec/runtime/shape_items_limits_test.go:box.vertices18 → 24; thebox.tfe.lengtherror case is gone becausetfenow holdsRectangleedges, which have alength.docs/project/library-and-prefix-sweep-outcomes.txt(regenerated with-update-library-prefix-sweep), 16 rows:Probe::box.subitems66 → 54 objects as above; the twelveProbe::box.*eedge subsetters (bfe,bre,bsle,bsre,tfe,tre,tsle,tsre,ufle,ufre,urle,urre)StructuredCurve#1, #2of their own → twoRectangleedges (ShapeItems::Rectangle::e<n>objects) ofedges, those their bindings name;box.tfrv,box.trrvempty → threeStructuredPoints (the faces' vertices their bindings name);box.verticescollection(18) → collection(24). No other row moved.tests/corpus/testdata/training_examples_expected.txt: untouched.New pins:
conformance/subsetting_draws_from_subsetted.sysml+.expected.json,conformance/subsetting_binding_links.sysml+.expected.json,conformance/subsetting_binding_from_owner.sysml+.expected.json,robustness_subsetted_pool_test.go:TestRuntimeRobustnessSubsettedPool(under-populated collection; write to the collection), a row indocs/project/spec-compliance.md,changes/unreleased/subsetter-values-from-subsetted.fixed.md.Cost
Wall time of
sysml, three runs each, develop → branch:-instantiate=G::bonBox0.08/0.08/0.08 s → 0.08/0.10/0.10 s;-action L::countover a 10 000-iterationwhileloop 0.07/0.08/0.09 s → 0.08/0.07/0.08 s.How it was verified
go build ./...clean;go vet ./...clean;gofmt -l .empty;make lint✓ (staticcheck + gosec).go test ./...with the four corpora downloaded andOPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 OPENSYSML_REQUIRE_SPEC_EXAMPLES=1 OPENSYSML_REQUIRE_PILOT_LIBRARY_XMI=1: every package ok on the merged head exceptcmd/sysml, which hit its 10 min package timeout under the whole suite's load (as in earlier runs) and passes alone:ok cmd/sysml 237.009s,ok tests/codegen 267.350s(go test -count=1 -p 1).go test -count=1 -run 'TestExecutionConformance|TestHeldImage|TestKernelLibraryMembersReadableWhileRunning|TestRuntimeRobustness|TestShapeItems' ./internal/exec/runtime:ok 36.346s.go test -count=1 -run 'TestExecutionConformance|TestLibraryAndPrefixSweep|TestKernelLibraryMembersReadable|TestRuntimeRobustness|TestHeldImage' ./internal/exec/runtimeon the merged head:ok 40.791s.python3 scripts/changelog.py check✓;python3 scripts/check-doc-ids.py✓ ("No internal work-item labels in reader-facing documentation").Dry-merges:
origin/develop(cf6a6e2ba, which carries #1492, #1508 and #1515) is an ancestor of this branch (merged in as a merge commit; the one conflict,instance_library_geometry_box.expected.jsonbox.subitems, is re-recorded with this tree's reading, 54 objects, together with the sweep rowProbe::box.subitems).Checklist
make testandmake lintpass locallychanges/unreleased/<slug>.<section>.mdmake docs-countsrun if a gate movedF4,K5) in anything a user readsLink to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/51a37fedd9774deb9642040ed4e5a7f4
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/51a37fedd9774deb9642040ed4e5a7f4?variant=devin
Requested by: @HuiJun