feat(migrate): run configurations, property-valued probabilities, draw policies and a result comparison harness - #383
Merged
Conversation
-draws / %draws resolve every uniform, uniformInteger, triangular and normal call at random from the seed, or at the call's min, max or average, threaded through the analysis questions, the engine wire and witnesses so replay: follows it. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ferences A «Probability» naming a numeric property visible from the activity is written as a reference the run reads at the decision, not folded to its default; the unmarked branch takes the dynamic remainder. Metadata bodies are type-checked so a feature-valued weight must be Real or Integer, and the runtime checks the declared distribution's range and sum when the decision is reached. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…stant ones Co-Authored-By: jason.han <hanhuijun@gmail.com>
…w policy Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ject already runs Co-Authored-By: jason.han <hanhuijun@gmail.com>
… initial Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ing the target's behavior Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…re each configuration's runs with them -migration-results writes the run configurations and their stored snapshots as a JSON sidecar; -compare-results runs each configuration on its target for its numberOfRuns under its durationSimulationMode and prints the tool's and OpenSysML's min, mean, p50, p90 and max per observable with the relative difference. An action's outcome now holds what the one object each of its parts denotes holds, as part.attribute, so a configuration's observables are read off its target; %runs takes no seed under a fixed draw policy. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…on the wire Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ults comparison Co-Authored-By: jason.han <hanhuijun@gmail.com>
…d result package Co-Authored-By: jason.han <hanhuijun@gmail.com>
The self-model, README and testing notes now state 104 bundled library files and ten OpenSysML extensions; the pilot-differential digest of examples/ is re-recorded for the self-model's new figure. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…car trailing content A metadata value must be model-level evaluable, except the weight Stochastic::Probability::p, which the run reads when its decision is reached; every other metadata feature, including p on another type, keeps the rule. ReadResults now requires the sidecar to hold exactly one JSON document and rejects a second document or trailing garbage. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ads it A subtype of Stochastic::Probability has no runtime reader, so its inherited p is judged model-level evaluable like any metadata value. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ion-configs The pilot-differential digest of examples/ is re-recorded for the merged tree; both sides had re-recorded it for their own self-model figures. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ion-configs The embedded library snapshot is regenerated for the merged bundled library. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…etadata body literal, fix normal(m, 0) under min and max A -compare-results configuration some runs of which failed is now a failing verdict with each error under the table, as a %runs table with a failed row is; the header still counts the completed runs the statistics are of. A metadata body value the model can evaluate is checked against the restated feature's scalar type like any other: @weight { p = "heavy"; } on a Real p is a type error. The DiagramLayout pass keeps judging constants of the right type that are no geometry (null, an odd pair). normal(mean, 0) draws nothing but mean, so min and max resolve it to mean as average does; a normal with sd > 0 stays unbounded under them. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…state needs no initial The exemption a parallel state's regions already had applies to the machine's top-level regions too: a bare `state idle;` beside a region with substates is a region standing in idle, not one missing its `entry; then <state>;`. The robustness case for a region without an initial now declares substates, since the bare state it used is a valid region. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…config branch Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ding it Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ted slots Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ion-configs Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/project/pilot-differential-baseline.json
An explicitly empty -compare-results= was indistinguishable from the flag's absence, so the model alone ran and the REPL opened; an empty -migration-results= silently wrote no sidecar. Both are usage errors now, beside the other empty-value checks. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ion-configs Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # README.md # cmd/sysml/check.go # cmd/sysml/convert.go # docs/internals/testing.md # docs/project/pilot-differential-baseline.json # docs/reference/grammar/README.md # examples/self-model/pipeline.sysml # internal/check/passes/typecheck_metadata_body.go # internal/check/passes/typecheck_metadata_body_test.go # internal/exec/runtime/action_results_parts_test.go # internal/exec/runtime/draw_policy.go # internal/exec/runtime/draw_policy_test.go # internal/exec/runtime/modeled.go # internal/exec/runtime/robustness_draw_policy_test.go # internal/exec/runtime/robustness_feature_weights_test.go # internal/exec/runtime/testdata/conformance/action_part_attributes_in_outcome.expected.json # internal/exec/runtime/testdata/conformance/action_part_attributes_in_outcome.sysml # internal/exec/runtime/testdata/conformance/action_perform_chain_joins_object_performance.expected.json # internal/exec/runtime/testdata/conformance/action_perform_chain_joins_object_performance.sysml # internal/exec/runtime/testdata/conformance/state_parallel_stateless_region.expected.json # internal/exec/runtime/testdata/conformance/state_parallel_stateless_region.sysml # internal/exec/runtime/testdata/conformance/state_parallel_stateless_region.trace.golden # internal/exec/runtime/testdata/conformance/state_parallel_stateless_region_with_behaviors.expected.json # internal/exec/runtime/testdata/conformance/state_parallel_stateless_region_with_behaviors.sysml # internal/exec/runtime/testdata/conformance/state_parallel_stateless_region_with_behaviors.trace.golden # internal/exec/runtime/testdata/conformance/state_parallel_stateless_top_region.expected.json # internal/exec/runtime/testdata/conformance/state_parallel_stateless_top_region.sysml # internal/exec/runtime/testdata/conformance/state_parallel_stateless_top_region.trace.golden # internal/exec/runtime/testdata/conformance/stochastic_draws_average.expected.json # internal/exec/runtime/testdata/conformance/stochastic_draws_average.sysml # internal/exec/runtime/testdata/conformance/stochastic_draws_max.expected.json # internal/exec/runtime/testdata/conformance/stochastic_draws_max.sysml # internal/exec/runtime/testdata/conformance/stochastic_draws_max.trace.golden # internal/exec/runtime/testdata/conformance/stochastic_draws_max_normal_unbounded.expected.json # internal/exec/runtime/testdata/conformance/stochastic_draws_max_normal_unbounded.sysml # internal/exec/runtime/testdata/conformance/stochastic_draws_min.expected.json # internal/exec/runtime/testdata/conformance/stochastic_draws_min.sysml # internal/exec/runtime/testdata/conformance/stochastic_weights_read_from_performer.expected.json # internal/exec/runtime/testdata/conformance/stochastic_weights_read_from_performer.sysml # internal/frontend/repl/compare.go # internal/frontend/repl/compare_test.go # internal/frontend/repl/draws_test.go # internal/frontend/repl/runs.go # internal/semantic/semantics/stochastic.go # internal/translate/convert/convert.go # internal/translate/migrate/migrate.go # internal/translate/migrate/results.go # internal/translate/migrate/simconfig.go # internal/workspace/libs/stdlib/OpenSysML Libraries/Simulation.sysml # tests/hygiene/layering_test.go
Both sides re-recorded the examples digest of the pilot differential baseline; it is re-derived over the merged tree. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…bservable Co-Authored-By: jason.han <hanhuijun@gmail.com>
… path only Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ts it by simple name A quoted unrestricted name may hold '::', so the sidecar name Cfg::'Sub::Group' ends in the one segment 'Sub::Group'; splitting the flat text on the last '::' made -action Sub::Group select nothing. The selector and the configuration's name are now read through the notation parser, segment by segment. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…at both ends uniform(lo, hi) draws on [lo, hi) at random, and max resolves it to hi: the bound the draws approach, as a v1 duration interval's tool reads its max mode. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…r, a general or a special of it A snapshot classified by a sibling special — sharing only a general with the target's classifier — is of a run on another kind of object, and a shared result package no longer mixes its snapshots into the configuration's results. The classifier test reads the conformance direction: the snapshot's classifier is among the target's classifiers and their generals, or its own generals reach one of the target's classifiers. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ion-configs Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # internal/ir/lower/state_graph.go # internal/translate/migrate/migrate.go
…ion-configs Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # cmd/sysml/usage.go # internal/frontend/repl/meta.go # man/man1/sysml.1
…aults Co-Authored-By: jason.han <hanhuijun@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
The SysML v1 migrator wrote a decision edge's «Probability» as a constant even when the tag names a property of the analysis block, so every migrated run drew a fixed tier mix instead of the one a Cameo run configuration sets; the
SimulationProfile:SimulationConfigelements themselves (run count, duration mode, time variable, execution target, result location) and the tool's stored result snapshots were reported unmapped, and nothing compared a migrated configuration's-runsdistribution with those snapshots.activity.go: probability()resolves a tag that names a property (by name or XMI id) visible from the activity or its context block to a feature reference,@Probability { p = ProbabilityBTOOP; }, so the object the behavior runs on decides the weights. Tags naming nothing visible, a private property, a non-property or a non-numeric one are report entries with the reason. Lowering type-checks a feature-valuedpagainstProbability::p, and the[0, 1]/ sum-to-one checks made of constants at lowering are made of the read values when the decision is reached, each anErrBranchWeights; guarded-out branches are filtered before the draw and the rest renormalised.runtime.DrawPolicy(random|min|max|average) states how everyRandomFunctionscall resolves —min/max/averageneed no seed,normalhas no finitemin/maxand returns a typed error naming the call. Threaded like the seed:-draws,%draws,%runs <n> [<seed>] <action>(seed optional under a fixed policy, still refused underrandom), analysis wire/JSON ("draws"), external and standing engines, gRPC, witnesses (draws by max) andreplay:compatibility. Weighted decisions stay seeded whatever the policy.simconfig.gowrites each configuration, recognised by its profile's provenance, as anaction defholding theexecutionTargetaspart targetandperform action run ::> target.<behavior>(inherited classifier behaviors resolved), annotated with the new non-normativeOpenSysML Libraries/Simulation.sysmlmetadata@Simulation::Configuration { runs; draws; timeVariable; startTime; stepSize; timeUnit; parallelForks }; every other setting is kept in a comment. Targets the migration did not write, non-part targets, state machines and classifiers with no behavior are reported with the reason.ActionExecutor.Results()also exposes<part>.<attribute>of the parts the action holds so the target's attributes are observable after the run.results.goindexes the tool's result-snapshot instances (classifier-less or typed) under each configuration'sresultLocation/result package into a JSON sidecar (-migration-results <file>), resolving observable names through defining features and inferring classifiers from slot owners. Snapshots in a shared result package whose configured feature values differ from what the target configures are excluded with a note rather than mixed in.sysml <migrated>.sysml -compare-results <sidecar> [-action ...] [-runs n] [-draws p] [-seed s] [-observe stored[=feature]...]runs each configuration with its recorded count and policy (or the ones given) and prints tool vs OpenSysML min/mean/p50/p90/max per observable with the relative difference; empty, non-numeric and unrun observables are reported, never dropped..xmi(SimulationProfile.xmi) is pinned as a profile, not the OMG XMI namespace, by tests ininternal/translate/xmiand itssysmlv1reader.internal/translate/simresults(standard library imports only), registered in thetranslatelayer oftests/hygiene/layering_test.go: it describes what the migration writes, andmigrate, the CLI and the REPL comparison read it through that layer; nopermittedortoleratedentry changed.examples/digest only, re-recorded for that figure.TMT proof (
TMT-2024x.mdzip)The +24 mapped / −24 approximated is 24 SimulationConfig classes (of 62, all approximated as plain classes before) and 6 decision nodes becoming mapped, against 6 unmarked control flows beside marked ones now reported approximated with the complementary weight they are given; no other report entry moves. The 38 remaining configurations are approximated with the reason (12 name no execution target, the classifier behavior of the target is written as a verification def rather than an action def,
treatAllClassifiersAsActive = false, …). The migrated file validates with 0 errors. 30 of the 62 configurations have stored snapshots (82 total).Acquire Target with IRIS and NFIRAOS - Logical, seed 1,Time_Acq_Total:For comparison, develop's migration of the same activity (fixed
p = 0.5) gives mean 133.31 s (30.86–315.42 s) at 100 runs. The Group 0 target class as saved in the model configures onlyProbabilityAcqPwfsSecond = 1.0; the four stored snapshots recording that configuration are the ones compared, and the nine others in the sharedResults::Group 0package (six recordingAcqTelPoint = BTOOP = ChkLaserProp = 1.0, mean 96.6 s, and three recordingAcqTTFOIWFS = 1.0) are excluded with a note as runs of another configuration. Under-draws max,Align BTO OP Logicalon its target is 90.2 s for every run (min9.2 s,average49.7 s).Known limitations
Acquire and Lock PWFS Logical, which is migrated by another change; it also makes the Group 0 configuration exceed the action-step budget under a fixed draw policy, so the deterministic-duration proof usesAlign BTO OP Logical.executionListeners,animationSpeed, UI options, …) are kept in a comment and are not executable.MonteCarloAnalysis::Mean, …) or holding a non-number is a note, not a value.Specification basis
SysML v2 v2.0 §7.16 (Actions: decision nodes and succession guards) for the weighted-successor semantics; the «Probability» tag,
SimulationConfig, result snapshots anddurationSimulationModeare MagicDraw/Cameo profile encodings with no OMG counterpart, migrated by provenance.docs/project/spec-compliance.mdgains rows for the draw policy and non-constant branch weights;docs/reference/sysml-v1-migration.mdgains the mapping rows and a "Run configurations" section.How it was verified
gofmt -l .(empty),go vet ./...,make lint,go build ./...,go test ./...(incl../tests/...) all pass locally.OPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 OPENSYSML_REQUIRE_PILOT_LIBRARY_XMI=1 go test -count=1 ./tests/corpus ./tests/identity -run 'TestTrainingExamples|TestPilotCorpora|TestPilotLibraryXMI|TestCorpusGates|TestCorpusRoundTrip'): 100/100 training clean, pilot ratchets unchanged, 9823 identities agree.make docs-check,python3 scripts/changelog.py check,python3 scripts/check-doc-ids.pypass.tests/migrate(testdata/xmi/simconfig.xmi) (property-valued probability, config → action def, min/max/random/average modes, result snapshots incl. classifier-less, nested packages, other-configuration exclusion, empty defaults); conformancestochastic_draws_{min,max,average},stochastic_draws_max_normal_unbounded,stochastic_weights_read_from_performer,action_part_attributes_in_outcome,action_perform_chain_joins_object_performance,state_parallel_stateless_region(+ trace goldens);robustness_draw_policy_test.go; REPL/CLI/analysis/gRPC/witness tests for-draws/%draws/replay;cmd/sysml/compare_test.gofor the harness;internal/translate/xminamespace tests;go test ./tests/...incl. the layering gate.Checklist
make testandmake lintpass locallychanges/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build)F4,K5) in the body, docs, or changelog